ide: package compiled file: store lazarusversion and switch between fallback on check not on prepare

This commit is contained in:
mattias 2023-08-15 10:59:04 +02:00
parent fffdea39bb
commit ec5726dc18
2 changed files with 249 additions and 210 deletions

View File

@ -447,7 +447,7 @@ type
podwWritable, podwWritable,
podwNotWritable podwNotWritable
); );
TPkgLastCompileStats = record TPkgLastCompileStats = class
StateFileLoaded: boolean; StateFileLoaded: boolean;
StateFileName: string; // the .compiled file StateFileName: string; // the .compiled file
StateFileDate: longint; StateFileDate: longint;
@ -458,8 +458,8 @@ type
MainPPUExists: boolean; // main ppu file was there after compile MainPPUExists: boolean; // main ppu file was there after compile
ViaMakefile: boolean; // compiled via make ViaMakefile: boolean; // compiled via make
DirectoryWritable: TPkgOutputDirWritable; DirectoryWritable: TPkgOutputDirWritable;
LazarusVersion: string;
end; end;
PPkgLastCompileStats = ^TPkgLastCompileStats;
TPkgOutputDir = ( TPkgOutputDir = (
podDefault, podDefault,
podFallback // used when podDefault is not writable podFallback // used when podDefault is not writable
@ -2619,6 +2619,8 @@ begin
end; end;
constructor TLazPackage.Create; constructor TLazPackage.Create;
var
pod: TPkgOutputDir;
begin begin
inherited Create; inherited Create;
FComponents:=TFPList.Create; FComponents:=TFPList.Create;
@ -2638,6 +2640,8 @@ begin
FDefineTemplates:=TLazPackageDefineTemplates.Create(Self); FDefineTemplates:=TLazPackageDefineTemplates.Create(Self);
fPublishOptions:=TPublishPackageOptions.Create(Self); fPublishOptions:=TPublishPackageOptions.Create(Self);
FProvides:=TStringList.Create; FProvides:=TStringList.Create;
for pod in TPkgOutputDir do
LastCompile[pod]:=TPkgLastCompileStats.Create;
FUsageOptions.ParsedOpts.InvalidateParseOnChange:=true; FUsageOptions.ParsedOpts.InvalidateParseOnChange:=true;
end; end;
@ -2648,9 +2652,13 @@ begin
end; end;
destructor TLazPackage.Destroy; destructor TLazPackage.Destroy;
var
pod: TPkgOutputDir;
begin begin
Include(FFlags,lpfDestroying); Include(FFlags,lpfDestroying);
Clear; Clear;
for pod in TPkgOutputDir do
FreeAndNil(LastCompile[pod]);
FreeAndNil(FOptionsBackup); FreeAndNil(FOptionsBackup);
FreeAndNil(fPublishOptions); FreeAndNil(fPublishOptions);
FreeAndNil(FProvides); FreeAndNil(FProvides);

View File

@ -243,6 +243,8 @@ type
CheckDependencies, SkipDesignTimePackages, GroupCompile: boolean; CheckDependencies, SkipDesignTimePackages, GroupCompile: boolean;
out NeedBuildAllFlag, ConfigChanged, DependenciesChanged: boolean; out NeedBuildAllFlag, ConfigChanged, DependenciesChanged: boolean;
var Note: string): TModalResult; var Note: string): TModalResult;
function LoadPackageCompiledStateFile(APackage: TLazPackage; o: TPkgOutputDir;
StateFile: string; IgnoreErrors, ShowAbort: boolean): TModalResult;
procedure InvalidateStateFile(APackage: TLazPackage); procedure InvalidateStateFile(APackage: TLazPackage);
procedure OnExtToolBuildStopped(Sender: TObject); procedure OnExtToolBuildStopped(Sender: TObject);
procedure PkgModify(Sender: TObject); procedure PkgModify(Sender: TObject);
@ -3214,7 +3216,7 @@ var
StateFile: String; StateFile: String;
CompilerFileDate: Integer; CompilerFileDate: Integer;
o: TPkgOutputDir; o: TPkgOutputDir;
stats: PPkgLastCompileStats; Stats: TPkgLastCompileStats;
begin begin
Result:=mrCancel; Result:=mrCancel;
StateFile:=APackage.GetStateFilename; StateFile:=APackage.GetStateFilename;
@ -3222,15 +3224,17 @@ begin
CompilerFileDate:=FileAgeCached(CompilerFilename); CompilerFileDate:=FileAgeCached(CompilerFilename);
o:=APackage.GetOutputDirType; o:=APackage.GetOutputDirType;
stats:=@APackage.LastCompile[o]; Stats:=APackage.LastCompile[o];
stats^.CompilerFilename:=CompilerFilename; Stats.LazarusVersion:=LazarusVersionStr;
stats^.CompilerFileDate:=CompilerFileDate; Stats.CompilerFilename:=CompilerFilename;
stats^.Params:=CompilerParams; Stats.CompilerFileDate:=CompilerFileDate;
stats^.Complete:=Complete; Stats.Params:=CompilerParams;
stats^.ViaMakefile:=false; Stats.Complete:=Complete;
Stats.ViaMakefile:=false;
XMLConfig:=TXMLConfig.CreateClean(StateFile); XMLConfig:=TXMLConfig.CreateClean(StateFile);
try try
XMLConfig.SetValue('Lazarus/Version',Stats.LazarusVersion);
XMLConfig.SetValue('Compiler/Value',CompilerFilename); XMLConfig.SetValue('Compiler/Value',CompilerFilename);
XMLConfig.SetValue('Compiler/Date',CompilerFileDate); XMLConfig.SetValue('Compiler/Date',CompilerFileDate);
XMLConfig.SetValue('Params/Value',CompilerParams); XMLConfig.SetValue('Params/Value',CompilerParams);
@ -3241,9 +3245,9 @@ begin
finally finally
XMLConfig.Free; XMLConfig.Free;
end; end;
stats^.StateFileName:=StateFile; Stats.StateFileName:=StateFile;
stats^.StateFileDate:=FileAgeCached(StateFile); Stats.StateFileDate:=FileAgeCached(StateFile);
APackage.LastCompile[o].StateFileLoaded:=true; Stats.StateFileLoaded:=true;
except except
on E: Exception do begin on E: Exception do begin
Result:=IDEMessageDialogAb(lisPkgMangErrorWritingFile, Result:=IDEMessageDialogAb(lisPkgMangErrorWritingFile,
@ -3260,83 +3264,12 @@ end;
function TLazPackageGraph.LoadPackageCompiledState(APackage: TLazPackage; function TLazPackageGraph.LoadPackageCompiledState(APackage: TLazPackage;
IgnoreErrors, ShowAbort: boolean): TModalResult; IgnoreErrors, ShowAbort: boolean): TModalResult;
var var
XMLConfig: TXMLConfig;
StateFile: String; StateFile: String;
StateFileAge: Integer;
stats: PPkgLastCompileStats;
o: TPkgOutputDir; o: TPkgOutputDir;
MakefileValue: String;
MakefileVersion: Integer;
begin begin
o:=APackage.GetOutputDirType;
stats:=@APackage.LastCompile[o];
StateFile:=APackage.GetStateFilename; StateFile:=APackage.GetStateFilename;
if not FileExistsCached(StateFile) then begin o:=APackage.GetOutputDirType;
//DebugLn('TLazPackageGraph.LoadPackageCompiledState Statefile not found: ',StateFile); Result:=LoadPackageCompiledStateFile(APackage,o,StateFile,IgnoreErrors,ShowAbort);
stats^.StateFileLoaded:=false;
Result:=mrOk;
exit;
end;
// read the state file
StateFileAge:=FileAgeCached(StateFile);
if (not stats^.StateFileLoaded)
or (stats^.StateFileDate<>StateFileAge)
or (stats^.StateFileName<>StateFile) then begin
stats^.StateFileLoaded:=false;
try
XMLConfig:=TXMLConfig.Create(StateFile);
try
stats^.CompilerFilename:=XMLConfig.GetValue('Compiler/Value','');
stats^.CompilerFileDate:=XMLConfig.GetValue('Compiler/Date',0);
stats^.Params:=XMLConfig.GetValue('Params/Value','');
stats^.Complete:=XMLConfig.GetValue('Complete/Value',true);
stats^.MainPPUExists:=XMLConfig.GetValue('Complete/MainPPUExists',true);
MakefileValue:=XMLConfig.GetValue('Makefile/Value','');
if (MakefileValue='') then
stats^.ViaMakefile:=false
else begin
stats^.ViaMakefile:=true;
MakefileVersion:=StrToIntDef(MakefileValue,0);
if MakefileVersion<2 then begin
// old versions used %(
stats^.CompilerFilename:=StringReplace(stats^.CompilerFilename,'%(','$(',[rfReplaceAll]);
stats^.Params:=StringReplace(stats^.Params,'%(','$(',[rfReplaceAll]);
end;
ForcePathDelims(stats^.CompilerFilename);
ForcePathDelims(stats^.Params);
end;
finally
XMLConfig.Free;
end;
stats^.StateFileName:=StateFile;
stats^.StateFileDate:=StateFileAge;
stats^.StateFileLoaded:=true;
except
on E: EXMLReadError do begin
// invalid XML
debugln(['Warning: (lazarus) package "',APackage.IDAsString,'": syntax error in ',StateFile,' => need clean build.']);
stats^.Complete:=false;
stats^.CompilerFilename:='';
stats^.StateFileName:=StateFile;
stats^.StateFileDate:=StateFileAge;
stats^.StateFileLoaded:=true;
end;
on E: Exception do begin
if IgnoreErrors then begin
Result:=mrOk;
end else begin
Result:=IDEMessageDialogAb(lisPkgMangErrorReadingFile,
Format(lisPkgMangUnableToReadStateFileOfPackageError,
[StateFile, LineEnding, APackage.IDAsString, LineEnding, E.Message]),
mtError,[mbCancel],ShowAbort);
end;
exit;
end;
end;
end;
Result:=mrOk;
end; end;
function TLazPackageGraph.CheckCompileNeedDueToFPCUnits(TheOwner: TObject; function TLazPackageGraph.CheckCompileNeedDueToFPCUnits(TheOwner: TObject;
@ -3454,13 +3387,14 @@ begin
if Dependency.DependencyType=pdtFPMake if Dependency.DependencyType=pdtFPMake
then begin then begin
// skip // skip
end else if SkipDesignTimePackages and (RequiredPackage.PackageType=lptDesignTime) end else if SkipDesignTimePackages and (RequiredPackage.PackageType=lptDesignTime) then
then begin
// skip // skip
end else begin else if RequiredPackage.IsVirtual then
// skip
else if RequiredPackage.Missing then
// skip
else begin
// check compile state file of required package // check compile state file of required package
if (not RequiredPackage.IsVirtual) and (not RequiredPackage.Missing)
then begin
Result:=LoadPackageCompiledState(RequiredPackage,false,true); Result:=LoadPackageCompiledState(RequiredPackage,false,true);
if Result<>mrOk then begin if Result<>mrOk then begin
// file broken, user was told that file is broken and user had a // file broken, user was told that file is broken and user had a
@ -3509,7 +3443,6 @@ begin
end; end;
end; end;
end; end;
end;
Dependency:=Dependency.NextRequiresDependency; Dependency:=Dependency.NextRequiresDependency;
end; end;
Result:=mrNo; Result:=mrNo;
@ -3524,7 +3457,7 @@ var
ConfigChanged: boolean; ConfigChanged: boolean;
DependenciesChanged: boolean; DependenciesChanged: boolean;
DefResult: TModalResult; DefResult: TModalResult;
OldNeedBuildAllFlag: Boolean; OldNeedBuildAllFlag, IsDefDirWritable: Boolean;
OldOverride: String; OldOverride: String;
begin begin
Result:=mrYes; Result:=mrYes;
@ -3546,11 +3479,13 @@ begin
end; end;
// the current output directory needs compilation // the current output directory needs compilation
OutputDir:=APackage.GetOutputDirectory(false);
IsDefDirWritable:=OutputDirectoryIsWritable(APackage,OutputDir,false);
if APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride='' then if APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride='' then
begin begin
// the last compile was put to the normal/default output directory // the last compile was put to the normal/default output directory
OutputDir:=APackage.GetOutputDirectory(false); if IsDefDirWritable then
if OutputDirectoryIsWritable(APackage,OutputDir,false) then
begin begin
// the normal output directory is writable => keep using it // the normal output directory is writable => keep using it
exit; exit;
@ -3570,6 +3505,8 @@ begin
NeedBuildAllFlag,ConfigChanged,DependenciesChanged,Note); NeedBuildAllFlag,ConfigChanged,DependenciesChanged,Note);
end else begin end else begin
// the last compile was put to the fallback output directory // the last compile was put to the fallback output directory
if not IsDefDirWritable then begin
if not ConfigChanged then begin if not ConfigChanged then begin
// some source files have changed, not the compiler parameters // some source files have changed, not the compiler parameters
// => keep using the fallback directory // => keep using the fallback directory
@ -3583,20 +3520,26 @@ begin
end; end;
// maybe the user switched the settings back to default // maybe the user switched the settings back to default
// => try using the default output directory // => try using the default output directory
end;
OldOverride:=APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride; OldOverride:=APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride;
APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride:=''; APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride:='';
if ConsoleVerbosity>=0 then
debugln(['Hint: (lazarus) trying the default output directory of package ',APackage.IDAsString]);
OldNeedBuildAllFlag:=NeedBuildAllFlag; OldNeedBuildAllFlag:=NeedBuildAllFlag;
DefResult:=CheckIfCurPkgOutDirNeedsCompile(APackage, DefResult:=CheckIfCurPkgOutDirNeedsCompile(APackage,
true,SkipDesignTimePackages,GroupCompile, true,SkipDesignTimePackages,GroupCompile,
NeedBuildAllFlag,ConfigChanged,DependenciesChanged,Note); NeedBuildAllFlag,ConfigChanged,DependenciesChanged,Note);
if DefResult=mrNo then begin if IsDefDirWritable or (DefResult=mrNo) then begin
// switching back to the not writable output directory requires no compile // switching back to the default output directory
debugln(['Hint: (lazarus) switching back to the normal output directory: "',APackage.GetOutputDirectory,'" Package ',APackage.IDAsString]); debugln(['Hint: (lazarus) switching back to the normal output directory: "',APackage.GetOutputDirectory,'" Package ',APackage.IDAsString]);
Note+='Switching back to not writable output directory.'+LineEnding; Note+='Switching back to default output directory.'+LineEnding;
exit(mrNo); exit(DefResult);
end; end;
// neither the default nor the fallback is valid // neither the default nor the fallback is valid
// => switch back to the fallback // => switch back to the fallback
if ConsoleVerbosity>=0 then
debugln(['Hint: (lazarus) switching back to fallback output directory package ',APackage.IDAsString]);
APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride:=OldOverride; APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride:=OldOverride;
NeedBuildAllFlag:=OldNeedBuildAllFlag; NeedBuildAllFlag:=OldNeedBuildAllFlag;
end; end;
@ -3618,7 +3561,7 @@ var
OldValue: string; OldValue: string;
NewValue: string; NewValue: string;
o: TPkgOutputDir; o: TPkgOutputDir;
Stats: PPkgLastCompileStats; Stats: TPkgLastCompileStats;
SrcPPUFile: String; SrcPPUFile: String;
AFilename: String; AFilename: String;
CompilerFilename, CompilerParams, SrcFilename: string; CompilerFilename, CompilerParams, SrcFilename: string;
@ -3642,14 +3585,14 @@ begin
CompilerParams:=GetPackageCompilerParams(APackage); CompilerParams:=GetPackageCompilerParams(APackage);
o:=APackage.GetOutputDirType; o:=APackage.GetOutputDirType;
Stats:=@APackage.LastCompile[o]; Stats:=APackage.LastCompile[o];
//debugln(['TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Last="',ExtractCompilerParamsForBuildAll(APackage.LastCompilerParams),'" Now="',ExtractCompilerParamsForBuildAll(CompilerParams),'"']); //debugln(['TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Last="',ExtractCompilerParamsForBuildAll(APackage.LastCompilerParams),'" Now="',ExtractCompilerParamsForBuildAll(CompilerParams),'"']);
// check state file // check state file
StateFilename:=APackage.GetStateFilename; StateFilename:=APackage.GetStateFilename;
Result:=LoadPackageCompiledState(APackage,false,true); Result:=LoadPackageCompiledState(APackage,false,true);
if Result<>mrOk then exit; // read error and user aborted if Result<>mrOk then exit; // read error and user aborted
if not Stats^.StateFileLoaded then begin if not Stats.StateFileLoaded then begin
// package was not compiled via Lazarus nor via Makefile/fpmake // package was not compiled via Lazarus nor via Makefile/fpmake
DebugLn('Hint: (lazarus) Missing state file of ',APackage.IDAsString,': ',StateFilename); DebugLn('Hint: (lazarus) Missing state file of ',APackage.IDAsString,': ',StateFilename);
Note+='Missing state file "'+StateFilename+'".'+LineEnding; Note+='Missing state file "'+StateFilename+'".'+LineEnding;
@ -3658,13 +3601,23 @@ begin
exit(mrYes); exit(mrYes);
end; end;
if (o=podFallback) and (Stats.LazarusVersion<>LazarusVersionStr) then
begin
// package in fallback directory was compiled by another Lazarus -> rebuild
DebugLn('Hint: (lazarus) State file of ',APackage.IDAsString,' from Lazarus "',Stats.LazarusVersion,'" instead of "',LazarusVersionStr,'": ',StateFilename);
Note+='State file "'+StateFilename+'" from another Lazarus version "'+Stats.LazarusVersion+'".'+LineEnding;
NeedBuildAllFlag:=true;
ConfigChanged:=true;
exit(mrYes);
end;
// check if build all (-B) is needed // check if build all (-B) is needed
if (Stats^.CompilerFilename<>CompilerFilename) if (Stats.CompilerFilename<>CompilerFilename)
or (ExtractFPCParamsForBuildAll(Stats^.Params) or (ExtractFPCParamsForBuildAll(Stats.Params)
<>ExtractFPCParamsForBuildAll(CompilerParams)) <>ExtractFPCParamsForBuildAll(CompilerParams))
or ((Stats^.CompilerFileDate>0) or ((Stats.CompilerFileDate>0)
and FileExistsCached(CompilerFilename) and FileExistsCached(CompilerFilename)
and (FileAgeCached(CompilerFilename)<>Stats^.CompilerFileDate)) and (FileAgeCached(CompilerFilename)<>Stats.CompilerFileDate))
then begin then begin
NeedBuildAllFlag:=true; NeedBuildAllFlag:=true;
ConfigChanged:=true; ConfigChanged:=true;
@ -3681,7 +3634,7 @@ begin
// check compiler and params // check compiler and params
LastParams:=APackage.GetLastCompilerParams(o); LastParams:=APackage.GetLastCompilerParams(o);
if Stats^.ViaMakefile then begin if Stats.ViaMakefile then begin
// the package was compiled via Makefile/fpmake // the package was compiled via Makefile/fpmake
if ConsoleVerbosity>=1 then if ConsoleVerbosity>=1 then
debugln(['Hint: (lazarus) package ',APackage.IDAsString,' was compiled via "make" with parameters "',LastParams,'"']); debugln(['Hint: (lazarus) package ',APackage.IDAsString,' was compiled via "make" with parameters "',LastParams,'"']);
@ -3700,11 +3653,11 @@ begin
DebugLn('Hint: (lazarus) Compiler custom params changed for ',APackage.IDAsString); DebugLn('Hint: (lazarus) Compiler custom params changed for ',APackage.IDAsString);
DebugLn(' Old="',OldValue,'"'); DebugLn(' Old="',OldValue,'"');
DebugLn(' Now="',NewValue,'"'); DebugLn(' Now="',NewValue,'"');
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='Compiler custom parameters changed:'+LineEnding Note+='Compiler custom parameters changed:'+LineEnding
+' Old="'+OldValue+'"'+LineEnding +' Old="'+OldValue+'"'+LineEnding
+' Now="'+NewValue+'"'+LineEnding +' Now="'+NewValue+'"'+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding; +' State file="'+Stats.StateFileName+'"'+LineEnding;
ConfigChanged:=true; ConfigChanged:=true;
exit(mrYes); exit(mrYes);
end; end;
@ -3715,11 +3668,11 @@ begin
DebugLn('Hint: (lazarus) Compiler unit paths changed for ',APackage.IDAsString); DebugLn('Hint: (lazarus) Compiler unit paths changed for ',APackage.IDAsString);
DebugLn(' Old="',OldValue,'"'); DebugLn(' Old="',OldValue,'"');
DebugLn(' Now="',NewValue,'"'); DebugLn(' Now="',NewValue,'"');
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='Compiler unit paths changed:'+LineEnding Note+='Compiler unit paths changed:'+LineEnding
+' Old="'+OldValue+'"'+LineEnding +' Old="'+OldValue+'"'+LineEnding
+' Now="'+NewValue+'"'+LineEnding +' Now="'+NewValue+'"'+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding; +' State file="'+Stats.StateFileName+'"'+LineEnding;
ConfigChanged:=true; ConfigChanged:=true;
exit(mrYes); exit(mrYes);
end; end;
@ -3730,11 +3683,11 @@ begin
DebugLn('Hint: (lazarus) Compiler include paths changed for ',APackage.IDAsString); DebugLn('Hint: (lazarus) Compiler include paths changed for ',APackage.IDAsString);
DebugLn(' Old="',OldValue,'"'); DebugLn(' Old="',OldValue,'"');
DebugLn(' Now="',NewValue,'"'); DebugLn(' Now="',NewValue,'"');
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='Compiler include paths changed:'+LineEnding Note+='Compiler include paths changed:'+LineEnding
+' Old="'+OldValue+'"'+LineEnding +' Old="'+OldValue+'"'+LineEnding
+' Now="'+NewValue+'"'+LineEnding +' Now="'+NewValue+'"'+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding; +' State file="'+Stats.StateFileName+'"'+LineEnding;
ConfigChanged:=true; ConfigChanged:=true;
exit(mrYes); exit(mrYes);
end; end;
@ -3750,44 +3703,44 @@ begin
DebugLn('Hint: (lazarus) Compiler params changed for ',APackage.IDAsString); DebugLn('Hint: (lazarus) Compiler params changed for ',APackage.IDAsString);
DebugLn(' Old="',dbgstr(ReducedLastParams),'"'); DebugLn(' Old="',dbgstr(ReducedLastParams),'"');
DebugLn(' Now="',dbgstr(ReducedParams),'"'); DebugLn(' Now="',dbgstr(ReducedParams),'"');
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='Compiler parameters changed:'+LineEnding Note+='Compiler parameters changed:'+LineEnding
+' Old="'+dbgstr(ReducedLastParams)+'"'+LineEnding +' Old="'+dbgstr(ReducedLastParams)+'"'+LineEnding
+' Now="'+dbgstr(ReducedParams)+'"'+LineEnding +' Now="'+dbgstr(ReducedParams)+'"'+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding; +' State file="'+Stats.StateFileName+'"'+LineEnding;
ConfigChanged:=true; ConfigChanged:=true;
exit(mrYes); exit(mrYes);
end; end;
end; end;
if (not Stats^.ViaMakefile) if (not Stats.ViaMakefile)
and (CompilerFilename<>Stats^.CompilerFilename) then begin and (CompilerFilename<>Stats.CompilerFilename) then begin
DebugLn('Hint: (lazarus) Compiler filename changed for ',APackage.IDAsString); DebugLn('Hint: (lazarus) Compiler filename changed for ',APackage.IDAsString);
DebugLn(' Old="',Stats^.CompilerFilename,'"'); DebugLn(' Old="',Stats.CompilerFilename,'"');
DebugLn(' Now="',CompilerFilename,'"'); DebugLn(' Now="',CompilerFilename,'"');
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='Compiler filename changed:'+LineEnding Note+='Compiler filename changed:'+LineEnding
+' Old="'+Stats^.CompilerFilename+'"'+LineEnding +' Old="'+Stats.CompilerFilename+'"'+LineEnding
+' Now="'+CompilerFilename+'"'+LineEnding +' Now="'+CompilerFilename+'"'+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding; +' State file="'+Stats.StateFileName+'"'+LineEnding;
exit(mrYes); exit(mrYes);
end; end;
if not FileExistsCached(CompilerFilename) then begin if not FileExistsCached(CompilerFilename) then begin
DebugLn('Hint: (lazarus) Compiler filename not found for ',APackage.IDAsString); DebugLn('Hint: (lazarus) Compiler filename not found for ',APackage.IDAsString);
DebugLn(' File="',CompilerFilename,'"'); DebugLn(' File="',CompilerFilename,'"');
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='Compiler file "'+CompilerFilename+'" not found.'+LineEnding Note+='Compiler file "'+CompilerFilename+'" not found.'+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding; +' State file="'+Stats.StateFileName+'"'+LineEnding;
exit(mrYes); exit(mrYes);
end; end;
if (not Stats^.ViaMakefile) if (not Stats.ViaMakefile)
and (FileAgeCached(CompilerFilename)<>Stats^.CompilerFileDate) then begin and (FileAgeCached(CompilerFilename)<>Stats.CompilerFileDate) then begin
DebugLn('Hint: (lazarus) Compiler file changed for ',APackage.IDAsString); DebugLn('Hint: (lazarus) Compiler file changed for ',APackage.IDAsString);
DebugLn(' File="',CompilerFilename,'"'); DebugLn(' File="',CompilerFilename,'"');
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='Compiler file "'+CompilerFilename+'" changed:'+LineEnding Note+='Compiler file "'+CompilerFilename+'" changed:'+LineEnding
+' Old='+FileAgeToStr(Stats^.CompilerFileDate)+LineEnding +' Old='+FileAgeToStr(Stats.CompilerFileDate)+LineEnding
+' Now='+FileAgeToStr(FileAgeCached(CompilerFilename))+LineEnding +' Now='+FileAgeToStr(FileAgeCached(CompilerFilename))+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding; +' State file="'+Stats.StateFileName+'"'+LineEnding;
exit(mrYes); exit(mrYes);
end; end;
@ -3803,7 +3756,7 @@ begin
DebugLn('Hint: (lazarus) source disk file modified of ',APackage.IDAsString,': ',SrcFilename); DebugLn('Hint: (lazarus) source disk file modified of ',APackage.IDAsString,': ',SrcFilename);
Note+='Source file "'+SrcFilename+'" modified:'+LineEnding Note+='Source file "'+SrcFilename+'" modified:'+LineEnding
+' Source file age='+FileAgeToStr(FileAgeCached(SrcFilename))+LineEnding +' Source file age='+FileAgeToStr(FileAgeCached(SrcFilename))+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding +' State file="'+Stats.StateFileName+'"'+LineEnding
+' State file age='+FileAgeToStr(StateFileAge)+LineEnding; +' State file age='+FileAgeToStr(StateFileAge)+LineEnding;
exit(mrYes); exit(mrYes);
end; end;
@ -3813,7 +3766,7 @@ begin
exit(mrYes); exit(mrYes);
end; end;
// check main source ppu file // check main source ppu file
if Stats^.MainPPUExists then begin if Stats.MainPPUExists then begin
SrcPPUFile:=APackage.GetSrcPPUFilename; SrcPPUFile:=APackage.GetSrcPPUFilename;
if not FileExistsCached(SrcPPUFile) then begin if not FileExistsCached(SrcPPUFile) then begin
DebugLn('Hint: (lazarus) main ppu file missing of ',APackage.IDAsString,': ',SrcPPUFile); DebugLn('Hint: (lazarus) main ppu file missing of ',APackage.IDAsString,': ',SrcPPUFile);
@ -3830,11 +3783,11 @@ begin
// quick compile is possible // quick compile is possible
NeedBuildAllFlag:=false; NeedBuildAllFlag:=false;
if not Stats^.Complete then begin if not Stats.Complete then begin
DebugLn('Hint: (lazarus) Last compile was incomplete for ',APackage.IDAsString); DebugLn('Hint: (lazarus) Last compile was incomplete for ',APackage.IDAsString);
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='Last compile was incomplete.'+LineEnding Note+='Last compile was incomplete.'+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding; +' State file="'+Stats.StateFileName+'"'+LineEnding;
exit(mrYes); exit(mrYes);
end; end;
@ -3852,10 +3805,10 @@ begin
// check package files // check package files
if StateFileAge<FileAgeCached(APackage.Filename) then begin if StateFileAge<FileAgeCached(APackage.Filename) then begin
DebugLn('Hint: (lazarus) State file older than lpk ',APackage.IDAsString); DebugLn('Hint: (lazarus) State file older than lpk ',APackage.IDAsString);
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='State file older than lpk:'+LineEnding Note+='State file older than lpk:'+LineEnding
+' State file age='+FileAgeToStr(StateFileAge)+LineEnding +' State file age='+FileAgeToStr(StateFileAge)+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding +' State file="'+Stats.StateFileName+'"'+LineEnding
+' LPK age='+FileAgeToStr(FileAgeCached(APackage.Filename))+LineEnding; +' LPK age='+FileAgeToStr(FileAgeCached(APackage.Filename))+LineEnding;
exit(mrYes); exit(mrYes);
end; end;
@ -3870,10 +3823,10 @@ begin
if FileExistsCached(AFilename) if FileExistsCached(AFilename)
and (StateFileAge<FileAgeCached(AFilename)) then begin and (StateFileAge<FileAgeCached(AFilename)) then begin
DebugLn('Hint: (lazarus) Source file has changed ',APackage.IDAsString,' ',CurFile.Filename); DebugLn('Hint: (lazarus) Source file has changed ',APackage.IDAsString,' ',CurFile.Filename);
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='State file older than source "'+AFilename+'"'+LineEnding Note+='State file older than source "'+AFilename+'"'+LineEnding
+' State file age='+FileAgeToStr(StateFileAge)+LineEnding +' State file age='+FileAgeToStr(StateFileAge)+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding +' State file="'+Stats.StateFileName+'"'+LineEnding
+' Src file age='+FileAgeToStr(FileAgeCached(AFilename))+LineEnding; +' Src file age='+FileAgeToStr(FileAgeCached(AFilename))+LineEnding;
exit(mrYes); exit(mrYes);
end; end;
@ -3882,10 +3835,10 @@ begin
if FileExistsCached(LFMFilename) if FileExistsCached(LFMFilename)
and (StateFileAge<FileAgeCached(LFMFilename)) then begin and (StateFileAge<FileAgeCached(LFMFilename)) then begin
DebugLn('Hint: (lazarus) LFM has changed ',APackage.IDAsString,' ',LFMFilename); DebugLn('Hint: (lazarus) LFM has changed ',APackage.IDAsString,' ',LFMFilename);
DebugLn(' State file="',Stats^.StateFileName,'"'); DebugLn(' State file="',Stats.StateFileName,'"');
Note+='State file older than resource "'+LFMFilename+'"'+LineEnding Note+='State file older than resource "'+LFMFilename+'"'+LineEnding
+' State file age='+FileAgeToStr(StateFileAge)+LineEnding +' State file age='+FileAgeToStr(StateFileAge)+LineEnding
+' State file="'+Stats^.StateFileName+'"'+LineEnding +' State file="'+Stats.StateFileName+'"'+LineEnding
+' Resource file age='+FileAgeToStr(FileAgeCached(LFMFilename))+LineEnding; +' Resource file age='+FileAgeToStr(FileAgeCached(LFMFilename))+LineEnding;
exit(mrYes); exit(mrYes);
end; end;
@ -3898,6 +3851,89 @@ begin
Result:=mrNo; Result:=mrNo;
end; end;
function TLazPackageGraph.LoadPackageCompiledStateFile(APackage: TLazPackage;
o: TPkgOutputDir; StateFile: string; IgnoreErrors, ShowAbort: boolean
): TModalResult;
var
Stats: TPkgLastCompileStats;
StateFileAge, MakefileVersion: LongInt;
XMLConfig: TXMLConfig;
MakefileValue, Params: String;
begin
Stats:=APackage.LastCompile[o];
if not FileExistsCached(StateFile) then begin
//DebugLn('TLazPackageGraph.LoadPackageCompiledStateFile file not found: ',StateFile);
Stats.StateFileLoaded:=false;
Result:=mrOk;
exit;
end;
// read the state file
StateFileAge:=FileAgeCached(StateFile);
if (not Stats.StateFileLoaded)
or (Stats.StateFileDate<>StateFileAge)
or (Stats.StateFileName<>StateFile) then begin
Stats.StateFileLoaded:=false;
Stats.LazarusVersion:='';
Stats.Complete:=false;
Stats.CompilerFilename:='';
Stats.StateFileName:=StateFile;
Stats.StateFileDate:=StateFileAge;
try
XMLConfig:=TXMLConfig.Create(StateFile);
try
Stats.LazarusVersion:=XMLConfig.GetValue('Lazarus/Version','');
Stats.CompilerFilename:=XMLConfig.GetValue('Compiler/Value','');
Stats.CompilerFileDate:=XMLConfig.GetValue('Compiler/Date',0);
Stats.Complete:=XMLConfig.GetValue('Complete/Value',true);
Stats.MainPPUExists:=XMLConfig.GetValue('Complete/MainPPUExists',true);
MakefileValue:=XMLConfig.GetValue('Makefile/Value','');
Params:=XMLConfig.GetValue('Params/Value','');
if (MakefileValue='') then
Stats.ViaMakefile:=false
else begin
Stats.ViaMakefile:=true;
MakefileVersion:=StrToIntDef(MakefileValue,0);
if MakefileVersion<2 then begin
// old versions used %(
Stats.CompilerFilename:=StringReplace(Stats.CompilerFilename,'%(','$(',[rfReplaceAll]);
Params:=StringReplace(Params,'%(','$(',[rfReplaceAll]);
end;
ForcePathDelims(Stats.CompilerFilename);
ForcePathDelims(Params);
Params:=StringReplace(Params,'$(CPU_TARGET)','$(TargetCPU)',[rfReplaceAll]);
Params:=StringReplace(Params,'$(OS_TARGET)','$(TargetOS)',[rfReplaceAll]);
Params:=StringReplace(Params,'$(LCL_PLATFORM)','$(LCLWidgetType)',[rfReplaceAll]);
Params:=APackage.SubstitutePkgMacros(Params,false);
end;
Stats.Params:=Params;
finally
XMLConfig.Free;
end;
Stats.StateFileLoaded:=true;
except
on E: EXMLReadError do begin
// invalid XML
debugln(['Warning: (lazarus) package "',APackage.IDAsString,'": syntax error in ',StateFile,' => need clean build.']);
Stats.StateFileLoaded:=true;
end;
on E: Exception do begin
if IgnoreErrors then begin
Result:=mrOk;
end else begin
Result:=IDEMessageDialogAb(lisPkgMangErrorReadingFile,
Format(lisPkgMangUnableToReadStateFileOfPackageError,
[StateFile, LineEnding, APackage.IDAsString, LineEnding, E.Message]),
mtError,[mbCancel],ShowAbort);
end;
exit;
end;
end;
end;
Result:=mrOk;
end;
procedure TLazPackageGraph.InvalidateStateFile(APackage: TLazPackage); procedure TLazPackageGraph.InvalidateStateFile(APackage: TLazPackage);
begin begin
APackage.LastCompile[APackage.GetOutputDirType].StateFileLoaded:=false APackage.LastCompile[APackage.GetOutputDirType].StateFileLoaded:=false
@ -5237,13 +5273,12 @@ end;
function TLazPackageGraph.PreparePackageOutputDirectory(APackage: TLazPackage; function TLazPackageGraph.PreparePackageOutputDirectory(APackage: TLazPackage;
CleanUp: boolean): TModalResult; CleanUp: boolean): TModalResult;
var var
OutputDir: String; OutputDir, NewOutputDir: String;
StateFile: String; StateFile: String;
PkgSrcDir: String; PkgSrcDir: String;
i: Integer; i: Integer;
CurFile: TPkgFile; CurFile: TPkgFile;
OutputFileName: String; OutputFileName: String;
NewOutputDir: String;
DeleteAllFilesInOutputDir: Boolean; DeleteAllFilesInOutputDir: Boolean;
DirCache: TCTDirectoryCache; DirCache: TCTDirectoryCache;
CleanFiles: TStrings; CleanFiles: TStrings;
@ -5252,30 +5287,26 @@ begin
OutputDir:=APackage.GetOutputDirectory; OutputDir:=APackage.GetOutputDirectory;
//debugln(['TLazPackageGraph.PreparePackageOutputDirectory OutputDir="',OutputDir,'"']); //debugln(['TLazPackageGraph.PreparePackageOutputDirectory OutputDir="',OutputDir,'"']);
// Note: The OutputDirectoryOverride is set prior in CheckIfPackageNeedsCompilation
DeleteAllFilesInOutputDir:=false; DeleteAllFilesInOutputDir:=false;
if not OutputDirectoryIsWritable(APackage,OutputDir,false) then if not OutputDirectoryIsWritable(APackage,OutputDir,false) then
begin begin
// the normal output directory is not writable // the output directory is not writable
// => use the fallback directory debugln(['Error: (lazarus) [TLazPackageGraph.PreparePackageOutputDirectory] failed to create writable directory (',APackage.IDAsString,'): ',OutputDir]);
NewOutputDir:=GetFallbackOutputDir(APackage);
if (NewOutputDir=OutputDir) or (NewOutputDir='') then begin
debugln(['Error: (lazarus) [TLazPackageGraph.PreparePackageOutputDirectory] failed to create writable directory: ',OutputDir]);
exit(mrCancel);
end;
APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride:=NewOutputDir;
OutputDir:=APackage.GetOutputDirectory;
if not OutputDirectoryIsWritable(APackage,OutputDir,true) then
begin
debugln(['Error: (lazarus) [TLazPackageGraph.PreparePackageOutputDirectory] failed to create writable directory: ',OutputDir]);
Result:=mrCancel; Result:=mrCancel;
end;
DeleteAllFilesInOutputDir:=true;
end else if APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride<>'' end else if APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride<>''
then then
// package is already using the fallback directory // package is already using the fallback directory
DeleteAllFilesInOutputDir:=true DeleteAllFilesInOutputDir:=true
else if CleanUp then begin else if CleanUp then begin
// package is not using the fallback directory // package is not using the fallback directory
// delete fallback if it exists
NewOutputDir:=GetFallbackOutputDir(APackage);
if DirPathExistsCached(NewOutputDir) then
DeleteDirectory(NewOutputDir,false);
// check if the output directory contains sources // check if the output directory contains sources
DeleteAllFilesInOutputDir:=APackage.HasSeparateOutputDirectory; DeleteAllFilesInOutputDir:=APackage.HasSeparateOutputDirectory;
end; end;