implemented compilation of dependencies

git-svn-id: trunk@4073 -
This commit is contained in:
mattias 2003-04-17 18:56:10 +00:00
parent 26ea00db8d
commit ea81b30e67
7 changed files with 483 additions and 109 deletions

View File

@ -2548,6 +2548,7 @@ begin
+'designer'+ds+'jitform;'
+'debugger;'
+'packager;'
+'packager'+ds+'registration;'
+'components'+ds+'synedit;'
+'components'+ds+'codetools;'
+'components'+ds+'custom;'
@ -2629,7 +2630,8 @@ begin
DirTempl.AddChild(TDefineTemplate.Create('components path addition',
Format(ctsAddsDirToSourcePath,['synedit']),
ExternalMacroStart+'SrcPath',
'..'+ds+'components'+ds+'synedit;'
'registration;'
+'..'+ds+'components'+ds+'synedit;'
+'..'+ds+'components'+ds+'codetools;'
+'..'+ds+'components'+ds+'custom;'
+SrcPath

View File

@ -133,7 +133,7 @@ begin
if BuildAll then
CmdLine := CmdLine+' -B';
CmdLine := CmdLine
+ ' '+ AProject.CompilerOptions.MakeOptionsString(ProjectFilename)
+ ' '+ AProject.CompilerOptions.MakeOptionsString(ProjectFilename,[])
+ ' '+ PrepareCmdLineOption(ProjectFilename);
if Assigned(FOnCmdLineCreate) then begin
Abort:=false;
@ -190,6 +190,9 @@ end.
{
$Log$
Revision 1.41 2003/04/17 18:56:10 mattias
implemented compilation of dependencies
Revision 1.40 2003/03/13 23:27:22 mattias
localized codetools options

View File

@ -116,10 +116,16 @@ type
{ TBaseCompilerOptions }
TCompilerCmdLineOption = (
ccloNoLinkerOpts // exclude linker options
);
TCompilerCmdLineOptions = set of TCompilerCmdLineOption;
TBaseCompilerOptions = class
private
FBaseDirectory: string;
FDefaultMakeOptionsFlags: TCompilerCmdLineOptions;
fInheritedOptions: array[TInheritedCompilerOption] of string;
fInheritedOptParseStamps: integer;
fInheritedOptGraphStamps: integer;
@ -211,6 +217,7 @@ type
fAdditionalConfigFile: Boolean;
fConfigFilePath: String;
fCustomOptions: string;
procedure SetDefaultMakeOptionsFlags(const AValue: TCompilerCmdLineOptions);
protected
procedure SetBaseDirectory(const AValue: string); virtual;
procedure SetCompilerPath(const AValue: String); virtual;
@ -239,8 +246,9 @@ type
procedure Assign(CompOpts: TBaseCompilerOptions); virtual;
function IsEqual(CompOpts: TBaseCompilerOptions): boolean; virtual;
function MakeOptionsString: String;
function MakeOptionsString(const MainSourceFileName: string): String; virtual;
function MakeOptionsString(Flags: TCompilerCmdLineOptions): String;
function MakeOptionsString(const MainSourceFileName: string;
Flags: TCompilerCmdLineOptions): String; virtual;
function CustomOptionsAsString: string;
function ConvertSearchPathToCmdLine(const switch, paths: String): String;
function ConvertOptionsToCmdLine(const Delim, Switch, OptionStr: string): string;
@ -253,6 +261,7 @@ type
function MergeLinkerOptions(const OldOptions, AddOptions: string): string;
function MergeCustomOptions(const OldOptions, AddOptions: string): string;
function GetDefaultMainSourceFileName: string; virtual;
function NeedsLinkerOpts: boolean;
public
{ Properties }
property Owner: TObject read fOwner write fOwner;
@ -261,6 +270,7 @@ type
property ParsedOpts: TParsedCompilerOptions read FParsedOpts;
property BaseDirectory: string read FBaseDirectory write SetBaseDirectory;
property TargetFilename: String read fTargetFilename write fTargetFilename;
property DefaultMakeOptionsFlags: TCompilerCmdLineOptions read FDefaultMakeOptionsFlags write SetDefaultMakeOptionsFlags;
property XMLFile: String read fXMLFile write fXMLFile;
property XMLConfigFile: TXMLConfig read xmlconfig write xmlconfig;
@ -733,6 +743,13 @@ begin
ParsedOpts.SetUnparsedValue(pcosCompilerPath,fCompilerPath);
end;
procedure TBaseCompilerOptions.SetDefaultMakeOptionsFlags(
const AValue: TCompilerCmdLineOptions);
begin
if FDefaultMakeOptionsFlags=AValue then exit;
FDefaultMakeOptionsFlags:=AValue;
end;
procedure TBaseCompilerOptions.SetBaseDirectory(const AValue: string);
begin
if FBaseDirectory=AValue then exit;
@ -1160,20 +1177,26 @@ begin
Result:='';
end;
function TBaseCompilerOptions.NeedsLinkerOpts: boolean;
begin
Result:=not (ccloNoLinkerOpts in fDefaultMakeOptionsFlags);
end;
{------------------------------------------------------------------------------
TBaseCompilerOptions MakeOptionsString
------------------------------------------------------------------------------}
function TBaseCompilerOptions.MakeOptionsString: String;
function TBaseCompilerOptions.MakeOptionsString(Flags: TCompilerCmdLineOptions
): String;
begin
Result:=MakeOptionsString(GetDefaultMainSourceFileName)
Result:=MakeOptionsString(GetDefaultMainSourceFileName,Flags);
end;
{------------------------------------------------------------------------------
function TBaseCompilerOptions.MakeOptionsString(
const MainSourceFilename: string): String;
const MainSourceFilename: string; Flags: TCompilerCmdLineOptions): String;
------------------------------------------------------------------------------}
function TBaseCompilerOptions.MakeOptionsString(
const MainSourceFilename: string): String;
const MainSourceFilename: string; Flags: TCompilerCmdLineOptions): String;
var
switches, tempsw: String;
InhLinkerOpts: String;
@ -1509,7 +1532,7 @@ Processor specific options:
switches := switches + ' -gl';
{ Use Heaptrc Unit }
if (UseHeaptrc) then
if (UseHeaptrc) and (not (ccloNoLinkerOpts in Flags)) then
switches := switches + ' -gh';
{ Generate code gprof }
@ -1517,7 +1540,7 @@ Processor specific options:
switches := switches + ' -pg';
{ Strip Symbols }
if (StripSymbols) then
if (StripSymbols) and (not (ccloNoLinkerOpts in Flags)) then
switches := switches + ' -Xs';
{ Link Style
@ -1525,23 +1548,26 @@ Processor specific options:
-XS = Link with static libraries
-XX = Link smart
}
case (LinkStyle) of
1: switches := switches + ' -XD';
2: switches := switches + ' -XS';
3: switches := switches + ' -XX';
end;
if (not (ccloNoLinkerOpts in Flags)) then
case (LinkStyle) of
1: switches := switches + ' -XD';
2: switches := switches + ' -XS';
3: switches := switches + ' -XX';
end;
// additional Linker options
if PassLinkerOptions then begin
if PassLinkerOptions and (not (ccloNoLinkerOpts in Flags)) then begin
CurLinkerOptions:=ParsedOpts.GetParsedValue(pcosLinkerOptions);
if (CurLinkerOptions<>'') then
switches := switches + ' ' + ConvertOptionsToCmdLine(' ','-k', CurLinkerOptions);
end;
// inherited Linker options
InhLinkerOpts:=GetInheritedOption(icoLinkerOptions,true);
if InhLinkerOpts<>'' then
switches := switches + ' ' + ConvertOptionsToCmdLine(' ','-k', InhLinkerOpts);
if (not (ccloNoLinkerOpts in Flags)) then begin
InhLinkerOpts:=GetInheritedOption(icoLinkerOptions,true);
if InhLinkerOpts<>'' then
switches := switches + ' ' + ConvertOptionsToCmdLine(' ','-k', InhLinkerOpts);
end;
{ ---------------- Other Tab -------------------- }
@ -1617,14 +1643,18 @@ Processor specific options:
switches := switches + ' ' + ConvertSearchPathToCmdLine('-Fi', InhIncludePath);
// library path
CurLibraryPath:=ParsedOpts.GetParsedValue(pcosLibraryPath);
if (CurLibraryPath <> '') then
switches := switches + ' ' + ConvertSearchPathToCmdLine('-Fl', CurLibraryPath);
if (not (ccloNoLinkerOpts in Flags)) then begin
CurLibraryPath:=ParsedOpts.GetParsedValue(pcosLibraryPath);
if (CurLibraryPath <> '') then
switches := switches + ' ' + ConvertSearchPathToCmdLine('-Fl', CurLibraryPath);
end;
// inherited library path
InhLibraryPath:=GetInheritedOption(icoLibraryPath,true);
if (InhLibraryPath <> '') then
switches := switches + ' ' + ConvertSearchPathToCmdLine('-Fl', InhLibraryPath);
if (not (ccloNoLinkerOpts in Flags)) then begin
InhLibraryPath:=GetInheritedOption(icoLibraryPath,true);
if (InhLibraryPath <> '') then
switches := switches + ' ' + ConvertSearchPathToCmdLine('-Fl', InhLibraryPath);
end;
// object path
CurObjectPath:=ParsedOpts.GetParsedValue(pcosObjectPath);
@ -1653,7 +1683,8 @@ Processor specific options:
{ Unit output directory }
if UnitOutputDirectory<>'' then
CurOutputDir:=ParsedOpts.GetParsedValue(pcosOutputDir)
CurOutputDir:=CreateRelativePath(ParsedOpts.GetParsedValue(pcosOutputDir),
BaseDirectory)
else
CurOutputDir:='';
if CurOutputDir<>'' then
@ -2203,20 +2234,20 @@ begin
ModalResult:=mrCancel;
end;
{------------------------------------------------------------------------------}
{ TfrmCompilerOptions ButtonApplyClicked }
{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------
TfrmCompilerOptions ButtonApplyClicked
------------------------------------------------------------------------------}
procedure TfrmCompilerOptions.ButtonApplyClicked(Sender: TObject);
begin
// Apply any changes
PutCompilerOptions;
end;
{------------------------------------------------------------------------------}
{ TfrmCompilerOptions ButtonTestClicked }
{ This function is for testing the MakeOptionsString function only. Remove }
{ this function and its button when the function is working correctly. }
{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------
TfrmCompilerOptions ButtonTestClicked
This function is for testing the MakeOptionsString function only. Remove
this function and its button when the function is working correctly.
------------------------------------------------------------------------------}
procedure TfrmCompilerOptions.ButtonTestClicked(Sender: TObject);
var
teststr: String;
@ -2226,7 +2257,7 @@ begin
Assert(False, 'Trace:Test MakeOptionsString function');
PutCompilerOptions;
teststr := CompilerOpts.MakeOptionsString;
teststr := CompilerOpts.MakeOptionsString(CompilerOpts.DefaultMakeOptionsFlags);
WriteLn('CompilerOpts.MakeOptionsString: ' + teststr);
i:=1;
LineLen:=0;
@ -2281,8 +2312,12 @@ end;
TfrmCompilerOptions GetCompilerOptions
------------------------------------------------------------------------------}
procedure TfrmCompilerOptions.GetCompilerOptions;
var i: integer;
var
i: integer;
EnabledLinkerOpts: Boolean;
begin
EnabledLinkerOpts:=CompilerOpts.NeedsLinkerOpts;
{ Get the compiler options and apply them to the dialog }
case CompilerOpts.Style of
1: radStyleIntel.Checked := true;
@ -2310,6 +2345,7 @@ begin
chkChecksOverflow.Checked := CompilerOpts.OverflowChecks;
chkChecksStack.Checked := CompilerOpts.StackChecks;
grpHeapSize.Enabled:=EnabledLinkerOpts;
edtHeapSize.Text := IntToStr(CompilerOpts.HeapSize);
case CompilerOpts.Generate of
@ -2336,18 +2372,22 @@ begin
chkDebugDBX.Checked := CompilerOpts.GenerateDebugDBX;
chkUseLineInfoUnit.Checked := CompilerOpts.UseLineInfoUnit;
chkUseHeaptrc.Checked := CompilerOpts.UseHeaptrc;
chkUseHeaptrc.Enabled:=EnabledLinkerOpts;
chkGenGProfCode.Checked := CompilerOpts.GenGProfCode;
chkSymbolsStrip.Checked := CompilerOpts.StripSymbols;
chkSymbolsStrip.Enabled:=EnabledLinkerOpts;
case CompilerOpts.LinkStyle of
1: radLibsLinkDynamic.Checked := true;
2: radLibsLinkStatic.Checked := true;
3: radLibsLinkSmart.Checked := true;
end;
grpLinkLibraries.Enabled:=EnabledLinkerOpts;
chkOptionsLinkOpt.Checked := CompilerOpts.PassLinkerOptions;
edtOptionsLinkOpt.Text := CompilerOpts.LinkerOptions;
grpOptions.Enabled:=EnabledLinkerOpts;
chkErrors.Checked := CompilerOpts.ShowErrors;
chkWarnings.Checked := CompilerOpts.ShowWarn;
chkNotes.Checked := CompilerOpts.ShowNotes;
@ -2379,6 +2419,7 @@ begin
edtOtherUnits.Text := CompilerOpts.OtherUnitFiles;
edtIncludeFiles.Text := CompilerOpts.IncludeFiles;
edtLibraries.Text := CompilerOpts.Libraries;
grpLibraries.Enabled:=EnabledLinkerOpts;
edtCompiler.Text := CompilerOpts.CompilerPath;
edtUnitOutputDir.Text := CompilerOpts.UnitOutputDirectory;
@ -2410,13 +2451,13 @@ begin
OldCompOpts.Assign(CompilerOpts);
if (radStyleIntel.Checked) then
CompilerOpts.Style := 1
CompilerOpts.Style := 1
else if (radStyleATT.Checked) then
CompilerOpts.Style := 2
CompilerOpts.Style := 2
else if (radStyleAsIs.Checked) then
CompilerOpts.Style := 3
CompilerOpts.Style := 3
else
CompilerOpts.Style := 1;
CompilerOpts.Style := 1;
CompilerOpts.D2Extensions := chkSymD2Ext.Checked;
CompilerOpts.CStyleOperators := chkSymCOper.Checked;
@ -2446,32 +2487,32 @@ begin
CompilerOpts.HeapSize := hs;
if (radGenFaster.Checked) then
CompilerOpts.Generate := 1
CompilerOpts.Generate := 1
else if (radGenSmaller.Checked) then
CompilerOpts.Generate := 2
CompilerOpts.Generate := 2
else
CompilerOpts.Generate := 1;
CompilerOpts.Generate := 1;
if (radTarget386.Checked) then
CompilerOpts.TargetProcessor := 1
CompilerOpts.TargetProcessor := 1
else if (radTargetPent.Checked) then
CompilerOpts.TargetProcessor := 2
CompilerOpts.TargetProcessor := 2
else if (radTargetPentPro.Checked) then
CompilerOpts.TargetProcessor := 3
CompilerOpts.TargetProcessor := 3
else
CompilerOpts.TargetProcessor := 1;
CompilerOpts.TargetProcessor := 1;
CompilerOpts.VariablesInRegisters := chkOptVarsInReg.Checked;
CompilerOpts.UncertainOptimizations := chkOptUncertain.Checked;
if (radOptLevel1.Checked) then
CompilerOpts.OptimizationLevel := 1
CompilerOpts.OptimizationLevel := 1
else if (radOptLevel2.Checked) then
CompilerOpts.OptimizationLevel := 2
CompilerOpts.OptimizationLevel := 2
else if (radOptLevel3.Checked) then
CompilerOpts.OptimizationLevel := 3
CompilerOpts.OptimizationLevel := 3
else
CompilerOpts.OptimizationLevel := 1;
CompilerOpts.OptimizationLevel := 1;
CompilerOpts.GenerateDebugInfo := chkDebugGDB.Checked;
CompilerOpts.GenerateDebugDBX := chkDebugDBX.Checked;

View File

@ -59,7 +59,10 @@ type
TPkgOpenFlags = set of TPkgOpenFlag;
TPkgCompileFlag = (
pcfCompileAll
pcfCleanCompile, // append -B to the compiler options
pcfDoNotCompileDependencies,
pcfOnlyIfNeeded,
pcfAutomatic
);
TPkgCompileFlags = set of TPkgCompileFlag;
@ -92,9 +95,69 @@ type
var
PkgBoss: TBasePkgManager;
const
PkgSaveFlagNames: array[TPkgSaveFlag] of string = (
'psfSaveAs',
'psfAskBeforeSaving'
);
PkgOpenFlagNames: array[TPkgOpenFlag] of string = (
'pofAddToRecent'
);
PkgCompileFlagNames: array[TPkgCompileFlag] of string = (
'pcfCleanCompile',
'pcfDoNotCompileDependencies',
'pcfOnlyIfNeeded',
'pcfAutomatic'
);
function PkgSaveFlagsToString(Flags: TPkgSaveFlags): string;
function PkgOpenFlagsToString(Flags: TPkgOpenFlags): string;
function PkgCompileFlagsToString(Flags: TPkgCompileFlags): string;
implementation
function PkgSaveFlagsToString(Flags: TPkgSaveFlags): string;
var
f: TPkgSaveFlag;
begin
Result:='';
for f:=Low(TPkgSaveFlag) to High(TPkgSaveFlag) do begin
if not (f in Flags) then continue;
if Result<>'' then Result:=Result+',';
Result:=Result+PkgSaveFlagNames[f];
end;
Result:='['+Result+']';
end;
function PkgOpenFlagsToString(Flags: TPkgOpenFlags): string;
var
f: TPkgOpenFlag;
begin
Result:='';
for f:=Low(TPkgOpenFlag) to High(TPkgOpenFlag) do begin
if not (f in Flags) then continue;
if Result<>'' then Result:=Result+',';
Result:=Result+PkgOpenFlagNames[f];
end;
Result:='['+Result+']';
end;
function PkgCompileFlagsToString(Flags: TPkgCompileFlags): string;
var
f: TPkgCompileFlag;
begin
Result:='';
for f:=Low(TPkgCompileFlag) to High(TPkgCompileFlag) do begin
if not (f in Flags) then continue;
if Result<>'' then Result:=Result+',';
Result:=Result+PkgCompileFlagNames[f];
end;
Result:='['+Result+']';
end;
initialization
PkgBoss:=nil;

View File

@ -337,8 +337,9 @@ type
// package requires this package)
lpfVisited, // Used by the PackageGraph to avoid double checking
lpfDestroying, // set during destruction
lpfSkipSaving,
lpfCircle
lpfSkipSaving, // Used by PkgBoss to skip saving
lpfCircle, // Used by the PackageGraph to mark circles
lpfStateFileLoaded // state file data valid
);
TLazPackageFlags = set of TLazPackageFlag;
@ -372,6 +373,8 @@ type
FFlags: TLazPackageFlags;
FIconFile: string;
FInstalled: TPackageInstallType;
FLastCompilerFilename: string;
FLastCompilerParams: string;
FMacros: TTransferMacroList;
FModifiedLock: integer;
FPackageEditor: TBasePackageEditor;
@ -379,6 +382,7 @@ type
FReadOnly: boolean;
FRemovedFiles: TList; // TList of TPkgFile
FRegistered: boolean;
FStateFileDate: longint;
FUsageOptions: TPkgAdditionalCompilerOptions;
function GetAutoIncrementVersionOnBuild: boolean;
function GetAutoUpdate: boolean;
@ -429,6 +433,8 @@ type
procedure GetInheritedCompilerOptions(var OptionsList: TList);
function GetCompileSourceFilename: string;
function GetOutputDirectory: string;
function GetStateFilename: string;
function GetCompilerFilename: string;
// files
function FindPkgFile(const AFilename: string;
ResolveLinks, IgnoreRemoved: boolean): TPkgFile;
@ -491,13 +497,18 @@ type
property Flags: TLazPackageFlags read FFlags write SetFlags;
property IconFile: string read FIconFile write SetIconFile;
property Installed: TPackageInstallType read FInstalled write SetInstalled;
property Registered: boolean read FRegistered write SetRegistered;
property LastCompilerFilename: string read FLastCompilerFilename
write FLastCompilerFilename;
property LastCompilerParams: string read FLastCompilerParams
write FLastCompilerParams;
property Macros: TTransferMacroList read FMacros;
property Modified: boolean read GetModified write SetModified;
property PackageType: TLazPackageType read FPackageType write SetPackageType;
property ReadOnly: boolean read FReadOnly write SetReadOnly;
property Registered: boolean read FRegistered write SetRegistered;
property RemovedFilesCount: integer read GetRemovedCount;
property RemovedFiles[Index: integer]: TPkgFile read GetRemovedFiles;
property Macros: TTransferMacroList read FMacros;
property StateFileDate: longint read FStateFileDate write FStateFileDate;
property UsageOptions: TPkgAdditionalCompilerOptions
read FUsageOptions;
end;
@ -529,7 +540,8 @@ const
'RunTime', 'DesignTime', 'RunAndDesignTime');
LazPackageFlagNames: array[TLazPackageFlag] of string = (
'lpfAutoIncrementVersionOnBuild', 'lpfModified', 'lpfAutoUpdate',
'lpfNeeded', 'lpfVisited', 'lpfDestroying', 'lpfSkipSaving', 'lpfCircle');
'lpfNeeded', 'lpfVisited', 'lpfDestroying', 'lpfSkipSaving', 'lpfCircle',
'lpfStateFileLoaded');
var
// All TPkgDependency are added to this AVL tree (sorted for names, not version!)
@ -1499,6 +1511,7 @@ begin
FCompilerOptions:=TPkgCompilerOptions.Create(Self);
FCompilerOptions.ParsedOpts.OnLocalSubstitute:=@SubstitutePkgMacro;
FCompilerOptions.ParsedOpts.InvalidateGraphOnChange:=true;
FCompilerOptions.DefaultMakeOptionsFlags:=[ccloNoLinkerOpts];
FUsageOptions:=TPkgAdditionalCompilerOptions.Create(Self);
FUsageOptions.ParsedOpts.OnLocalSubstitute:=@SubstitutePkgMacro;
Clear;
@ -2072,6 +2085,17 @@ begin
Result:='';
end;
function TLazPackage.GetStateFilename: string;
begin
Result:=GetOutputDirectory
+ChangeFileExt(GetCompileSourceFilename,'.compiled');
end;
function TLazPackage.GetCompilerFilename: string;
begin
Result:=CompilerOptions.ParsedOpts.GetParsedValue(pcosCompilerPath);
end;
{ TPkgComponent }
procedure TPkgComponent.SetPkgFile(const AValue: TPkgFile);

View File

@ -154,6 +154,7 @@ type
procedure MarkNeededPackages;
function FindBrokenDependencyPath(APackage: TLazPackage): TList;
function FindCircleDependencyPath(APackage: TLazPackage): TList;
function GetAutoCompilationOrder(APackage: TLazPackage): TList;
public
// packages handling
function CreateNewPackage(const Prefix: string): TLazPackage;
@ -1036,6 +1037,40 @@ begin
FindCircle(APackage,Result);
end;
function TLazPackageGraph.GetAutoCompilationOrder(APackage: TLazPackage
): TList;
procedure GetTopologicalOrder(const FirstDependency: TPkgDependency);
var
Dependency: TPkgDependency;
RequiredPackage: TLazPackage;
begin
Dependency:=FirstDependency;
while Dependency<>nil do begin
if Dependency.LoadPackageResult=lprSuccess then begin
RequiredPackage:=Dependency.RequiredPackage;
if not (lpfVisited in RequiredPackage.Flags) then begin
RequiredPackage.Flags:=RequiredPackage.Flags+[lpfVisited];
if RequiredPackage.AutoUpdate then begin
// add first all needed packages
GetTopologicalOrder(RequiredPackage.FirstRequiredDependency);
// then add this package
if Result=nil then Result:=TList.Create;
Result.Add(RequiredPackage);
end;
end;
end;
Dependency:=Dependency.NextRequiresDependency;
end;
end;
begin
Result:=nil;
MarkAllPackagesAsNotVisited;
APackage.Flags:=APackage.Flags+[lpfVisited];
GetTopologicalOrder(APackage.FirstRequiredDependency);
end;
procedure TLazPackageGraph.MarkAllPackagesAsNotVisited;
var
i: Integer;

View File

@ -84,6 +84,12 @@ type
procedure OnApplicationIdle(Sender: TObject);
private
function DoShowSavePackageAsDialog(APackage: TLazPackage): TModalResult;
function CompileRequiredPackages(APackage: TLazPackage): TModalResult;
function CheckPackageGraphForCompilation(APackage: TLazPackage): TModalResult;
function DoPreparePackageOutputDirectory(APackage: TLazPackage): TModalResult;
function DoSavePackageCompiledState(APackage: TLazPackage;
const CompilerFilename, CompilerParams: string): TModalResult;
function CheckIfPackageNeedsCompilation(APackage: TLazPackage): boolean;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
@ -96,7 +102,7 @@ type
procedure LoadInstalledPackages; override;
function AddPackageToGraph(APackage: TLazPackage): TModalResult;
function ShowConfigureCustomComponents: TModalResult; override;
function DoNewPackage: TModalResult; override;
function DoShowOpenInstalledPckDlg: TModalResult; override;
@ -159,7 +165,7 @@ var
Flags: TPkgCompileFlags;
begin
Flags:=[];
if CompileAll then Include(Flags,pcfCompileAll);
if CompileAll then Include(Flags,pcfCleanCompile);
Result:=DoCompilePackage(APackage,Flags);
end;
@ -525,6 +531,197 @@ begin
Result:=mrOk;
end;
function TPkgManager.CompileRequiredPackages(APackage: TLazPackage
): TModalResult;
var
AutoPackages: TList;
i: Integer;
begin
AutoPackages:=PackageGraph.GetAutoCompilationOrder(APackage);
if AutoPackages<>nil then begin
try
i:=0;
while i<AutoPackages.Count do begin
Result:=DoCompilePackage(TLazPackage(AutoPackages[i]),
[pcfDoNotCompileDependencies,pcfOnlyIfNeeded,
pcfAutomatic]);
if Result<>mrOk then exit;
inc(i);
end;
finally
AutoPackages.Free;
end;
end;
Result:=mrOk;
end;
function TPkgManager.CheckPackageGraphForCompilation(APackage: TLazPackage
): TModalResult;
var
PathList: TList;
begin
// check for broken dependencies
PathList:=PackageGraph.FindBrokenDependencyPath(APackage);
if PathList<>nil then begin
DoShowPackageGraphPathList(PathList);
Result:=MessageDlg('Broken dependency',
'A required packages was not found. See package graph.',
mtError,[mbCancel,mbAbort],0);
exit;
end;
// check for circle dependencies
PathList:=PackageGraph.FindCircleDependencyPath(APackage);
if PathList<>nil then begin
DoShowPackageGraphPathList(PathList);
Result:=MessageDlg('Circle in package dependencies',
'There is a circle in the required packages. See package graph.',
mtError,[mbCancel,mbAbort],0);
exit;
end;
Result:=mrOk;
end;
function TPkgManager.DoSavePackageCompiledState(APackage: TLazPackage;
const CompilerFilename, CompilerParams: string): TModalResult;
var
XMLConfig: TXMLConfig;
StateFile: String;
begin
StateFile:=APackage.GetStateFilename;
try
ClearFile(StateFile,true);
XMLConfig:=TXMLConfig.Create(StateFile);
try
XMLConfig.SetValue('Compiler/Value',CompilerFilename);
XMLConfig.SetValue('Params/Value',CompilerParams);
XMLConfig.Flush;
finally
XMLConfig.Free;
end;
APackage.LastCompilerFilename:=CompilerFilename;
APackage.LastCompilerParams:=CompilerParams;
APackage.StateFileDate:=FileAge(StateFile);
APackage.Flags:=APackage.Flags+[lpfStateFileLoaded];
except
on E: Exception do begin
Result:=MessageDlg('Error writing file',
'Unable to write state file "'+StateFile+'"'#13
+'of package '+APackage.IDAsString+'.',
mtError,[mbAbort,mbCancel],0);
exit;
end;
end;
Result:=MainIDE.DoDeleteAmbigiousFiles(StateFile);
if Result<>mrOk then exit;
end;
function TPkgManager.DoPreparePackageOutputDirectory(APackage: TLazPackage
): TModalResult;
var
OutputDir: String;
StateFile: String;
begin
OutputDir:=APackage.GetOutputDirectory;
StateFile:=APackage.GetStateFilename;
// create the output directory
if not ForceDirectory(OutputDir) then begin
Result:=MessageDlg('Unable to create directory',
'Unable to create output directory "'+OutputDir+'"'#13
+'for package '+APackage.IDAsString+'.',
mtError,[mbCancel,mbAbort],0);
exit;
end;
// delete old Compile State file
if FileExists(StateFile) and not DeleteFile(StateFile) then begin
Result:=MessageDlg('Unable to delete file',
'Unable to delete old state file "'+StateFile+'"'#13
+'for package '+APackage.IDAsString+'.',
mtError,[mbCancel,mbAbort],0);
exit;
end;
APackage.Flags:=APackage.Flags-[lpfStateFileLoaded];
Result:=mrOk;
end;
function TPkgManager.CheckIfPackageNeedsCompilation(APackage: TLazPackage
): boolean;
var
OutputDir: String;
SrcFilename: String;
CompilerFilename: String;
CompilerParams: String;
StateFilename: String;
StateFileAge: Integer;
i: Integer;
XMLConfig: TXMLConfig;
CurFile: TPkgFile;
begin
Result:=true;
writeln('TPkgManager.CheckIfPackageNeedsCompilation A ',APackage.IDAsString);
// check state file
StateFilename:=APackage.GetStateFilename;
if not FileExists(StateFilename) then exit;
StateFileAge:=FileAge(StateFilename);
// read the state file
if (not (lpfStateFileLoaded in APackage.Flags))
or (APackage.StateFileDate<>StateFileAge) then begin
try
XMLConfig:=TXMLConfig.Create(StateFilename);
try
APackage.LastCompilerFilename:=
XMLConfig.GetValue('Compiler/Value','');
APackage.LastCompilerParams:=
XMLConfig.GetValue('Params/Value','');
finally
XMLConfig.Free;
end;
APackage.StateFileDate:=StateFileAge;
except
on E: Exception do begin
MessageDlg('Error reading file',
'Unable to read state file "'+StateFilename+'"'#13
+'of package '+APackage.IDAsString+'.',
mtError,[mbCancel],0);
exit;
end;
end;
APackage.Flags:=APackage.Flags+[lpfStateFileLoaded];
end;
OutputDir:=APackage.GetOutputDirectory;
SrcFilename:=OutputDir+APackage.GetCompileSourceFilename;
CompilerFilename:=APackage.GetCompilerFilename;
CompilerParams:=APackage.CompilerOptions.MakeOptionsString(
APackage.CompilerOptions.DefaultMakeOptionsFlags)
+' '+CreateRelativePath(SrcFilename,APackage.Directory);
// check compiler command
if CompilerFilename<>APackage.LastCompilerFilename then exit;
if CompilerParams<>APackage.LastCompilerParams then exit;
// check main source file
if StateFileAge<FileAge(SrcFilename) then exit;
// check package files
for i:=0 to APackage.FileCount-1 do begin
CurFile:=APackage.Files[i];
if FileExists(CurFile.Filename)
and (StateFileAge<FileAge(CurFile.Filename)) then exit;
end;
writeln('TPkgManager.CheckIfPackageNeedsCompilation END ',APackage.IDAsString);
Result:=false;
end;
constructor TPkgManager.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
@ -904,79 +1101,88 @@ end;
function TPkgManager.DoCompilePackage(APackage: TLazPackage;
Flags: TPkgCompileFlags): TModalResult;
var
PathList: TList;
PkgCompileTool: TExternalToolOptions;
OutputDir: String;
SrcFilename: String;
CompilerFilename: String;
CompilerParams: String;
begin
Result:=mrCancel;
writeln('TPkgManager.DoCompilePackage A ',APackage.IDAsString,' Flags=',PkgCompileFlagsToString(Flags));
if APackage.AutoCreated then exit;
// check for broken dependencies
PathList:=PackageGraph.FindBrokenDependencyPath(APackage);
if PathList<>nil then begin
DoShowPackageGraphPathList(PathList);
Result:=MessageDlg('Broken dependency',
'A required packages was not found. See package graph.',
mtError,[mbCancel,mbAbort],0);
exit;
// check graph for circles and broken dependencies
if not (pcfDoNotCompileDependencies in Flags) then begin
Result:=CheckPackageGraphForCompilation(APackage);
if Result<>mrOk then exit;
end;
// check for circle dependencies
PathList:=PackageGraph.FindCircleDependencyPath(APackage);
if PathList<>nil then begin
DoShowPackageGraphPathList(PathList);
Result:=MessageDlg('Circle in package dependencies',
'There is a circle in the required packages. See package graph.',
mtError,[mbCancel,mbAbort],0);
exit;
// save all open files
if not (pcfAutomatic in Flags) then begin
Result:=MainIDE.DoSaveForBuild;
if Result<>mrOk then exit;
end;
// create the output directory
OutputDir:=APackage.GetOutputDirectory;
if not ForceDirectory(OutputDir) then begin
Result:=MessageDlg('Unable to create directory',
'Unable to create output directory "'+OutputDir+'"'#13
+'for package '+APackage.IDAsString+'.',
mtError,[mbCancel,mbAbort],0);
// automatically compile required packages
if not (pcfDoNotCompileDependencies in Flags) then begin
Result:=CompileRequiredPackages(APackage);
if Result<>mrOk then exit;
end;
// check if compilation is neccessary
if ([pcfOnlyIfNeeded,pcfCleanCompile]*Flags<>[])
and (not CheckIfPackageNeedsCompilation(APackage)) then begin
Result:=mrOk;
exit;
end;
// save everything
Result:=MainIDE.DoSaveForBuild;
Result:=DoPreparePackageOutputDirectory(APackage);
if Result<>mrOk then exit;
// update dependencies
// ToDo
// create package main source file
Result:=DoSavePackageMainSource(APackage,Flags);
if Result<>mrOk then exit;
SrcFilename:=CreateRelativePath(OutputDir+APackage.GetCompileSourceFilename,
APackage.Directory);
// create external tool to run the compiler
OutputDir:=APackage.GetOutputDirectory;
SrcFilename:=CreateRelativePath(OutputDir+APackage.GetCompileSourceFilename,
APackage.Directory);
CompilerFilename:=APackage.GetCompilerFilename;
CompilerParams:=APackage.CompilerOptions.MakeOptionsString(
APackage.CompilerOptions.DefaultMakeOptionsFlags)
+' '+SrcFilename;
PkgCompileTool:=TExternalToolOptions.Create;
PkgCompileTool.Title:='Compiling package '+APackage.IDAsString;
PkgCompileTool.Filename:=APackage.CompilerOptions.CompilerPath;
PkgCompileTool.ScanOutputForFPCMessages:=true;
PkgCompileTool.ScanOutputForMakeMessages:=true;
PkgCompileTool.WorkingDirectory:=APackage.Directory;
PkgCompileTool.CmdLineParams:=APackage.CompilerOptions.MakeOptionsString
+' '+SrcFilename;
try
PkgCompileTool.Title:='Compiling package '+APackage.IDAsString;
PkgCompileTool.Filename:=CompilerFilename;
PkgCompileTool.ScanOutputForFPCMessages:=true;
PkgCompileTool.ScanOutputForMakeMessages:=true;
PkgCompileTool.WorkingDirectory:=APackage.Directory;
PkgCompileTool.CmdLineParams:=CompilerParams;
// clear old errors
SourceNotebook.ClearErrorLines;
// clear old errors
SourceNotebook.ClearErrorLines;
// compile package
Result:=EnvironmentOptions.ExternalTools.Run(PkgCompileTool,MainIDE.MacroList);
// compile package
Result:=EnvironmentOptions.ExternalTools.Run(PkgCompileTool,MainIDE.MacroList);
if Result=mrOk then begin
// compilation succeded -> write state file
Result:=DoSavePackageCompiledState(APackage,
CompilerFilename,CompilerParams);
if Result<>mrOk then exit;
end;
finally
// clean up
PkgCompileTool.Free;
// clean up
PkgCompileTool.Free;
MainIDE.DoCheckFilesOnDisk;
if not (pcfAutomatic in Flags) then begin
// check for changed files on disk
MainIDE.DoCheckFilesOnDisk;
end;
end;
Result:=mrOk;
end;