IDE: conditional compiler options: load/save

git-svn-id: trunk@17883 -
This commit is contained in:
mattias 2008-12-22 15:41:01 +00:00
parent c39f263237
commit 014229dcec
6 changed files with 499 additions and 258 deletions

View File

@ -37,7 +37,7 @@ uses
// LCL
InterfaceBase, LCLProc, Dialogs, FileUtil, Forms, Controls,
// codetools
BasicCodeTools, CodeToolManager, DefineTemplates,
ExprEval, BasicCodeTools, CodeToolManager, DefineTemplates,
// IDEIntf
SrcEditorIntf, ProjectIntf, MacroIntf, IDEDialogs, IDEExternToolIntf,
LazIDEIntf,
@ -205,6 +205,7 @@ begin
OnBackupFileInteractive:=@BackupFile;
RunCompilerWithOptions:=@OnRunCompilerWithOptions;
BuildModes:=TBuildModes.Create;
end;
destructor TBuildManager.Destroy;
@ -212,6 +213,7 @@ begin
LazConfMacroFunc:=nil;
OnBackupFileInteractive:=nil;
FreeAndNil(InputHistories);
FreeAndNil(BuildModes);
inherited Destroy;
MainBuildBoss:=nil;

View File

@ -41,16 +41,26 @@ unit CompilerOptions;
interface
uses
Classes, SysUtils, FileProcs, FileUtil, InterfaceBase, LCLProc, Forms, Controls,
Laz_XMLCfg, ProjectIntf, MacroIntf, IDEExternToolIntf, SrcEditorIntf,
IDEProcs, LazConf, TransferMacros
{$IFDEF EnableBuildModes}
,CompOptsModes
{$ENDIF}
;
Classes, SysUtils, FileProcs, FileUtil, InterfaceBase, LCLProc, Forms,
Controls, Laz_XMLCfg, ExprEval,
// IDEIntf
ProjectIntf, MacroIntf, IDEExternToolIntf, SrcEditorIntf,
// IDE
IDEProcs, LazConf, TransferMacros, CompOptsModes;
type
{ TBuildModes }
TBuildModes = class
private
FEvaluator: TExpressionEvaluator;
public
constructor Create;
destructor Destroy; override;
property Evaluator: TExpressionEvaluator read FEvaluator;
end;
{ TGlobalCompilerOptions - compiler options overrides }
TGlobalCompilerOptions = class
@ -102,7 +112,7 @@ type
pcosDebugPath // additional debug search path
);
TParsedCompilerOptStrings = set of TParsedCompilerOptString;
const
ParsedCompilerSearchPaths = [pcosUnitPath,pcosIncludePath,pcosObjectPath,
@ -127,6 +137,20 @@ const
'pcosCompilerPath',
'pcosDebugPath'
);
ParsedCompOptToConditional: array[TParsedCompilerOptString] of TCOCValueType = (
cocvtNone, // pcosNone
cocvtNone, // pcosBaseDir
cocvtUnitPath, // pcosUnitPath
cocvtIncludePath, // pcosIncludePath
cocvtObjectPath, // pcosObjectPath
cocvtLibraryPath, // pcosLibraryPath
cocvtSrcPath, // pcosSrcPath
cocvtLinkerOptions, // pcosLinkerOptions
cocvtCustomOptions, // pcosCustomOptions
cocvtNone, // pcosOutputDir
cocvtNone, // pcosCompilerPath
cocvtDebugPath // pcosDebugPath
);
InheritedToParsedCompilerOption: array[TInheritedCompilerOption] of
TParsedCompilerOptString = (
@ -161,6 +185,7 @@ type
TParsedCompilerOptions = class
private
FConditionals: TCompOptConditionals;
FGetWritableOutputDirectory: TGetWritableOutputDirectory;
FInvalidateParseOnChange: boolean;
FOnLocalSubstitute: TLocalSubstitutionEvent;
@ -174,7 +199,7 @@ type
ParsedPIValues: array[TParsedCompilerOptString] of string;
ParsedPIStamp: array[TParsedCompilerOptString] of integer;
ParsingPI: array[TParsedCompilerOptString] of boolean;
constructor Create;
constructor Create(TheConditionals: TCompOptConditionals);
function GetParsedValue(Option: TParsedCompilerOptString): string;
function GetParsedPIValue(Option: TParsedCompilerOptString): string;
procedure SetUnparsedValue(Option: TParsedCompilerOptString;
@ -193,6 +218,7 @@ type
write FInvalidateParseOnChange;
property GetWritableOutputDirectory: TGetWritableOutputDirectory
read FGetWritableOutputDirectory write FGetWritableOutputDirectory;
property Conditionals: TCompOptConditionals read FConditionals;
end;
TParseStringEvent =
@ -306,7 +332,8 @@ type
procedure SetDefaultMakeOptionsFlags(const AValue: TCompilerCmdLineOptions);
public
constructor Create(const AOwner: TObject); override;
constructor Create(const AOwner: TObject; const AToolClass: TCompilationToolClass);
constructor Create(const AOwner: TObject;
const AToolClass: TCompilationToolClass);
destructor Destroy; override;
procedure Clear; virtual;
@ -410,6 +437,7 @@ type
TAdditionalCompilerOptions = class
private
FBaseDirectory: string;
FConditionals: TCompOptConditionals;
FCustomOptions: string;
FIncludePath: string;
FLibraryPath: string;
@ -448,6 +476,7 @@ type
property CustomOptions: string read FCustomOptions write SetCustomOptions;
property BaseDirectory: string read FBaseDirectory write SetBaseDirectory;
property ParsedOpts: TParsedCompilerOptions read FParsedOpts;
property Conditionals: TCompOptConditionals read FConditionals;
end;
@ -455,7 +484,9 @@ type
TCompilerOptions = TBaseCompilerOptions;
var
BuildModes: TBuildModes;
const
CompileReasonNames: array[TCompileReason] of string = (
'Compile',
@ -781,7 +812,8 @@ constructor TBaseCompilerOptions.Create(const AOwner: TObject;
const AToolClass: TCompilationToolClass);
begin
inherited Create(AOwner);
FParsedOpts := TParsedCompilerOptions.Create;
FConditionals := TCompOptConditionals.Create(BuildModes.Evaluator);
FParsedOpts := TParsedCompilerOptions.Create(TCompOptConditionals(FConditionals));
FExecuteBefore := AToolClass.Create;
FExecuteAfter := AToolClass.Create;
FTargets := TFPList.Create;
@ -801,6 +833,7 @@ begin
FreeThenNil(fExecuteBefore);
FreeThenNil(fExecuteAfter);
FreeThenNil(FParsedOpts);
FreeThenNil(FConditionals); // free FConditionals before FParsedOpts
FreeThenNil(FTargets);
inherited Destroy;
end;
@ -1058,6 +1091,10 @@ begin
ObjectPath := sp(XMLConfigFile.GetValue(p+'ObjectPath/Value', ''));
SrcPath := sp(XMLConfigFile.GetValue(p+'SrcPath/Value', ''));
{ Conditionals }
TCompOptConditionals(FConditionals).LoadFromXMLConfig(XMLConfigFile,
Path+'Conditionals/',PathDelimChanged);
{ Parsing }
p:=Path+'Parsing/';
AssemblerStyle := XMLConfigFile.GetValue(p+'Style/Value', 0);
@ -1230,6 +1267,10 @@ begin
XMLConfigFile.SetDeleteValue(p+'ObjectPath/Value', ObjectPath,'');
XMLConfigFile.SetDeleteValue(p+'SrcPath/Value', SrcPath,'');
{ Conditionals }
TCompOptConditionals(FConditionals).SaveToXMLConfig(XMLConfigFile,
Path+'Conditionals/');
{ Parsing }
p:=Path+'Parsing/';
XMLConfigFile.SetDeleteValue(p+'Style/Value', AssemblerStyle,0);
@ -2789,13 +2830,15 @@ end;
constructor TAdditionalCompilerOptions.Create(TheOwner: TObject);
begin
fOwner:=TheOwner;
FParsedOpts:=TParsedCompilerOptions.Create;
FConditionals:=TCompOptConditionals.Create(BuildModes.Evaluator);
FParsedOpts:=TParsedCompilerOptions.Create(FConditionals);
Clear;
end;
destructor TAdditionalCompilerOptions.Destroy;
begin
FreeThenNil(FParsedOpts);
FreeThenNil(FConditionals);// free conditionals before FParsedOpts
inherited Destroy;
end;
@ -2825,6 +2868,7 @@ begin
LinkerOptions:=f(XMLConfig.GetValue(Path+'LinkerOptions/Value',''));
ObjectPath:=f(XMLConfig.GetValue(Path+'ObjectPath/Value',''));
UnitPath:=f(XMLConfig.GetValue(Path+'UnitPath/Value',''));
FConditionals.LoadFromXMLConfig(XMLConfig,Path+'Conditionals/',AdjustPathDelims);
end;
procedure TAdditionalCompilerOptions.SaveToXMLConfig(XMLConfig: TXMLConfig;
@ -2836,6 +2880,7 @@ begin
XMLConfig.SetDeleteValue(Path+'LinkerOptions/Value',fLinkerOptions,'');
XMLConfig.SetDeleteValue(Path+'ObjectPath/Value',FObjectPath,'');
XMLConfig.SetDeleteValue(Path+'UnitPath/Value',FUnitPath,'');
FConditionals.SaveToXMLConfig(XMLConfig,Path+'Conditionals/');
end;
function TAdditionalCompilerOptions.GetOwnerName: string;
@ -2865,8 +2910,9 @@ end;
{ TParsedCompilerOptions }
constructor TParsedCompilerOptions.Create;
constructor TParsedCompilerOptions.Create(TheConditionals: TCompOptConditionals);
begin
FConditionals:=TheConditionals;
Clear;
end;
@ -2940,8 +2986,29 @@ function TParsedCompilerOptions.DoParseOption(const OptionText: string;
var
s: String;
BaseDirectory: String;
cocOption: TCOCValueType;
h: string;
begin
s:=OptionText;
// add conditional additions
if Conditionals<>nil then begin
cocOption:=ParsedCompOptToConditional[Option];
case Option of
pcosUnitPath,pcosSrcPath,pcosIncludePath,pcosObjectPath,pcosLibraryPath,
pcosDebugPath:
// add search path
s:=MergeSearchPaths(s,FConditionals.Values[cocOption]);
pcosLinkerOptions,pcosCustomOptions:
begin
// add command line option
h:=FConditionals.Values[cocOption];
if (h<>'') then begin
if s<>'' then s:=s+' ';
s:=s+h;
end;
end;
end;
end;
// parse locally
if Assigned(OnLocalSubstitute) then
s:=OnLocalSubstitute(s,PlatformIndependent);
@ -3230,6 +3297,19 @@ begin
AddDiffItem(PropertyName,s);
end;
{ TBuildModes }
constructor TBuildModes.Create;
begin
FEvaluator:=TExpressionEvaluator.Create;
end;
destructor TBuildModes.Destroy;
begin
FreeAndNil(FEvaluator);
inherited Destroy;
end;
initialization
CompilerParseStamp:=1;
CompilerParseStampIncreased:=nil;

View File

@ -38,251 +38,43 @@ unit CompOptsModes;
interface
uses
Classes, SysUtils, Laz_XMLCfg, ExprEval;
Classes, SysUtils, Laz_XMLCfg, ExprEval,
IDEProcs, ProjectIntf;
type
TCOCNodeType = (
cocntNone,
cocntIf,
cocntIfdef,
cocntIfNdef,
cocntElseIf,
cocntElse,
cocntEndIf,
cocntAddValue
);
TCOCNodeTypes = set of TCOCNodeType;
TCOCValueType = (
cocvtNone,
cocvtUnitPath,
cocvtSrcPath,
cocvtIncPath,
cocvtObjectPath,
cocvtLibraryPath,
cocvtLinkerOptions,
cocvtCustomOptions
);
TCOCValueTypes = set of TCOCValueType;
const
COCNodeTypeNames: array[TCOCNodeType] of string = (
'None',
'If',
'Ifdef',
'IfNdef',
'ElseIf',
'Else',
'EndIf',
'AddValue'
);
COCValueTypeNames: array[TCOCValueType] of string = (
'None',
'UnitPath',
'SrcPath',
'IncPath',
'ObjectPath',
'LibraryPath',
'LinkerOptions',
'CustomOptions'
);
type
TCompOptConditionals = class;
{ TCompOptCondNode }
TCompOptCondNode = class
private
FCount: integer;
fClearing: Boolean;
FFirstChild: TCompOptCondNode;
FLastChild: TCompOptCondNode;
FNextSibling: TCompOptCondNode;
FNodeType: TCOCNodeType;
FOwner: TCompOptConditionals;
FParent: TCompOptCondNode;
FPrevSibling: TCompOptCondNode;
FValue: string;
FValueType: TCOCValueType;
procedure SetNodeType(const AValue: TCOCNodeType);
procedure SetValue(const AValue: string);
procedure SetValueType(const AValue: TCOCValueType);
procedure Changed;
procedure Unbind;
public
constructor Create(TheOwner: TCompOptConditionals);
destructor Destroy; override;
procedure Clear;
procedure AddLast(Child: TCompOptCondNode);
procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string;
DoSwitchPathDelims: boolean); virtual;
procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string); virtual;
property NodeType: TCOCNodeType read FNodeType write SetNodeType;
property ValueType: TCOCValueType read FValueType write SetValueType;
property Value: string read FValue write SetValue;
property Owner: TCompOptConditionals read FOwner;
property Parent: TCompOptCondNode read FParent;
property Count: integer read FCount;
property FirstChild: TCompOptCondNode read FFirstChild;
property LastChild: TCompOptCondNode read FLastChild;
property NextSibling: TCompOptCondNode read FNextSibling;
property PrevSibling: TCompOptCondNode read FPrevSibling;
end;
{ TCompOptConditionals }
TCompOptConditionals = class
TCompOptConditionals = class(TLazCompOptConditionals)
private
FChangeStamp: integer;
FErrorMsg: string;
FErrorNode: TCompOptCondNode;
FEvaluator: TExpressionEvaluator;
FRoot: TCompOptCondNode;
FEvaluatorStamp: integer;
FValuesValid: boolean;
FValues: array[TCOCValueType] of string;
function GetValues(const ValueType: TCOCValueType): string;
procedure SetEvaluator(const AValue: TExpressionEvaluator);
procedure AddValue(const ValueType: TCOCValueType; Value: string);
public
constructor Create;
constructor Create(TheEvaluator: TExpressionEvaluator);
destructor Destroy; override;
procedure Clear;
procedure InvalidateValues;
procedure ClearNodes;
procedure InvalidateValues; override;
procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string;
DoSwitchPathDelims: boolean); virtual;
procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string); virtual;
property Values[ValueType: TCOCValueType]: string read GetValues;
property Evaluator: TExpressionEvaluator read FEvaluator write SetEvaluator;
property ChangeStamp: integer read FChangeStamp;
property Root: TCompOptCondNode read FRoot;
procedure IncreaseChangeStamp; inline;
property ErrorNode: TCompOptCondNode read FErrorNode write FErrorNode;
property ErrorMsg: string read FErrorMsg write FErrorMsg;
end;
function COCNodeTypeNameToType(const s: string): TCOCNodeType;
function COCValueTypeNameToType(const s: string): TCOCValueType;
implementation
function COCNodeTypeNameToType(const s: string): TCOCNodeType;
begin
for Result:=Low(TCOCNodeType) to High(TCOCNodeType) do
if SysUtils.CompareText(s,COCNodeTypeNames[Result])=0 then exit;
Result:=cocntNone;
end;
function COCValueTypeNameToType(const s: string): TCOCValueType;
begin
for Result:=Low(TCOCValueType) to High(TCOCValueType) do
if SysUtils.CompareText(s,COCValueTypeNames[Result])=0 then exit;
Result:=cocvtNone;
end;
{ TCompOptCondNode }
procedure TCompOptCondNode.SetNodeType(const AValue: TCOCNodeType);
begin
if FNodeType=AValue then exit;
FNodeType:=AValue;
Changed;
end;
procedure TCompOptCondNode.SetValue(const AValue: string);
begin
if FValue=AValue then exit;
FValue:=AValue;
Changed;
end;
procedure TCompOptCondNode.SetValueType(const AValue: TCOCValueType);
begin
if FValueType=AValue then exit;
FValueType:=AValue;
Changed;
end;
procedure TCompOptCondNode.Changed;
begin
if FOwner<>nil then FOwner.InvalidateValues;
end;
procedure TCompOptCondNode.Unbind;
begin
if FParent<>nil then begin
if FParent.FFirstChild=Self then FParent.FFirstChild:=FNextSibling;
if FParent.FLastChild=Self then FParent.FLastChild:=FPrevSibling;
dec(FParent.FCount);
FParent:=nil;
end;
if FNextSibling<>nil then FNextSibling.FPrevSibling:=FPrevSibling;
if FPrevSibling<>nil then FPrevSibling.FNextSibling:=FNextSibling;
FNextSibling:=nil;
FPrevSibling:=nil;
end;
constructor TCompOptCondNode.Create(TheOwner: TCompOptConditionals);
begin
FOwner:=TheOwner;
end;
destructor TCompOptCondNode.Destroy;
begin
Clear;
Unbind;
inherited Destroy;
end;
procedure TCompOptCondNode.Clear;
begin
fClearing:=true;
while FFirstChild<>nil do
FFirstChild.Free;
fClearing:=false;
end;
procedure TCompOptCondNode.AddLast(Child: TCompOptCondNode);
begin
Child.Unbind;
Child.fPrevSibling:=FLastChild;
FLastChild.FNextSibling:=Child;
if FFirstChild=nil then
FFirstChild:=Child;
FLastChild:=Child;
inc(FCount);
Child.FParent:=Self;
end;
procedure TCompOptCondNode.LoadFromXMLConfig(XMLConfig: TXMLConfig;
const Path: string; DoSwitchPathDelims: boolean);
var
NewCount: LongInt;
i: Integer;
NewChild: TCompOptCondNode;
begin
Clear;
FNodeType:=COCNodeTypeNameToType(XMLConfig.GetValue(Path+'NodeType',''));
FValueType:=COCValueTypeNameToType(XMLConfig.GetValue(Path+'ValueType',''));
FValue:=XMLConfig.GetValue(Path+'Value','');
NewCount:=XMLConfig.GetValue(Path+'ChildCount',0);
for i:=0 to NewCount-1 do begin
NewChild:=TCompOptCondNode.Create(Owner);
AddLast(NewChild);
NewChild.LoadFromXMLConfig(XMLConfig,Path+'Item'+IntToStr(i)+'/',
DoSwitchPathDelims);
end;
end;
procedure TCompOptCondNode.SaveToXMLConfig(XMLConfig: TXMLConfig;
const Path: string);
begin
XMLConfig.SetDeleteValue(Path+'NodeType',COCNodeTypeNames[NodeType],
COCNodeTypeNames[cocntNone]);
XMLConfig.SetDeleteValue(Path+'ValueType',COCValueTypeNames[ValueType],
COCValueTypeNames[cocvtNone]);
XMLConfig.SetDeleteValue(Path+'Value',Value,'');
XMLConfig.SetDeleteValue(Path+'ChildCount',Count,0);
// ToDo
end;
{ TCompOptConditionals }
function TCompOptConditionals.GetValues(const ValueType: TCOCValueType): string;
@ -298,6 +90,7 @@ function TCompOptConditionals.GetValues(const ValueType: TCOCValueType): string;
ResultStr:=FEvaluator.Eval(Node.Value);
if FEvaluator.ErrorPosition>=0 then begin
FErrorNode:=Node;
FErrorMsg:='error in expression at column '+IntToStr(FEvaluator.ErrorPosition);
exit(false);
end;
ExprResult:=ResultStr<>'0';
@ -307,30 +100,65 @@ function TCompOptConditionals.GetValues(const ValueType: TCOCValueType): string;
cocntIfNdef:
ExprResult:=not FEvaluator.IsDefined(Node.Value);
else
FErrorNode:=Node;
FErrorMsg:='unexpected node of type '+COCNodeTypeNames[Node.NodeType];
exit(false);
end;
Result:=true;
end;
function ComputeNode(Node: TCompOptCondNode): boolean;
function ComputeNode(ParentNode: TCompOptCondNode; Index: integer): boolean;
var
ExprResult: boolean;
Node: TCompOptCondNode;
begin
Result:=false;
case Node.NodeType of
cocntIf,cocntIfdef,cocntIfNdef:
begin
if not ComputeIfNode(Node,ExprResult) then exit;
if ExprResult then begin
if Node.FirstChild<>nil then
if not ComputeNode(Node.FirstChild) then exit;
// skip till EndIf
end else begin
while Index<ParentNode.Count do begin
Node:=ParentNode.Childs[Index];
case Node.NodeType of
cocntIf,cocntIfdef,cocntIfNdef:
while true do begin
if (Node.NodeType=cocntElse) then
ExprResult:=true
else if (not ComputeIfNode(Node,ExprResult)) then
exit;
if ExprResult then begin
// execute childs
if Node.Count>0 then
if not ComputeNode(Node,0) then exit;
// skip all else
inc(Index);
while (Index<ParentNode.Count) do begin
Node:=ParentNode.Childs[Index];
if not (Node.NodeType in [cocntElseIf,cocntElse]) then break;
if ParentNode.Childs[Index-1].NodeType=cocntElse then begin
FErrorNode:=Node;
FErrorMsg:='ElseIf not allowed after Else';
exit(false);
end;
inc(Index);
end;
break;
end else begin
// skip childs
inc(Index);
end;
if Index>=ParentNode.Count then break;
Node:=ParentNode.Childs[Index];
end;
end;
cocntAddValue:
begin
AddValue(Node.ValueType,Node.Value);
inc(Index);
end;
else
fErrorNode:=Node;
FErrorMsg:='unexpected node of type '+COCNodeTypeNames[Node.NodeType];
exit(false);
end;
end;
Result:=true;
end;
@ -338,11 +166,15 @@ function TCompOptConditionals.GetValues(const ValueType: TCOCValueType): string;
var
v: TCOCValueType;
begin
if FEvaluator=nil then begin
Result:='';
exit;
end;
if (not FValuesValid)
or (FEvaluator.ChangeStamp<>FEvaluatorStamp) then begin
for v:=Low(FValues) to High(FValues) do
FValues[v]:='';
ComputeNode(Root);
ComputeNode(Root,0);
FValuesValid:=true;
FEvaluatorStamp:=FEvaluator.ChangeStamp;
end;
@ -357,9 +189,31 @@ begin
InvalidateValues;
end;
constructor TCompOptConditionals.Create;
procedure TCompOptConditionals.AddValue(const ValueType: TCOCValueType;
Value: string);
begin
Value:=Trim(Value);
if Value='' then exit;
case ValueType of
cocvtNone: ; // ignore
cocvtUnitPath,cocvtSrcPath,cocvtIncludePath,cocvtObjectPath,cocvtLibraryPath,
cocvtDebugPath:
begin
FValues[ValueType]:=MergeSearchPaths(FValues[ValueType],Value);
end;
cocvtLinkerOptions,cocvtCustomOptions:
begin
if FValues[ValueType]<>'' then
FValues[ValueType]:=FValues[ValueType]+' ';
FValues[ValueType]:=FValues[ValueType]+Value;
end;
end;
end;
constructor TCompOptConditionals.Create(TheEvaluator: TExpressionEvaluator);
begin
FEvaluator:=TheEvaluator;
inherited Create;
end;
destructor TCompOptConditionals.Destroy;
@ -370,26 +224,73 @@ end;
procedure TCompOptConditionals.Clear;
begin
ClearNodes;
end;
procedure TCompOptConditionals.ClearNodes;
begin
FValuesValid:=false;
FErrorNode:=nil;
FreeAndNil(FRoot);
FErrorMsg:='';
Root.ClearNodes;
end;
procedure TCompOptConditionals.InvalidateValues;
begin
FValuesValid:=false;
FErrorNode:=nil;
FErrorMsg:='';
end;
procedure TCompOptConditionals.LoadFromXMLConfig(XMLConfig: TXMLConfig;
const Path: string; DoSwitchPathDelims: boolean);
begin
procedure LoadNode(Node: TCompOptCondNode; const SubPath: string);
var
NewCount: LongInt;
i: Integer;
NewChild: TCompOptCondNode;
begin
Node.ClearNodes;
Node.NodeType:=COCNodeTypeNameToType(XMLConfig.GetValue(SubPath+'NodeType',''));
Node.ValueType:=COCValueTypeNameToType(XMLConfig.GetValue(SubPath+'ValueType',''));
Node.Value:=XMLConfig.GetValue(SubPath+'Value','');
// load childs
NewCount:=XMLConfig.GetValue(SubPath+'ChildCount',0);
for i:=1 to NewCount do begin
NewChild:=TCompOptCondNode.Create(Node.Owner);
Node.AddLast(NewChild);
LoadNode(NewChild,SubPath+'Item'+IntToStr(i)+'/');
end;
end;
begin
LoadNode(Root,Path);
Root.NodeType:=cocntNone;
Root.ValueType:=cocvtNone;
Root.Value:='';
end;
procedure TCompOptConditionals.SaveToXMLConfig(XMLConfig: TXMLConfig;
const Path: string);
begin
procedure SaveNode(Node: TCompOptCondNode; const SubPath: string);
var
i: Integer;
begin
XMLConfig.SetDeleteValue(SubPath+'NodeType',COCNodeTypeNames[Node.NodeType],
COCNodeTypeNames[cocntNone]);
XMLConfig.SetDeleteValue(SubPath+'ValueType',COCValueTypeNames[Node.ValueType],
COCValueTypeNames[cocvtNone]);
XMLConfig.SetDeleteValue(SubPath+'Value',Node.Value,'');
// save childs
XMLConfig.SetDeleteValue(SubPath+'ChildCount',Node.Count,0);
for i:=0 to Node.Count-1 do
SaveNode(Node.Childs[i],SubPath+'Item'+IntToStr(i+1)+'/');
end;
begin
SaveNode(Root,Path);
end;
procedure TCompOptConditionals.IncreaseChangeStamp; inline;

View File

@ -1,4 +1,36 @@
unit frmcustomapplicationoptions;
{
/***************************************************************************
project.pp - project utility class file
-----------------------------------------
TProject is responsible for managing a complete project.
Initial Revision : Sun Mar 28 23:15:32 CST 1999
***************************************************************************/
***************************************************************************
* *
* This source is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This code is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* A copy of the GNU General Public License is available on the World *
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
* obtain it by writing to the Free Software Foundation, *
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
***************************************************************************
}
unit frmCustomApplicationOptions;
{$mode objfpc}{$H+}
@ -6,7 +38,8 @@ interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls,
ExtCtrls, Buttons, LazarusIDEStrConsts;
ExtCtrls, Buttons,
LazarusIDEStrConsts;
type

View File

@ -49,15 +49,15 @@ uses
MemCheck,
{$ENDIF}
Classes, SysUtils, TypInfo, FPCAdds, LCLProc, LCLIntf, LCLType, Forms,
Controls, Dialogs, Laz_XMLCfg, LazConf, FileUtil,
Controls, Dialogs,
Laz_XMLCfg, ExprEval, FileUtil, DefineTemplates, CodeToolManager, CodeCache,
// IDEIntf
PropEdits, ProjectIntf, MacroIntf, LazIDEIntf,
ProjectResources,
// IDE
frmcustomapplicationoptions,
LazarusIDEStrConsts, CompilerOptions, CodeToolManager, CodeCache,
CompOptsModes, ProjectResources, LazConf, frmCustomApplicationOptions,
LazarusIDEStrConsts, CompilerOptions,
TransferMacros, EditorOptions, IDEProcs, RunParamsOpts, ProjectDefs,
FileReferenceList, EditDefineTree, DefineTemplates, PackageDefs;
FileReferenceList, EditDefineTree, PackageDefs;
type
TUnitInfo = class;
@ -4773,7 +4773,7 @@ end;
destructor TProjectCompilerOptions.Destroy;
begin
inherited Destroy;
FGlobals.Free;
FreeAndNil(FGlobals);
end;
function TProjectCompilerOptions.GetOwnerName: string;

View File

@ -45,6 +45,100 @@ const
ProjDescNameEmpty = 'Empty';
type
TCOCNodeType = (
cocntNone,
cocntIf,
cocntIfdef,
cocntIfNdef,
cocntElseIf,
cocntElse,
cocntAddValue
);
TCOCNodeTypes = set of TCOCNodeType;
TCOCValueType = (
cocvtNone,
cocvtUnitPath,
cocvtSrcPath,
cocvtIncludePath,
cocvtObjectPath,
cocvtLibraryPath,
cocvtDebugPath,
cocvtLinkerOptions,
cocvtCustomOptions
);
TCOCValueTypes = set of TCOCValueType;
const
COCNodeTypeNames: array[TCOCNodeType] of string = (
'None',
'If',
'Ifdef',
'IfNdef',
'ElseIf',
'Else',
'AddValue'
);
COCValueTypeNames: array[TCOCValueType] of string = (
'None',
'UnitPath',
'SrcPath',
'IncludePath',
'ObjectPath',
'LibraryPath',
'DebugPath',
'LinkerOptions',
'CustomOptions'
);
type
TLazCompOptConditionals = class;
{ TCompOptCondNode }
TCompOptCondNode = class
private
fChilds: TFPList; // list of TCompOptCondNode
fClearing: boolean;
FNodeType: TCOCNodeType;
FOwner: TLazCompOptConditionals;
FParent: TCompOptCondNode;
FValue: string;
FValueType: TCOCValueType;
function GetChilds(Index: integer): TCompOptCondNode;
function GetCount: integer;
procedure SetNodeType(const AValue: TCOCNodeType);
procedure SetValue(const AValue: string);
procedure SetValueType(const AValue: TCOCValueType);
procedure Changed;
public
constructor Create(TheOwner: TLazCompOptConditionals);
destructor Destroy; override;
procedure ClearNodes;
procedure AddLast(Child: TCompOptCondNode);
procedure Insert(Index: integer; Child: TCompOptCondNode);
procedure Move(OldIndex, NewIndex: integer);
procedure Delete(Index: integer);
property NodeType: TCOCNodeType read FNodeType write SetNodeType;
property ValueType: TCOCValueType read FValueType write SetValueType;
property Value: string read FValue write SetValue;
property Owner: TLazCompOptConditionals read FOwner;
property Parent: TCompOptCondNode read FParent;
property Count: integer read GetCount;
property Childs[Index: integer]: TCompOptCondNode read GetChilds;
end;
{ TLazCompOptConditionals }
TLazCompOptConditionals = class
private
FRoot: TCompOptCondNode;
public
constructor Create;
destructor Destroy; override;
procedure InvalidateValues; virtual; abstract;
property Root: TCompOptCondNode read FRoot write FRoot;
end;
{ TLazCompilerOptions }
TCompilationExecutableType = (
@ -79,6 +173,9 @@ type
FSrcPath: string;
fUnitOutputDir: string;
fDebugPath: string;
// conditionals / build modes
FConditionals: TLazCompOptConditionals;
fLCLWidgetType: string;
// Parsing:
@ -184,8 +281,12 @@ type
property OtherUnitFiles: String read fUnitPaths write SetUnitPaths;
property ObjectPath: string read FObjectPath write SetObjectPath;
property SrcPath: string read FSrcPath write SetSrcPath;
property UnitOutputDirectory: string read fUnitOutputDir write SetUnitOutputDir;
property DebugPath: string read FDebugPath write SetDebugPath;
property UnitOutputDirectory: string read fUnitOutputDir write SetUnitOutputDir;
// conditional / build modes
property Conditionals: TLazCompOptConditionals read FConditionals;
// Beware: eventually LCLWidgetType will be replaced by a more generic solution
property LCLWidgetType: string read fLCLWidgetType write fLCLWidgetType;
// parsing:
@ -676,6 +777,8 @@ function ProjectFlagsToStr(Flags: TProjectFlags): string;
function StrToProjectSessionStorage(const s: string): TProjectSessionStorage;
function CompilationExecutableTypeNameToType(const s: string
): TCompilationExecutableType;
function COCNodeTypeNameToType(const s: string): TCOCNodeType;
function COCValueTypeNameToType(const s: string): TCOCValueType;
procedure RegisterProjectFileDescriptor(FileDesc: TProjectFileDescriptor);
procedure RegisterProjectDescriptor(ProjDesc: TProjectDescriptor);
@ -691,6 +794,19 @@ procedure RegisterProjectDescriptor(ProjDesc: TProjectDescriptor;
implementation
function COCNodeTypeNameToType(const s: string): TCOCNodeType;
begin
for Result:=Low(TCOCNodeType) to High(TCOCNodeType) do
if SysUtils.CompareText(s,COCNodeTypeNames[Result])=0 then exit;
Result:=cocntNone;
end;
function COCValueTypeNameToType(const s: string): TCOCValueType;
begin
for Result:=Low(TCOCValueType) to High(TCOCValueType) do
if SysUtils.CompareText(s,COCValueTypeNames[Result])=0 then exit;
Result:=cocvtNone;
end;
procedure RegisterProjectFileDescriptor(FileDesc: TProjectFileDescriptor);
begin
@ -809,6 +925,102 @@ begin
Result:=cetProgram;
end;
{ TCompOptCondNode }
procedure TCompOptCondNode.SetNodeType(const AValue: TCOCNodeType);
begin
if FNodeType=AValue then exit;
FNodeType:=AValue;
Changed;
end;
function TCompOptCondNode.GetChilds(Index: integer): TCompOptCondNode;
begin
Result:=TCompOptCondNode(fChilds[Index]);
end;
function TCompOptCondNode.GetCount: integer;
begin
Result:=fChilds.Count;
end;
procedure TCompOptCondNode.SetValue(const AValue: string);
begin
if FValue=AValue then exit;
FValue:=AValue;
Changed;
end;
procedure TCompOptCondNode.SetValueType(const AValue: TCOCValueType);
begin
if FValueType=AValue then exit;
FValueType:=AValue;
Changed;
end;
procedure TCompOptCondNode.Changed;
begin
if (FOwner<>nil) and (not fClearing) then FOwner.InvalidateValues;
end;
constructor TCompOptCondNode.Create(TheOwner: TLazCompOptConditionals);
begin
FOwner:=TheOwner;
fChilds:=TFPList.Create;
end;
destructor TCompOptCondNode.Destroy;
begin
fClearing:=true;
ClearNodes;
if FParent<>nil then begin
FParent.fChilds.Remove(Self);
FParent.Changed;
FParent:=nil;
end;
FreeAndNil(fChilds);
inherited Destroy;
end;
procedure TCompOptCondNode.ClearNodes;
var
i: Integer;
OldClearing: Boolean;
begin
if fChilds.Count=0 then exit;
OldClearing:=fClearing;
fClearing:=true;
for i:=fChilds.Count-1 downto 0 do
TObject(fChilds[i]).Free;
fChilds.Clear;
fClearing:=OldClearing;
Changed;
end;
procedure TCompOptCondNode.AddLast(Child: TCompOptCondNode);
begin
Insert(Count,Child);
end;
procedure TCompOptCondNode.Insert(Index: integer; Child: TCompOptCondNode);
begin
fChilds.Insert(Index,Child);
Child.FParent:=Self;
Changed;
end;
procedure TCompOptCondNode.Move(OldIndex, NewIndex: integer);
begin
if OldIndex=NewIndex then exit;
fChilds.Move(OldIndex,NewIndex);
Changed;
end;
procedure TCompOptCondNode.Delete(Index: integer);
begin
Childs[Index].Free;
end;
{ TProjectFileDescriptor }
procedure TProjectFileDescriptor.SetResourceClass(
@ -1258,6 +1470,19 @@ begin
FDescriptor:=TNewItemProject(Source).Descriptor;
end;
{ TLazCompOptConditionals }
constructor TLazCompOptConditionals.Create;
begin
FRoot:=TCompOptCondNode.Create(Self);
end;
destructor TLazCompOptConditionals.Destroy;
begin
FreeAndNil(FRoot);
inherited Destroy;
end;
initialization
ProjectFileDescriptors:=nil;