mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-10-21 00:04:13 +02:00
IDE: moved package compile code to packagesystem, IDEIntf: removed IsPartOfProject flag of Backup functions, lazbuidl: package compiling
git-svn-id: trunk@9821 -
This commit is contained in:
parent
cbbc16493d
commit
f7855da268
@ -102,7 +102,7 @@ const
|
||||
'i386', 'powerpc', 'm68k', 'x86_64', 'sparc', 'arm'
|
||||
);
|
||||
|
||||
Lazarus_CPU_OS_Widget_Combinations: array[1..31] of string = (
|
||||
Lazarus_CPU_OS_Widget_Combinations: array[1..31] of shortstring = (
|
||||
'i386-linux-gtk',
|
||||
'i386-linux-gnome',
|
||||
'i386-linux-gtk2',
|
||||
|
@ -1823,11 +1823,11 @@ begin
|
||||
for i:=Low(Args) to High(Args) do begin
|
||||
case Args[i].VType of
|
||||
vtInteger: DbgOut(dbgs(Args[i].vinteger));
|
||||
vtInt64: DbgOut(dbgs(Args[i].VInt64));
|
||||
vtQWord: DbgOut(dbgs(Args[i].VQWord));
|
||||
vtInt64: DbgOut(dbgs(Args[i].VInt64^));
|
||||
vtQWord: DbgOut(dbgs(Args[i].VQWord^));
|
||||
vtBoolean: DbgOut(dbgs(Args[i].vboolean));
|
||||
vtExtended: DbgOut(dbgs(Args[i].VExtended^));
|
||||
vtCurrency: DbgOut(dbgs(Args[i].vCurrency));
|
||||
vtCurrency: DbgOut(dbgs(Args[i].vCurrency^));
|
||||
vtString: DbgOut(Args[i].VString^);
|
||||
vtAnsiString: DbgOut(AnsiString(Args[i].VAnsiString));
|
||||
vtChar: DbgOut(Args[i].VChar);
|
||||
|
@ -1188,13 +1188,13 @@ begin
|
||||
mtError,[mbCancel,mbAbort],'');
|
||||
exit;
|
||||
end;
|
||||
|
||||
|
||||
TextConverter:=TIDETextConverter.Create(nil);
|
||||
try
|
||||
TextConverter.Filename:=TempCHeaderFilename;
|
||||
FLastUsedFilename:=TextConverter.Filename;
|
||||
TextConverter.LoadFromFile(InputFilename);
|
||||
DebugLn(['TH2PasConverter.ConvertFile TempCHeaderFilename="',TempCHeaderFilename,'" CurrentType=',ord(TextConverter.CurrentType),' ',FileSize(TempCHeaderFilename)]);
|
||||
DebugLn(['TH2PasConverter.ConvertFile TempCHeaderFilename="',TempCHeaderFilename,'" CurrentType=',ord(TextConverter.CurrentType),' FileSize=',FileSize(TempCHeaderFilename)]);
|
||||
|
||||
// run converters for .h file to make it compatible for h2pas
|
||||
Result:=TextConverter.Execute(Project.PreH2PasTools);
|
||||
@ -1208,9 +1208,9 @@ begin
|
||||
try
|
||||
Tool.Title:='h2pas';
|
||||
Tool.H2PasFile:=AFile;
|
||||
DebugLn(['TH2PasConverter.ConvertFile AAA TempCHeaderFilename="',TempCHeaderFilename,'" CurrentType=',ord(TextConverter.CurrentType),' ',FileSize(TempCHeaderFilename)]);
|
||||
DebugLn(['TH2PasConverter.ConvertFile AAA TempCHeaderFilename="',TempCHeaderFilename,'" CurrentType=',ord(TextConverter.CurrentType),' FileSize=',FileSize(TempCHeaderFilename)]);
|
||||
Tool.TargetFilename:=TextConverter.Filename;
|
||||
DebugLn(['TH2PasConverter.ConvertFile BBB TempCHeaderFilename="',TempCHeaderFilename,'" CurrentType=',ord(TextConverter.CurrentType),' ',FileSize(TempCHeaderFilename)]);
|
||||
DebugLn(['TH2PasConverter.ConvertFile BBB TempCHeaderFilename="',TempCHeaderFilename,'" CurrentType=',ord(TextConverter.CurrentType),' FileSize=',FileSize(TempCHeaderFilename)]);
|
||||
Tool.Filename:=GetH2PasFilename;
|
||||
Tool.CmdLineParams:=AFile.GetH2PasParameters(Tool.TargetFilename);
|
||||
Tool.ScanOutput:=true;
|
||||
@ -1218,7 +1218,7 @@ begin
|
||||
Tool.WorkingDirectory:=Project.BaseDir;
|
||||
Tool.OnParseLine:=@OnParseH2PasLine;
|
||||
DebugLn(['TH2PasConverter.ConvertFile Tool.Filename="',Tool.Filename,'" Tool.CmdLineParams="',Tool.CmdLineParams,'"']);
|
||||
Result:=LazarusIDE.RunExternalTool(Tool);
|
||||
Result:=RunExternalTool(Tool);
|
||||
if Result<>mrOk then exit(mrAbort);
|
||||
if FindH2PasErrorMessage>=0 then exit(mrAbort);
|
||||
finally
|
||||
|
@ -153,6 +153,7 @@ var
|
||||
Tool: TCustomTextConverterTool;
|
||||
begin
|
||||
Tool:=GetCurrentTool;
|
||||
//DebugLn(['TTextConvListEditor.PropertyGridModified ',dbgsName(Tool)]);
|
||||
if Tool=nil then exit;
|
||||
MakeToolCaptionAndNameUnique(Tool);
|
||||
Modified:=true;
|
||||
@ -265,6 +266,7 @@ begin
|
||||
for i:=0 to FListOfTools.ComponentCount-1 do begin
|
||||
Tool:=FListOfTools.Components[i] as TCustomTextConverterTool;
|
||||
sl.Add(Tool.Caption);
|
||||
//DebugLn(['TTextConvListEditor.UpdateToolsListBox Caption=',Tool.Caption,' ',dbgsName(Tool)]);
|
||||
end;
|
||||
end;
|
||||
// save selection
|
||||
@ -320,7 +322,8 @@ begin
|
||||
Result:=TCustomTextConverterTool(FListOfTools.Components[i]);
|
||||
end;
|
||||
|
||||
procedure TTextConvListEditor.MakeToolCaptionUnique(NewTool: TCustomTextConverterTool);
|
||||
procedure TTextConvListEditor.MakeToolCaptionUnique(
|
||||
NewTool: TCustomTextConverterTool);
|
||||
var
|
||||
NewCaption: String;
|
||||
|
||||
@ -337,6 +340,15 @@ var
|
||||
end;
|
||||
Result:=true;
|
||||
NewTool.Caption:=NewCaption;
|
||||
if (FListOfTools<>nil) then begin
|
||||
for i:=0 to FListOfTools.ComponentCount-1 do begin
|
||||
if FListOfTools.Components[i]=NewTool then begin
|
||||
if (i<ToolsListBox.Items.Count) then begin
|
||||
ToolsListBox.Items[i]:=NewTool.Caption;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
|
@ -734,7 +734,7 @@ begin
|
||||
if LFMCode<>nil then begin
|
||||
// save LFM file
|
||||
DebugLn('ConvertDelphiToLazarusUnit Save LFM');
|
||||
Result:=MainIDEInterface.DoSaveCodeBufferToFile(LFMCode,LFMCode.Filename,false);
|
||||
Result:=SaveCodeBufferToFile(LFMCode,LFMCode.Filename);
|
||||
if Result<>mrOk then exit;
|
||||
|
||||
// convert lfm to lrs
|
||||
|
@ -33,7 +33,8 @@ unit BaseBuildManager;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Project;
|
||||
Classes, SysUtils, Forms,
|
||||
Project;
|
||||
|
||||
type
|
||||
|
||||
@ -56,6 +57,16 @@ type
|
||||
function GetTestBuildDirectory: string; virtual; abstract;
|
||||
function IsTestUnitFilename(const AFilename: string): boolean; virtual; abstract;
|
||||
function GetTargetUnitFilename(AnUnitInfo: TUnitInfo): string; virtual; abstract;
|
||||
|
||||
function CheckAmbiguousSources(const AFilename: string;
|
||||
Compiling: boolean): TModalResult; virtual; abstract;
|
||||
function DeleteAmbiguousFiles(const Filename:string
|
||||
): TModalResult; virtual; abstract;
|
||||
function CheckUnitPathForAmbiguousPascalFiles(const BaseDir, TheUnitPath,
|
||||
CompiledExt, ContextDescription: string
|
||||
): TModalResult; virtual; abstract;
|
||||
|
||||
function BackupFile(const Filename: string): TModalResult; virtual; abstract;
|
||||
end;
|
||||
|
||||
var
|
||||
|
@ -33,13 +33,13 @@ unit BuildManager;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils,
|
||||
Classes, SysUtils, AVL_Tree,
|
||||
// LCL
|
||||
LCLProc, Dialogs, FileUtil,
|
||||
LCLProc, Dialogs, FileUtil, Forms, Controls,
|
||||
// codetools
|
||||
CodeToolManager, DefineTemplates,
|
||||
// IDEIntf
|
||||
MacroIntf, IDEDialogs,
|
||||
SrcEditorIntf, ProjectIntf, MacroIntf, IDEDialogs, IDEExternToolIntf,
|
||||
// IDE
|
||||
LazarusIDEStrConsts, DialogProcs, IDEProcs, CodeToolsOptions, InputHistory,
|
||||
MiscOptions, LazConf, EnvironmentOpts, TransferMacros, CompilerOptions,
|
||||
@ -89,6 +89,8 @@ type
|
||||
function CTMacroFuncProjectIncPath(Data: Pointer): boolean;
|
||||
function CTMacroFuncProjectSrcPath(Data: Pointer): boolean;
|
||||
procedure OnCmdLineCreate(var CmdLine: string; var Abort: boolean);
|
||||
function OnRunCompilerWithOptions(ExtTool: TIDEExternalToolOptions;
|
||||
CompOptions: TBaseCompilerOptions): TModalResult;
|
||||
protected
|
||||
OverrideTargetOS: string;
|
||||
OverrideTargetCPU: string;
|
||||
@ -118,6 +120,15 @@ type
|
||||
procedure GetFPCCompilerParamsForEnvironmentTest(out Params: string);
|
||||
procedure RescanCompilerDefines(OnlyIfCompilerChanged: boolean);
|
||||
|
||||
function CheckAmbiguousSources(const AFilename: string;
|
||||
Compiling: boolean): TModalResult; override;
|
||||
function DeleteAmbiguousFiles(const Filename:string
|
||||
): TModalResult; override;
|
||||
function CheckUnitPathForAmbiguousPascalFiles(const BaseDir, TheUnitPath,
|
||||
CompiledExt, ContextDescription: string
|
||||
): TModalResult; override;
|
||||
function BackupFile(const Filename: string): TModalResult; override;
|
||||
|
||||
// methods for building
|
||||
procedure SetBuildTarget(const TargetOS, TargetCPU, LCLWidgetType: string);
|
||||
procedure SetBuildTargetIDE;
|
||||
@ -130,6 +141,24 @@ var
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
TUnitFile = record
|
||||
UnitName: string;
|
||||
Filename: string;
|
||||
end;
|
||||
PUnitFile = ^TUnitFile;
|
||||
|
||||
function CompareUnitFiles(UnitFile1, UnitFile2: PUnitFile): integer;
|
||||
begin
|
||||
Result:=CompareText(UnitFile1^.UnitName,UnitFile2^.UnitName);
|
||||
end;
|
||||
|
||||
function CompareUnitNameAndUnitFile(UnitName: PChar;
|
||||
UnitFile: PUnitFile): integer;
|
||||
begin
|
||||
Result:=CompareStringPointerI(UnitName,PChar(UnitFile^.UnitName));
|
||||
end;
|
||||
|
||||
{ TBuildManager }
|
||||
|
||||
function TBuildManager.OnSubstituteCompilerOption(
|
||||
@ -142,18 +171,21 @@ begin
|
||||
GlobalMacroList.SubstituteStr(Result,CompilerOptionMacroPlatformIndependent)
|
||||
else
|
||||
GlobalMacroList.SubstituteStr(Result,CompilerOptionMacroNormal);
|
||||
if System.Pos('CompPath',UnparsedValue)>0 then
|
||||
DebugLn(['TBuildManager.OnSubstituteCompilerOption UnparsedValue="',UnparsedValue,'" Result="',Result,'" ',GlobalMacroList.FindByName('CompPath')<>nil]);
|
||||
end;
|
||||
|
||||
constructor TBuildManager.Create;
|
||||
begin
|
||||
MainBuildBoss:=Self;
|
||||
inherited Create;
|
||||
|
||||
OnBackupFileInteractive:=@BackupFile;
|
||||
RunCompilerWithOptions:=@OnRunCompilerWithOptions;
|
||||
end;
|
||||
|
||||
destructor TBuildManager.Destroy;
|
||||
begin
|
||||
OnBackupFileInteractive:=nil;
|
||||
|
||||
inherited Destroy;
|
||||
MainBuildBoss:=nil;
|
||||
end;
|
||||
@ -488,6 +520,404 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBuildManager.CheckAmbiguousSources(const AFilename: string;
|
||||
Compiling: boolean): TModalResult;
|
||||
|
||||
function DeleteAmbiguousFile(const AmbiguousFilename: string): TModalResult;
|
||||
begin
|
||||
if not DeleteFile(AmbiguousFilename) then begin
|
||||
Result:=IDEMessageDialog(lisErrorDeletingFile,
|
||||
Format(lisUnableToDeleteAmbiguousFile, ['"', AmbiguousFilename, '"']),
|
||||
mtError,[mbOk,mbAbort]);
|
||||
end else
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function RenameAmbiguousFile(const AmbiguousFilename: string): TModalResult;
|
||||
var
|
||||
NewFilename: string;
|
||||
begin
|
||||
NewFilename:=AmbiguousFilename+'.ambiguous';
|
||||
if not RenameFile(AmbiguousFilename,NewFilename) then
|
||||
begin
|
||||
Result:=IDEMessageDialog(lisErrorRenamingFile,
|
||||
Format(lisUnableToRenameAmbiguousFileTo, ['"', AmbiguousFilename, '"',
|
||||
#13, '"', NewFilename, '"']),
|
||||
mtError,[mbOk,mbAbort]);
|
||||
end else
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function AddCompileWarning(const AmbiguousFilename: string): TModalResult;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if Compiling then begin
|
||||
TheOutputFilter.ReadConstLine(
|
||||
Format(lisWarningAmbiguousFileFoundSourceFileIs,
|
||||
['"', AmbiguousFilename, '"', '"', AFilename, '"']), true);
|
||||
end;
|
||||
end;
|
||||
|
||||
function CheckFile(const AmbiguousFilename: string): TModalResult;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if not FileExists(AmbiguousFilename) then exit;
|
||||
if Compiling then begin
|
||||
Result:=AddCompileWarning(AmbiguousFilename);
|
||||
exit;
|
||||
end;
|
||||
case EnvironmentOptions.AmbiguousFileAction of
|
||||
afaAsk:
|
||||
begin
|
||||
Result:=IDEMessageDialog(lisAmbiguousFileFound,
|
||||
Format(lisThereIsAFileWithTheSameNameAndASimilarExtension, [#13,
|
||||
AFilename, #13, AmbiguousFilename, #13, #13]),
|
||||
mtWarning,[mbYes,mbIgnore,mbAbort]);
|
||||
case Result of
|
||||
mrYes: Result:=DeleteAmbiguousFile(AmbiguousFilename);
|
||||
mrIgnore: Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
|
||||
afaAutoDelete:
|
||||
Result:=DeleteAmbiguousFile(AmbiguousFilename);
|
||||
|
||||
afaAutoRename:
|
||||
Result:=RenameAmbiguousFile(AmbiguousFilename);
|
||||
|
||||
afaWarnOnCompile:
|
||||
Result:=AddCompileWarning(AmbiguousFilename);
|
||||
|
||||
else
|
||||
Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
Ext, LowExt: string;
|
||||
i: integer;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if EnvironmentOptions.AmbiguousFileAction=afaIgnore then exit;
|
||||
if (EnvironmentOptions.AmbiguousFileAction=afaWarnOnCompile)
|
||||
and not Compiling then exit;
|
||||
|
||||
if FilenameIsPascalUnit(AFilename) then begin
|
||||
Ext:=ExtractFileExt(AFilename);
|
||||
LowExt:=lowercase(Ext);
|
||||
for i:=Low(PascalFileExt) to High(PascalFileExt) do begin
|
||||
if LowExt<>PascalFileExt[i] then begin
|
||||
Result:=CheckFile(ChangeFileExt(AFilename,PascalFileExt[i]));
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBuildManager.DeleteAmbiguousFiles(const Filename: string
|
||||
): TModalResult;
|
||||
var
|
||||
ADirectory: String;
|
||||
FileInfo: TSearchRec;
|
||||
ShortFilename: String;
|
||||
CurFilename: String;
|
||||
IsPascalUnit: Boolean;
|
||||
UnitName: String;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if EnvironmentOptions.AmbiguousFileAction=afaIgnore then exit;
|
||||
if EnvironmentOptions.AmbiguousFileAction
|
||||
in [afaAsk,afaAutoDelete,afaAutoRename]
|
||||
then begin
|
||||
ADirectory:=AppendPathDelim(ExtractFilePath(Filename));
|
||||
if SysUtils.FindFirst(ADirectory+GetAllFilesMask,faAnyFile,FileInfo)=0 then
|
||||
begin
|
||||
ShortFilename:=ExtractFileName(Filename);
|
||||
IsPascalUnit:=FilenameIsPascalUnit(ShortFilename);
|
||||
UnitName:=ExtractFilenameOnly(ShortFilename);
|
||||
repeat
|
||||
if (FileInfo.Name='.') or (FileInfo.Name='..')
|
||||
or (FileInfo.Name='')
|
||||
or ((FileInfo.Attr and faDirectory)<>0) then continue;
|
||||
if (ShortFilename=FileInfo.Name) then continue;
|
||||
if (AnsiCompareText(ShortFilename,FileInfo.Name)<>0)
|
||||
and ((not IsPascalUnit) or (not FilenameIsPascalUnit(FileInfo.Name))
|
||||
or (AnsiCompareText(UnitName,ExtractFilenameOnly(FileInfo.Name))<>0))
|
||||
then
|
||||
continue;
|
||||
|
||||
CurFilename:=ADirectory+FileInfo.Name;
|
||||
if EnvironmentOptions.AmbiguousFileAction=afaAsk then begin
|
||||
if IDEMessageDialog(lisDeleteAmbiguousFile,
|
||||
Format(lisAmbiguousFileFoundThisFileCanBeMistakenWithDelete, ['"',
|
||||
CurFilename, '"', #13, '"', ShortFilename, '"', #13, #13]),
|
||||
mtConfirmation,[mbYes,mbNo])=mrNo
|
||||
then continue;
|
||||
end;
|
||||
if EnvironmentOptions.AmbiguousFileAction in [afaAutoDelete,afaAsk]
|
||||
then begin
|
||||
if not DeleteFile(CurFilename) then begin
|
||||
IDEMessageDialog(lisDeleteFileFailed,
|
||||
Format(lisPkgMangUnableToDeleteFile, ['"', CurFilename, '"']),
|
||||
mtError,[mbOk]);
|
||||
end;
|
||||
end else if EnvironmentOptions.AmbiguousFileAction=afaAutoRename then
|
||||
begin
|
||||
Result:=BackupFile(CurFilename);
|
||||
if Result=mrABort then exit;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
until SysUtils.FindNext(FileInfo)<>0;
|
||||
end;
|
||||
FindClose(FileInfo);
|
||||
end;
|
||||
end;
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
function TBuildManager.CheckUnitPathForAmbiguousPascalFiles(
|
||||
const BaseDir, TheUnitPath, CompiledExt, ContextDescription: string
|
||||
): TModalResult;
|
||||
|
||||
Collect all pascal files and all compiled units in the unit path and check
|
||||
for ambiguous files. For example: doubles.
|
||||
-------------------------------------------------------------------------------}
|
||||
function TBuildManager.CheckUnitPathForAmbiguousPascalFiles(const BaseDir,
|
||||
TheUnitPath, CompiledExt, ContextDescription: string): TModalResult;
|
||||
|
||||
procedure FreeUnitTree(var Tree: TAVLTree);
|
||||
var
|
||||
ANode: TAVLTreeNode;
|
||||
AnUnitFile: PUnitFile;
|
||||
begin
|
||||
if Tree<>nil then begin
|
||||
ANode:=Tree.FindLowest;
|
||||
while ANode<>nil do begin
|
||||
AnUnitFile:=PUnitFile(ANode.Data);
|
||||
Dispose(AnUnitFile);
|
||||
ANode:=Tree.FindSuccessor(ANode);
|
||||
end;
|
||||
Tree.Free;
|
||||
Tree:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
EndPos: Integer;
|
||||
StartPos: Integer;
|
||||
CurDir: String;
|
||||
FileInfo: TSearchRec;
|
||||
SourceUnitTree, CompiledUnitTree: TAVLTree;
|
||||
ANode: TAVLTreeNode;
|
||||
CurUnitName: String;
|
||||
CurFilename: String;
|
||||
AnUnitFile: PUnitFile;
|
||||
CurUnitTree: TAVLTree;
|
||||
FileInfoNeedClose: Boolean;
|
||||
UnitPath: String;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
UnitPath:=TrimSearchPath(TheUnitPath,BaseDir);
|
||||
|
||||
SourceUnitTree:=TAVLTree.Create(TListSortCompare(@CompareUnitFiles));
|
||||
CompiledUnitTree:=TAVLTree.Create(TListSortCompare(@CompareUnitFiles));
|
||||
FileInfoNeedClose:=false;
|
||||
try
|
||||
// collect all units (.pas, .pp, compiled units)
|
||||
EndPos:=1;
|
||||
while EndPos<=length(UnitPath) do begin
|
||||
StartPos:=EndPos;
|
||||
while (StartPos<=length(UnitPath)) and (UnitPath[StartPos]=';') do
|
||||
inc(StartPos);
|
||||
EndPos:=StartPos;
|
||||
while (EndPos<=length(UnitPath)) and (UnitPath[EndPos]<>';') do
|
||||
inc(EndPos);
|
||||
if EndPos>StartPos then begin
|
||||
CurDir:=AppendPathDelim(TrimFilename(copy(
|
||||
UnitPath,StartPos,EndPos-StartPos)));
|
||||
FileInfoNeedClose:=true;
|
||||
if SysUtils.FindFirst(CurDir+GetAllFilesMask,faAnyFile,FileInfo)=0 then begin
|
||||
repeat
|
||||
if (FileInfo.Name='.') or (FileInfo.Name='..') or (FileInfo.Name='')
|
||||
or ((FileInfo.Attr and faDirectory)<>0) then continue;
|
||||
if FilenameIsPascalUnit(FileInfo.Name) then
|
||||
CurUnitTree:=SourceUnitTree
|
||||
else if (CompareFileExt(FileInfo.Name,CompiledExt,false)=0) then
|
||||
CurUnitTree:=CompiledUnitTree
|
||||
else
|
||||
continue;
|
||||
CurUnitName:=ExtractFilenameOnly(FileInfo.Name);
|
||||
CurFilename:=CurDir+FileInfo.Name;
|
||||
// check if unit already found
|
||||
ANode:=CurUnitTree.FindKey(PChar(CurUnitName),
|
||||
TListSortCompare(@CompareUnitNameAndUnitFile));
|
||||
if ANode<>nil then begin
|
||||
// pascal unit exists twice
|
||||
Result:=MessageDlg('Ambiguous unit found',
|
||||
'The unit '+CurUnitName+' exists twice in the unit path of the '
|
||||
+ContextDescription+':'#13
|
||||
+#13
|
||||
+'1. "'+PUnitFile(ANode.Data)^.Filename+'"'#13
|
||||
+'2. "'+CurFilename+'"'#13
|
||||
+#13
|
||||
+'Hint: Check if two packages contain a unit with the same name.',
|
||||
mtWarning,[mbAbort,mbIgnore],0);
|
||||
if Result<>mrIgnore then exit;
|
||||
end;
|
||||
// add unit to tree
|
||||
New(AnUnitFile);
|
||||
AnUnitFile^.UnitName:=CurUnitName;
|
||||
AnUnitFile^.Filename:=CurFilename;
|
||||
CurUnitTree.Add(AnUnitFile);
|
||||
until SysUtils.FindNext(FileInfo)<>0;
|
||||
end;
|
||||
FindClose(FileInfo);
|
||||
FileInfoNeedClose:=false;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
// clean up
|
||||
if FileInfoNeedClose then FindClose(FileInfo);
|
||||
FreeUnitTree(SourceUnitTree);
|
||||
FreeUnitTree(CompiledUnitTree);
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TBuildManager.BackupFile(const Filename: string): TModalResult;
|
||||
var BackupFilename, CounterFilename: string;
|
||||
AText,ACaption:string;
|
||||
BackupInfo: TBackupInfo;
|
||||
FilePath, FileNameOnly, FileExt, SubDir: string;
|
||||
i: integer;
|
||||
IsPartOfProject: boolean;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if not (FileExists(Filename)) then exit;
|
||||
IsPartOfProject:=(Project1<>nil)
|
||||
and (Project1.FindFile(Filename,[pfsfOnlyProjectFiles])<>nil);
|
||||
if IsPartOfProject then
|
||||
BackupInfo:=EnvironmentOptions.BackupInfoProjectFiles
|
||||
else
|
||||
BackupInfo:=EnvironmentOptions.BackupInfoOtherFiles;
|
||||
if (BackupInfo.BackupType=bakNone)
|
||||
or ((BackupInfo.BackupType=bakSameName) and (BackupInfo.SubDirectory='')) then
|
||||
exit;
|
||||
FilePath:=ExtractFilePath(Filename);
|
||||
FileExt:=ExtractFileExt(Filename);
|
||||
FileNameOnly:=ExtractFilenameOnly(Filename);
|
||||
if BackupInfo.SubDirectory<>'' then begin
|
||||
SubDir:=FilePath+BackupInfo.SubDirectory;
|
||||
repeat
|
||||
if not DirPathExists(SubDir) then begin
|
||||
if not CreateDir(SubDir) then begin
|
||||
Result:=IDEMessageDialog('Warning',
|
||||
Format(lisUnableToCreateBackupDirectory, ['"',SubDir, '"'])
|
||||
,mtWarning,[mbAbort,mbRetry,mbIgnore]);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
if BackupInfo.BackupType in
|
||||
[bakSymbolInFront,bakSymbolBehind,bakUserDefinedAddExt,bakSameName] then
|
||||
begin
|
||||
case BackupInfo.BackupType of
|
||||
bakSymbolInFront:
|
||||
BackupFilename:=FileNameOnly+'.~'+copy(FileExt,2,length(FileExt)-1);
|
||||
bakSymbolBehind:
|
||||
BackupFilename:=FileNameOnly+FileExt+'~';
|
||||
bakUserDefinedAddExt:
|
||||
BackupFilename:=FileNameOnly+FileExt+'.'+BackupInfo.AdditionalExtension;
|
||||
bakSameName:
|
||||
BackupFilename:=FileNameOnly+FileExt;
|
||||
end;
|
||||
if BackupInfo.SubDirectory<>'' then
|
||||
BackupFilename:=SubDir+PathDelim+BackupFilename
|
||||
else
|
||||
BackupFilename:=FilePath+BackupFilename;
|
||||
// remove old backup file
|
||||
repeat
|
||||
if FileExists(BackupFilename) then begin
|
||||
if not DeleteFile(BackupFilename) then begin
|
||||
ACaption:=lisDeleteFileFailed;
|
||||
AText:=Format(lisUnableToRemoveOldBackupFile, ['"', BackupFilename,
|
||||
'"']);
|
||||
Result:=IDEMessageDialog(ACaption,AText,mtError,
|
||||
[mbAbort,mbRetry,mbIgnore]);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end else begin
|
||||
// backup with counter
|
||||
if BackupInfo.SubDirectory<>'' then
|
||||
BackupFilename:=SubDir+PathDelim+FileNameOnly+FileExt+';'
|
||||
else
|
||||
BackupFilename:=Filename+';';
|
||||
if BackupInfo.MaxCounter<=0 then begin
|
||||
// search first non existing backup filename
|
||||
i:=1;
|
||||
while FileExists(BackupFilename+IntToStr(i)) do inc(i);
|
||||
BackupFilename:=BackupFilename+IntToStr(i);
|
||||
end else begin
|
||||
// rename all backup files (increase number)
|
||||
i:=1;
|
||||
while FileExists(BackupFilename+IntToStr(i))
|
||||
and (i<=BackupInfo.MaxCounter) do inc(i);
|
||||
if i>BackupInfo.MaxCounter then begin
|
||||
dec(i);
|
||||
CounterFilename:=BackupFilename+IntToStr(BackupInfo.MaxCounter);
|
||||
// remove old backup file
|
||||
repeat
|
||||
if FileExists(CounterFilename) then begin
|
||||
if not DeleteFile(CounterFilename) then begin
|
||||
ACaption:=lisDeleteFileFailed;
|
||||
AText:=Format(lisUnableToRemoveOldBackupFile, ['"',
|
||||
CounterFilename, '"']);
|
||||
Result:=MessageDlg(ACaption,AText,mtError,
|
||||
[mbAbort,mbRetry,mbIgnore],0);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
// rename all old backup files
|
||||
dec(i);
|
||||
while i>=1 do begin
|
||||
repeat
|
||||
if not RenameFile(BackupFilename+IntToStr(i),
|
||||
BackupFilename+IntToStr(i+1)) then
|
||||
begin
|
||||
ACaption:=lisRenameFileFailed;
|
||||
AText:=Format(lisUnableToRenameFileTo, ['"', BackupFilename+IntToStr
|
||||
(i), '"', '"', BackupFilename+IntToStr(i+1), '"']);
|
||||
Result:=MessageDlg(ACaption,AText,mtError,
|
||||
[mbAbort,mbRetry,mbIgnore],0);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
dec(i);
|
||||
end;
|
||||
BackupFilename:=BackupFilename+'1';
|
||||
end;
|
||||
end;
|
||||
// backup file
|
||||
repeat
|
||||
if not IDEProcs.BackupFile(Filename,BackupFilename) then begin
|
||||
ACaption:=lisBackupFileFailed;
|
||||
AText:=Format(lisUnableToBackupFileTo, ['"', Filename, '"', '"',
|
||||
BackupFilename, '"']);
|
||||
Result:=IDEMessageDialog(ACaption,AText,mterror,[mbabort,mbretry,mbignore]);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
|
||||
function TBuildManager.MacroFuncMakeExe(const Filename: string;
|
||||
const Data: PtrInt; var Abort: boolean): string;
|
||||
var
|
||||
@ -685,6 +1115,16 @@ begin
|
||||
Abort:=not GlobalMacroList.SubstituteStr(CmdLine);
|
||||
end;
|
||||
|
||||
function TBuildManager.OnRunCompilerWithOptions(
|
||||
ExtTool: TIDEExternalToolOptions; CompOptions: TBaseCompilerOptions
|
||||
): TModalResult;
|
||||
begin
|
||||
if SourceEditorWindow<>nil then
|
||||
SourceEditorWindow.ClearErrorLines;
|
||||
Result:=EnvironmentOptions.ExternalTools.Run(ExtTool,GlobalMacroList,
|
||||
TheOutputFilter,CompOptions);
|
||||
end;
|
||||
|
||||
procedure TBuildManager.SetBuildTarget(const TargetOS, TargetCPU,
|
||||
LCLWidgetType: string);
|
||||
var
|
||||
|
@ -41,8 +41,8 @@ unit CompilerOptions;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FileProcs, FileUtil, LCLProc,
|
||||
Laz_XMLCfg, ProjectIntf, MacroIntf,
|
||||
Classes, SysUtils, FileProcs, FileUtil, LCLProc, Forms, Controls,
|
||||
Laz_XMLCfg, ProjectIntf, MacroIntf, IDEExternToolIntf, SrcEditorIntf,
|
||||
IDEProcs, LazConf, TransferMacros;
|
||||
|
||||
type
|
||||
@ -256,6 +256,7 @@ type
|
||||
procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string); virtual;
|
||||
procedure CreateDiff(CompOpts: TCompilationToolOptions;
|
||||
Tool: TCompilerDiffTool); virtual;
|
||||
function Execute(const WorkingDir, ToolTitle: string): TModalResult;
|
||||
end;
|
||||
TCompilationToolClass = class of TCompilationToolOptions;
|
||||
|
||||
@ -453,12 +454,16 @@ const
|
||||
|
||||
type
|
||||
TCompilerGraphStampIncreasedEvent = procedure of object;
|
||||
TRunCompilerWithOptions = function(ExtTool: TIDEExternalToolOptions;
|
||||
ACompilerOptions: TBaseCompilerOptions): TModalResult of object;
|
||||
|
||||
var
|
||||
CompilerParseStamp: integer; // TimeStamp of base value for macros
|
||||
CompilerGraphStamp: integer; // TimeStamp of IDE graph (e.g. packages)
|
||||
OnParseString: TParseStringEvent;
|
||||
CompilerGraphStampIncreased: TCompilerGraphStampIncreasedEvent;
|
||||
OnParseString: TParseStringEvent = nil;
|
||||
CompilerGraphStampIncreased: TCompilerGraphStampIncreasedEvent = nil;
|
||||
|
||||
RunCompilerWithOptions: TRunCompilerWithOptions = nil;
|
||||
|
||||
procedure IncreaseCompilerParseStamp;
|
||||
procedure IncreaseCompilerGraphStamp;
|
||||
@ -2953,6 +2958,46 @@ begin
|
||||
Tool.AddDiff('ShowAllMessages',ShowAllMessages,CompOpts.ShowAllMessages);
|
||||
end;
|
||||
|
||||
function TCompilationToolOptions.Execute(const WorkingDir, ToolTitle: string
|
||||
): TModalResult;
|
||||
var
|
||||
ProgramFilename, Params: string;
|
||||
ExtTool: TIDEExternalToolOptions;
|
||||
Filename: String;
|
||||
begin
|
||||
if Command='' then begin
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if SourceEditorWindow<>nil then
|
||||
SourceEditorWindow.ClearErrorLines;
|
||||
|
||||
SplitCmdLine(Command,ProgramFilename,Params);
|
||||
if not FilenameIsAbsolute(ProgramFilename) then begin
|
||||
Filename:=FindProgram(ProgramFilename,WorkingDir,true);
|
||||
if Filename<>'' then ProgramFilename:=Filename;
|
||||
end;
|
||||
|
||||
ExtTool:=TIDEExternalToolOptions.Create;
|
||||
try
|
||||
ExtTool.Filename:=ProgramFilename;
|
||||
ExtTool.ScanOutputForFPCMessages:=ScanForFPCMessages;
|
||||
ExtTool.ScanOutputForMakeMessages:=ScanForMakeMessages;
|
||||
ExtTool.ScanOutput:=true;
|
||||
ExtTool.ShowAllOutput:=ShowAllMessages;
|
||||
ExtTool.Title:=ToolTitle;
|
||||
ExtTool.WorkingDirectory:=WorkingDir;
|
||||
ExtTool.CmdLineParams:=Params;
|
||||
|
||||
// run
|
||||
Result:=RunExternalTool(ExtTool);
|
||||
finally
|
||||
// clean up
|
||||
ExtTool.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TGlobalCompilerOptions }
|
||||
|
||||
procedure TGlobalCompilerOptions.SetTargetCPU(const AValue: string);
|
||||
|
@ -51,14 +51,23 @@ type
|
||||
lbfCreateClearOnError
|
||||
);
|
||||
TLoadBufferFlags = set of TLoadBufferFlag;
|
||||
|
||||
TOnBackupFileInteractive =
|
||||
function(const Filename: string): TModalResult of object;
|
||||
|
||||
var
|
||||
OnBackupFileInteractive: TOnBackupFileInteractive = nil;
|
||||
|
||||
function BackupFileInteractive(const Filename: string): TModalResult;
|
||||
function RenameFileWithErrorDialogs(const SrcFilename, DestFilename: string;
|
||||
ExtraButtons: TMsgDlgButtons): TModalResult;
|
||||
function CopyFileWithErrorDialogs(const SrcFilename, DestFilename: string;
|
||||
ExtraButtons: TMsgDlgButtons): TModalResult;
|
||||
function LoadCodeBuffer(var ACodeBuffer: TCodeBuffer; const AFilename: string;
|
||||
Flags: TLoadBufferFlags): TModalResult;
|
||||
function SaveCodeBuffer(var ACodeBuffer: TCodeBuffer): TModalResult;
|
||||
function SaveCodeBuffer(ACodeBuffer: TCodeBuffer): TModalResult;
|
||||
function SaveCodeBufferToFile(ACodeBuffer: TCodeBuffer;
|
||||
const Filename: string; Backup: boolean = false): TModalResult;
|
||||
function LoadStringListFromFile(const Filename, ListTitle: string;
|
||||
var sl: TStrings): TModalResult;
|
||||
function CreateEmptyFile(const Filename: string;
|
||||
@ -72,7 +81,8 @@ function ForceDirectoryInteractive(Directory: string;
|
||||
function DeleteFileInteractive(const Filename: string;
|
||||
ErrorButtons: TMsgDlgButtons): TModalResult;
|
||||
function SaveStringToFile(const Filename, Content: string;
|
||||
ErrorButtons: TMsgDlgButtons): TModalResult;
|
||||
ErrorButtons: TMsgDlgButtons; const Context: string = ''
|
||||
): TModalResult;
|
||||
function ConvertLFMToLRSFileInteractive(const LFMFilename,
|
||||
LRSFilename: string): TModalResult;
|
||||
function IfNotOkJumpToCodetoolErrorAndAskToAbort(Ok: boolean;
|
||||
@ -82,6 +92,14 @@ procedure NotImplementedDialog(const Feature: string);
|
||||
|
||||
implementation
|
||||
|
||||
function BackupFileInteractive(const Filename: string): TModalResult;
|
||||
begin
|
||||
if Assigned(OnBackupFileInteractive) then
|
||||
Result:=OnBackupFileInteractive(Filename)
|
||||
else
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function RenameFileWithErrorDialogs(const SrcFilename, DestFilename: string;
|
||||
ExtraButtons: TMsgDlgButtons): TModalResult;
|
||||
var
|
||||
@ -192,7 +210,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function SaveCodeBuffer(var ACodeBuffer: TCodeBuffer): TModalResult;
|
||||
function SaveCodeBuffer(ACodeBuffer: TCodeBuffer): TModalResult;
|
||||
begin
|
||||
repeat
|
||||
if ACodeBuffer.Save then begin
|
||||
@ -205,6 +223,30 @@ begin
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
|
||||
function SaveCodeBufferToFile(ACodeBuffer: TCodeBuffer; const Filename: string;
|
||||
Backup: boolean): TModalResult;
|
||||
var
|
||||
ACaption,AText:string;
|
||||
begin
|
||||
if Backup then begin
|
||||
Result:=BackupFileInteractive(Filename);
|
||||
if Result<>mrOk then exit;
|
||||
end else
|
||||
Result:=mrOk;
|
||||
repeat
|
||||
if ACodeBuffer.SaveToFile(Filename) then begin
|
||||
Result:=mrOk;
|
||||
end else begin
|
||||
ACaption:=lisWriteError;
|
||||
AText:=Format(lisUnableToWriteToFile, ['"', Filename, '"']);
|
||||
Result:=IDEMessageDialog(ACaption,AText,mtError,
|
||||
[mbAbort, mbRetry, mbIgnore]);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
|
||||
function LoadStringListFromFile(const Filename, ListTitle: string;
|
||||
var sl: TStrings): TModalResult;
|
||||
begin
|
||||
@ -362,7 +404,7 @@ begin
|
||||
end;
|
||||
|
||||
function SaveStringToFile(const Filename, Content: string;
|
||||
ErrorButtons: TMsgDlgButtons): TModalResult;
|
||||
ErrorButtons: TMsgDlgButtons; const Context: string): TModalResult;
|
||||
var
|
||||
fs: TFileStream;
|
||||
begin
|
||||
@ -380,7 +422,9 @@ begin
|
||||
on E: Exception do begin
|
||||
Result:=IDEMessageDialog('Write error',
|
||||
'Write error: '+E.Message+#13
|
||||
+'File: '+Filename,mtError,[mbAbort]+ErrorButtons);
|
||||
+'File: '+Filename+#13
|
||||
+Context,
|
||||
mtError,[mbAbort]+ErrorButtons);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -24,6 +24,7 @@
|
||||
This unit defines a dialog for the lazarus environment options and a class to
|
||||
store the options in a xml file.
|
||||
|
||||
ToDo: split this into two units - the dialog and the options.
|
||||
}
|
||||
unit EnvironmentOpts;
|
||||
|
||||
@ -37,7 +38,8 @@ uses
|
||||
{$ENDIF}
|
||||
Classes, SysUtils, FPCAdds, LCLProc, Forms, Controls, Buttons, GraphType,
|
||||
Graphics, ExtCtrls, StdCtrls, Spin, FileUtil, LResources, Dialogs,
|
||||
Laz_XMLCfg, ObjectInspector, IDEWindowIntf,
|
||||
Laz_XMLCfg,
|
||||
ObjectInspector, IDEWindowIntf,
|
||||
LazarusIDEStrConsts, TransferMacros, LazConf, ExtToolDialog, IDEProcs,
|
||||
IDEOptionDefs, InputHistory, EditorOptions, IDETranslations;
|
||||
|
||||
|
@ -247,7 +247,7 @@ var
|
||||
|
||||
procedure ProcessMessages;
|
||||
begin
|
||||
Application.ProcessMessages;
|
||||
if Application<>nil then Application.ProcessMessages;
|
||||
if (Progress<>nil) and Progress.Abort then
|
||||
Result:=mrAbort;
|
||||
end;
|
||||
@ -342,6 +342,7 @@ var
|
||||
AReplace:=ReplaceText;
|
||||
if sesoRegExpr in Flags then
|
||||
AReplace:=RE.Substitute(AReplace);
|
||||
DebugLn(['DoReplaceLine Replace with "',AReplace,'"']);
|
||||
|
||||
SrcEditPosValid:=false;
|
||||
|
||||
@ -572,7 +573,7 @@ begin
|
||||
FoundStartPos.Y,FoundStartPos.X);
|
||||
OriginalFile.AbsoluteToLineCol(NewMatchEndPos,
|
||||
FoundEndPos.Y,FoundEndPos.X);
|
||||
//DebugLn(['SearchInText NewMatchStartPos=',NewMatchStartPos,' NewMatchEndPos=',NewMatchEndPos,' FoundStartPos=',dbgs(FoundStartPos),' FoundEndPos=',dbgs(FoundEndPos),' Found="',dbgstr(copy(Src,NewMatchStartPos,NewMatchEndPos-NewMatchStartPos)),'"']);
|
||||
DebugLn(['SearchInText NewMatchStartPos=',NewMatchStartPos,' NewMatchEndPos=',NewMatchEndPos,' FoundStartPos=',dbgs(FoundStartPos),' FoundEndPos=',dbgs(FoundEndPos),' Found="',dbgstr(copy(Src,NewMatchStartPos,NewMatchEndPos-NewMatchStartPos)),'" Replace=',sesoReplace in Flags]);
|
||||
if sesoReplace in Flags then begin
|
||||
DoReplaceLine
|
||||
end else begin
|
||||
|
@ -53,6 +53,10 @@ const
|
||||
LanguageOpt='--language=';
|
||||
|
||||
resourcestring
|
||||
lisErrInvalidOption = 'Invalid option at position %d: "%s"';
|
||||
lisErrNoOptionAllowed = 'Option at position %d does not allow an argument: %s';
|
||||
lisErrOptionNeeded = 'Option at position %d needs an argument : %s';
|
||||
|
||||
lisEnterTransla = 'Enter translation language';
|
||||
// version
|
||||
lisLazarusVersionString = '%s beta'; // %s is the versionstring (eg. 0.9.10)
|
||||
|
274
ide/lazbuild.lpr
274
ide/lazbuild.lpr
@ -22,22 +22,23 @@
|
||||
!!! Under construction. !!!
|
||||
|
||||
ToDo:
|
||||
Separate the visual parts in the IDE from the package and build system.
|
||||
Separate the visual parts in the IDE from the project and build system.
|
||||
}
|
||||
program lazbuild;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
Classes, SysUtils, CustApp, LCLProc, Forms, Controls, FileUtil,
|
||||
Classes, SysUtils, CustApp, LCLProc, Dialogs, Forms, Controls, FileUtil,
|
||||
Process,
|
||||
// codetools
|
||||
CodeToolManager, Laz_XMLCfg,
|
||||
// IDEIntf
|
||||
MacroIntf, PackageIntf,
|
||||
MacroIntf, PackageIntf, IDEDialogs,
|
||||
// IDE
|
||||
IDEProcs, InitialSetupDlgs, OutputFilter, Compiler, CompilerOptions,
|
||||
TransferMacros, EnvironmentOpts, IDETranslations, LazarusIDEStrConsts,
|
||||
LazConf, BasePkgManager, PackageDefs, PackageLinks, PackageSystem,
|
||||
Project, LazConf, PackageDefs, PackageLinks, PackageSystem,
|
||||
BuildManager, BaseBuildManager;
|
||||
|
||||
type
|
||||
@ -60,13 +61,21 @@ type
|
||||
|
||||
// global package functions
|
||||
procedure GetDependencyOwnerDescription(Dependency: TPkgDependency;
|
||||
var Description: string);
|
||||
out Description: string);
|
||||
procedure GetDependencyOwnerDirectory(Dependency: TPkgDependency;
|
||||
var Directory: string);
|
||||
out Directory: string);
|
||||
procedure GetWritablePkgOutputDirectory(APackage: TLazPackage;
|
||||
var AnOutDirectory: string);
|
||||
// package graph
|
||||
procedure PackageGraphAddPackage(Pkg: TLazPackage);
|
||||
|
||||
// dialogs
|
||||
function OnIDEMessageDialog(const aCaption, aMsg: string;
|
||||
DlgType: TMsgDlgType; Buttons: TMsgDlgButtons;
|
||||
const HelpKeyword: string): Integer;
|
||||
function OnIDEQuestionDialog(const aCaption, aMsg: string;
|
||||
DlgType: TMsgDlgType; Buttons: array of const;
|
||||
const HelpKeyword: string): Integer;
|
||||
protected
|
||||
function BuildFile(Filename: string): boolean;
|
||||
function BuildPackage(const AFilename: string): boolean;
|
||||
@ -79,6 +88,9 @@ type
|
||||
procedure SetupOutputFilter;
|
||||
procedure SetupMacros;
|
||||
procedure SetupPackageSystem;
|
||||
procedure SetupDialogs;
|
||||
Function RepairedCheckOptions(Const ShortOptions : String;
|
||||
Const Longopts : TStrings; Opts,NonOpts : TStrings) : String;
|
||||
public
|
||||
Files: TStringList;
|
||||
constructor Create(TheOwner: TComponent); override;
|
||||
@ -92,12 +104,56 @@ type
|
||||
write FBuildRecursive;
|
||||
end;
|
||||
|
||||
var
|
||||
Application: TLazBuildApplication = nil;
|
||||
|
||||
const
|
||||
ErrorFileNotFound = 1;
|
||||
ErrorBuildFailed = 2;
|
||||
ErrorLoadPackageFailed = 3;
|
||||
ErrorPackageNameInvalid = 4;
|
||||
|
||||
procedure GetDescriptionOfDependencyOwner(Dependency: TPkgDependency;
|
||||
out Description: string);
|
||||
var
|
||||
DepOwner: TObject;
|
||||
begin
|
||||
DepOwner:=Dependency.Owner;
|
||||
if (DepOwner<>nil) then begin
|
||||
if DepOwner is TLazPackage then begin
|
||||
Description:=Format(lisPkgMangPackage, [TLazPackage(DepOwner).IDAsString]
|
||||
);
|
||||
end else if DepOwner is TProject then begin
|
||||
Description:=Format(lisPkgMangProject, [ExtractFileNameOnly(TProject(
|
||||
DepOwner).ProjectInfoFile)]);
|
||||
end else begin
|
||||
Description:=dbgsName(DepOwner)
|
||||
end;
|
||||
end else begin
|
||||
Description:=Format(lisPkgMangDependencyWithoutOwner, [Dependency.AsString]
|
||||
);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GetDirectoryOfDependencyOwner(Dependency: TPkgDependency;
|
||||
out Directory: string);
|
||||
var
|
||||
DepOwner: TObject;
|
||||
begin
|
||||
DepOwner:=Dependency.Owner;
|
||||
if (DepOwner<>nil) then begin
|
||||
if DepOwner is TLazPackage then begin
|
||||
Directory:=TLazPackage(DepOwner).Directory;
|
||||
end else if DepOwner is TProject then begin
|
||||
Directory:=TProject(DepOwner).ProjectDirectory;
|
||||
end else begin
|
||||
Directory:=''
|
||||
end;
|
||||
end else begin
|
||||
Directory:=''
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TLazBuildApplication }
|
||||
|
||||
procedure TLazBuildApplication.OnExtToolFreeOutputFilter(
|
||||
@ -113,13 +169,13 @@ begin
|
||||
end;
|
||||
|
||||
procedure TLazBuildApplication.GetDependencyOwnerDescription(
|
||||
Dependency: TPkgDependency; var Description: string);
|
||||
Dependency: TPkgDependency; out Description: string);
|
||||
begin
|
||||
GetDescriptionOfDependencyOwner(Dependency,Description);
|
||||
end;
|
||||
|
||||
procedure TLazBuildApplication.GetDependencyOwnerDirectory(
|
||||
Dependency: TPkgDependency; var Directory: string);
|
||||
Dependency: TPkgDependency; out Directory: string);
|
||||
begin
|
||||
GetDirectoryOfDependencyOwner(Dependency,Directory);
|
||||
end;
|
||||
@ -151,6 +207,24 @@ begin
|
||||
if FileExists(Pkg.FileName) then PkgLinks.AddUserLink(Pkg);
|
||||
end;
|
||||
|
||||
function TLazBuildApplication.OnIDEMessageDialog(const aCaption, aMsg: string;
|
||||
DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; const HelpKeyword: string
|
||||
): Integer;
|
||||
begin
|
||||
DumpStack;
|
||||
Error(ErrorBuildFailed,aMsg);
|
||||
Result:=mrCancel;
|
||||
end;
|
||||
|
||||
function TLazBuildApplication.OnIDEQuestionDialog(const aCaption, aMsg: string;
|
||||
DlgType: TMsgDlgType; Buttons: array of const; const HelpKeyword: string
|
||||
): Integer;
|
||||
begin
|
||||
DumpStack;
|
||||
Error(ErrorBuildFailed,aMsg);
|
||||
Result:=mrCancel;
|
||||
end;
|
||||
|
||||
function TLazBuildApplication.BuildFile(Filename: string): boolean;
|
||||
begin
|
||||
Result:=false;
|
||||
@ -170,16 +244,23 @@ var
|
||||
Flags: TPkgCompileFlags;
|
||||
begin
|
||||
Result:=false;
|
||||
|
||||
Init;
|
||||
|
||||
APackage:=LoadPackage(AFilename);
|
||||
if APackage=nil then
|
||||
Error(ErrorLoadPackageFailed, 'unable to load package "'+AFilename+'"');
|
||||
|
||||
Flags:=[];
|
||||
if BuildAll then
|
||||
Include(Flags,pcfCleanCompile);
|
||||
Include(Flags,pcfCleanCompile)
|
||||
else
|
||||
Include(Flags,pcfOnlyIfNeeded);
|
||||
if BuildRecursive and BuildAll then
|
||||
Include(Flags,pcfCompileDependenciesClean);
|
||||
CompilePackage(APackage,Flags);
|
||||
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function TLazBuildApplication.LoadPackage(const AFilename: string): TLazPackage;
|
||||
@ -229,7 +310,8 @@ begin
|
||||
CheckPackageGraphForCompilation(APackage,nil);
|
||||
end;
|
||||
|
||||
{$NOTE TODO: move code from package manager to packagegraph and use it here}
|
||||
if PackageGraph.CompilePackage(APackage,Flags)<>mrOk then
|
||||
Error(ErrorBuildFailed,APackage.IDAsString+' compilation failed');
|
||||
end;
|
||||
|
||||
procedure TLazBuildApplication.CheckPackageGraphForCompilation(
|
||||
@ -237,16 +319,29 @@ procedure TLazBuildApplication.CheckPackageGraphForCompilation(
|
||||
|
||||
function PathListToString(PathList: TFPList): string;
|
||||
var
|
||||
Dependency: TPkgDependency;
|
||||
i: Integer;
|
||||
Item: TObject;
|
||||
begin
|
||||
Result:='';
|
||||
for i:=0 to PathList.Count-1 do begin
|
||||
Dependency:=TPkgDependency(PathList[0]);
|
||||
if Dependency is TPkgDependency then begin
|
||||
Item:=TObject(PathList[0]);
|
||||
if Item is TPkgDependency then begin
|
||||
if Result<>'' then
|
||||
Result:=Result+'>';
|
||||
Result:=Result+Dependency.AsString;
|
||||
Result:=Result+TPkgDependency(Item).AsString;
|
||||
end else if Item is TProject then begin
|
||||
if Result<>'' then
|
||||
Result:=Result+'>';
|
||||
Result:=Result
|
||||
+'Project:'+ExtractFileNameOnly(TProject(Item).ProjectInfoFile);
|
||||
end else if Item is TLazPackage then begin
|
||||
if Result<>'' then
|
||||
Result:=Result+'>';
|
||||
Result:=Result+TLazPackage(Item).IDAsString;
|
||||
end else begin
|
||||
if Result<>'' then
|
||||
Result:=Result+'>';
|
||||
Result:=Result+'Unknown:'+dbgsName(Item);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -290,6 +385,9 @@ begin
|
||||
SetupOutputFilter;
|
||||
MainBuildBoss.SetupCompilerInterface;
|
||||
|
||||
// create static base packages
|
||||
PackageGraph.AddStaticBasePackages;
|
||||
|
||||
fInitResult:=true;
|
||||
end;
|
||||
|
||||
@ -337,9 +435,149 @@ begin
|
||||
PackageGraph.OnAddPackage:=@PackageGraphAddPackage;
|
||||
end;
|
||||
|
||||
procedure TLazBuildApplication.SetupDialogs;
|
||||
begin
|
||||
IDEMessageDialog:=@OnIDEMessageDialog;
|
||||
IDEQuestionDialog:=@OnIDEQuestionDialog;
|
||||
end;
|
||||
|
||||
function TLazBuildApplication.RepairedCheckOptions(const ShortOptions: String;
|
||||
const Longopts: TStrings; Opts, NonOpts: TStrings): String;
|
||||
|
||||
Var
|
||||
I,J,L,P : Integer;
|
||||
O,OV,SO : String;
|
||||
HaveArg : Boolean;
|
||||
NeedArg: Boolean;
|
||||
|
||||
Function FindLongOpt(S : String) : boolean;
|
||||
|
||||
Var
|
||||
I : integer;
|
||||
|
||||
begin
|
||||
If CaseSensitiveOptions then
|
||||
begin
|
||||
I:=LongOpts.Count-1;
|
||||
While (I>=0) and (LongOpts[i]<>S) do
|
||||
Dec(i);
|
||||
end
|
||||
else
|
||||
begin
|
||||
S:=UpperCase(S);
|
||||
I:=LongOpts.Count-1;
|
||||
While (I>=0) and (UpperCase(LongOpts[i])<>S) do
|
||||
Dec(i);
|
||||
end;
|
||||
Result:=(I<>-1);
|
||||
end;
|
||||
|
||||
begin
|
||||
If CaseSensitiveOptions then
|
||||
SO:=Shortoptions
|
||||
else
|
||||
SO:=LowerCase(Shortoptions);
|
||||
Result:='';
|
||||
I:=1;
|
||||
While (I<=ParamCount) and (Result='') do
|
||||
begin
|
||||
O:=Paramstr(I);
|
||||
If (Length(O)=0) or (O[1]<>OptionChar) then
|
||||
begin
|
||||
If Assigned(NonOpts) then
|
||||
NonOpts.Add(O)
|
||||
end
|
||||
else
|
||||
begin
|
||||
If (Length(O)<2) then
|
||||
Result:=Format(lisErrInvalidOption,[i,O])
|
||||
else
|
||||
begin
|
||||
HaveArg:=False;
|
||||
OV:='';
|
||||
// Long option ?
|
||||
If (O[2]=OptionChar) then
|
||||
begin
|
||||
Delete(O,1,2);
|
||||
J:=Pos('=',O);
|
||||
If J<>0 then
|
||||
begin
|
||||
HaveArg:=true;
|
||||
OV:=O;
|
||||
Delete(OV,1,J);
|
||||
O:=Copy(O,1,J-1);
|
||||
end;
|
||||
// Switch Option
|
||||
If FindLongopt(O) then
|
||||
begin
|
||||
If HaveArg then
|
||||
Result:=Format(lisErrNoOptionAllowed,[I,O])
|
||||
end
|
||||
else
|
||||
begin // Required argument
|
||||
If FindLongOpt(O+':') then
|
||||
begin
|
||||
If Not HaveArg then
|
||||
Result:=Format(lisErrOptionNeeded,[I,O]);
|
||||
end
|
||||
else
|
||||
begin // Optional Argument.
|
||||
If not FindLongOpt(O+'::') then
|
||||
Result:=Format(lisErrInvalidOption,[I,O]);
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else // Short Option.
|
||||
begin
|
||||
HaveArg:=(I<ParamCount) and (Length(ParamStr(I+1))>0)
|
||||
and (ParamStr(I+1)[i]<>OptionChar);
|
||||
If HaveArg then
|
||||
OV:=Paramstr(I+1);
|
||||
If Not CaseSensitiveOptions then
|
||||
O:=LowerCase(O);
|
||||
L:=Length(O);
|
||||
J:=2;
|
||||
NeedArg:=false;
|
||||
While (result='') and (J<=L) do
|
||||
begin
|
||||
P:=Pos(O[J],ShortOptions);
|
||||
If (P=0) or (O[j]=':') then
|
||||
Result:=Format(lisErrInvalidOption,[I,O[J]])
|
||||
else
|
||||
begin
|
||||
If (P<Length(ShortOptions)) and (Shortoptions[P+1]=':') then
|
||||
begin
|
||||
// Required argument
|
||||
NeedArg:=true;
|
||||
Writeln('P ',P,' J ',J,' ',O[J],' ',l,' Havearg ',HaveArg);
|
||||
If ((P+1)=Length(ShortOptions)) or (Shortoptions[P+2]<>':') Then
|
||||
If (J<L) or not haveArg then // Must be last in multi-opt !!
|
||||
Result:=Format(lisErrOptionNeeded,[I,O[J]]);
|
||||
O:=O[j]; // O is added to arguments.
|
||||
end;
|
||||
end;
|
||||
Inc(J);
|
||||
end;
|
||||
if not NeedArg then HaveArg:=false;
|
||||
If HaveArg then
|
||||
begin
|
||||
Inc(I); // Skip argument.
|
||||
O:=O[Length(O)]; // O is added to arguments !
|
||||
end;
|
||||
end;
|
||||
If HaveArg and (Result='') then
|
||||
If Assigned(Opts) then
|
||||
Opts.Add(O+'='+OV);
|
||||
end;
|
||||
end;
|
||||
Inc(I);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TLazBuildApplication.Create(TheOwner: TComponent);
|
||||
begin
|
||||
inherited Create(TheOwner);
|
||||
TOutputFilterProcess:=TProcess;
|
||||
Files:=TStringList.Create;
|
||||
end;
|
||||
|
||||
@ -408,7 +646,7 @@ begin
|
||||
LongOptions.Add('language');
|
||||
LongOptions.Add('build-all');
|
||||
LongOptions.Add('recursive');
|
||||
ErrorMsg:=CheckOptions('lBR',LongOptions,Options,NonOptions);
|
||||
ErrorMsg:=RepairedCheckOptions('lBR',LongOptions,Options,NonOptions);
|
||||
if ErrorMsg<>'' then begin
|
||||
writeln(ErrorMsg);
|
||||
writeln('');
|
||||
@ -418,6 +656,7 @@ begin
|
||||
// files
|
||||
Files.Assign(NonOptions);
|
||||
if Files.Count=0 then begin
|
||||
writeln('Error: missing file');
|
||||
WriteUsage;
|
||||
exit;
|
||||
end;
|
||||
@ -482,9 +721,10 @@ begin
|
||||
Halt(ErrorCode);
|
||||
end;
|
||||
|
||||
var
|
||||
Application: TLazBuildApplication;
|
||||
begin
|
||||
// free LCL application
|
||||
FreeAndNil(Forms.Application);
|
||||
// start our own application
|
||||
Application:=TLazBuildApplication.Create(nil);
|
||||
Application.Run;
|
||||
Application.Free;
|
||||
|
324
ide/main.pp
324
ide/main.pp
@ -53,6 +53,15 @@ unit Main;
|
||||
|
||||
interface
|
||||
|
||||
// TODO: Test on all platforms
|
||||
{$IFNDEF DisableAsyncProcess}
|
||||
{$IFDEF Linux}
|
||||
{$IFDEF CPUI386}
|
||||
{off $DEFINE UseAsyncProcess}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$I ide.inc}
|
||||
|
||||
uses
|
||||
@ -60,7 +69,7 @@ uses
|
||||
MemCheck,
|
||||
{$ENDIF}
|
||||
// fpc packages
|
||||
Classes, SysUtils, Process, TypInfo,
|
||||
Classes, SysUtils, Process, AsyncProcess, TypInfo,
|
||||
// lcl
|
||||
LCLProc, LCLMemManager, LCLType, LCLIntf, LMessages, LResources, StdCtrls,
|
||||
Forms, Buttons, Menus, FileUtil, Controls, GraphType, Graphics, ExtCtrls,
|
||||
@ -101,7 +110,7 @@ uses
|
||||
// debugger
|
||||
RunParamsOpts, BaseDebugManager, DebugManager,
|
||||
// packager
|
||||
PkgManager, BasePkgManager,
|
||||
PackageSystem, PkgManager, BasePkgManager,
|
||||
// source editing
|
||||
UnitEditor, CodeToolsOptions, IDEOptionDefs, CheckLFMDlg,
|
||||
CodeToolsDefines, DiffDialog, DiskDiffsDialog, UnitInfoDlg, EditorOptions,
|
||||
@ -691,13 +700,10 @@ type
|
||||
|
||||
// external tools
|
||||
function PrepareForCompile: TModalResult; override;
|
||||
function RunExternalTool(Tool: TIDEExternalToolOptions): TModalResult; override;
|
||||
function OnRunExternalTool(Tool: TIDEExternalToolOptions): TModalResult;
|
||||
function DoRunExternalTool(Index: integer): TModalResult;
|
||||
function DoSaveBuildIDEConfigs(Flags: TBuildLazarusFlags): TModalResult; override;
|
||||
function DoBuildLazarus(Flags: TBuildLazarusFlags): TModalResult; override;
|
||||
function DoExecuteCompilationTool(Tool: TCompilationToolOptions;
|
||||
const WorkingDir, ToolTitle: string
|
||||
): TModalResult; override;
|
||||
function DoBuildFile: TModalResult;
|
||||
function DoRunFile: TModalResult;
|
||||
function DoConfigBuildFile: TModalResult;
|
||||
@ -733,20 +739,11 @@ type
|
||||
Flags: TFindSourceFlags): string; override;
|
||||
function FileExistsInIDE(const Filename: string;
|
||||
SearchFlags: TProjectFileSearchFlags): boolean;
|
||||
function DoSaveStreamToFile(AStream:TStream; const Filename:string;
|
||||
IsPartOfProject:boolean): TModalResult;
|
||||
function DoSaveStringToFile(const Filename, Src,
|
||||
FileDescription: string): TModalResult; override;
|
||||
function LoadIDECodeBuffer(var ACodeBuffer: TCodeBuffer;
|
||||
const AFilename: string;
|
||||
Flags: TLoadBufferFlags): TModalResult;
|
||||
function DoLoadMemoryStreamFromFile(MemStream: TMemoryStream;
|
||||
const AFilename:string): TModalResult;
|
||||
function DoSaveCodeBufferToFile(ABuffer: TCodeBuffer;
|
||||
const AFilename: string;
|
||||
IsPartOfProject:boolean): TModalResult; override;
|
||||
function DoBackupFile(const Filename:string;
|
||||
IsPartOfProject:boolean): TModalResult; override;
|
||||
function DoRenameUnitLowerCase(AnUnitInfo: TUnitInfo;
|
||||
AskUser: boolean): TModalresult;
|
||||
function DoCheckFilesOnDisk(Instantaneous: boolean = false): TModalResult; override;
|
||||
@ -1031,6 +1028,12 @@ begin
|
||||
inherited Create(TheOwner);
|
||||
|
||||
SetupDialogs;
|
||||
RunExternalTool:=@OnRunExternalTool;
|
||||
{$IFDEF UseAsyncProcess}
|
||||
TOutputFilterProcess:=TAsyncProcess;
|
||||
{$ELSE}
|
||||
TOutputFilterProcess:=TProcess;
|
||||
{$ENDIF}
|
||||
|
||||
MainBuildBoss:=TBuildManager.Create;
|
||||
|
||||
@ -4203,8 +4206,7 @@ begin
|
||||
// stream text to file
|
||||
TxtCompStream.Position:=0;
|
||||
LFMCode.LoadFromStream(TxtCompStream);
|
||||
Result:=DoSaveCodeBufferToFile(LFMCode,LFMCode.Filename,
|
||||
AnUnitInfo.IsPartOfProject);
|
||||
Result:=SaveCodeBufferToFile(LFMCode,LFMCode.Filename);
|
||||
if not Result=mrOk then exit;
|
||||
Result:=mrCancel;
|
||||
finally
|
||||
@ -4266,16 +4268,14 @@ begin
|
||||
if ResourceCode<>nil then begin
|
||||
if not (sfSaveToTestDir in Flags) then begin
|
||||
if (ResourceCode.Modified) then begin
|
||||
Result:=DoSaveCodeBufferToFile(ResourceCode,ResourceCode.Filename,
|
||||
AnUnitInfo.IsPartOfProject);
|
||||
Result:=SaveCodeBufferToFile(ResourceCode,ResourceCode.Filename);
|
||||
if not Result=mrOk then exit;
|
||||
end;
|
||||
end else begin
|
||||
TestFilename:=MainBuildBoss.GetTestUnitFilename(AnUnitInfo);
|
||||
Result:=DoSaveCodeBufferToFile(ResourceCode,
|
||||
Result:=SaveCodeBufferToFile(ResourceCode,
|
||||
ChangeFileExt(TestFilename,
|
||||
ExtractFileExt(ResourceCode.Filename)),
|
||||
false);
|
||||
ExtractFileExt(ResourceCode.Filename)));
|
||||
if not Result=mrOk then exit;
|
||||
end;
|
||||
end;
|
||||
@ -4483,8 +4483,7 @@ begin
|
||||
end;
|
||||
|
||||
// save file
|
||||
Result:=DoSaveCodeBufferToFile(NewSource,NewSource.Filename,
|
||||
AnUnitInfo.IsPartOfProject);
|
||||
Result:=SaveCodeBufferToFile(NewSource,NewSource.Filename);
|
||||
if Result<>mrOk then exit;
|
||||
|
||||
// change packages containing the file
|
||||
@ -5023,7 +5022,7 @@ begin
|
||||
Result.EndUpdate;
|
||||
|
||||
Result.MainProject:=true;
|
||||
Result.OnFileBackup:=@DoBackupFile;
|
||||
Result.OnFileBackup:=@MainBuildBoss.BackupFile;
|
||||
Result.OnLoadProjectInfo:=@OnLoadProjectInfoFromXMLConfig;
|
||||
Result.OnSaveProjectInfo:=@OnSaveProjectInfoToXMLConfig;
|
||||
Result.OnGetTestDirectory:=@OnProjectGetTestDirectory;
|
||||
@ -5730,7 +5729,7 @@ begin
|
||||
end;
|
||||
|
||||
if sfCheckAmbiguousFiles in Flags then
|
||||
DoCheckAmbiguousSources(DestFilename,false);
|
||||
MainBuildBoss.CheckAmbiguousSources(DestFilename,false);
|
||||
|
||||
{$IFDEF IDE_DEBUG}
|
||||
writeln('*** HasResources=',ActiveUnitInfo.HasResources);
|
||||
@ -6324,32 +6323,6 @@ begin
|
||||
until FileIsUnique(Result);
|
||||
end;
|
||||
|
||||
function TMainIDE.DoSaveStringToFile(const Filename, Src,
|
||||
FileDescription: string): TModalResult;
|
||||
var
|
||||
fs: TFileStream;
|
||||
begin
|
||||
try
|
||||
ClearFile(Filename,true);
|
||||
InvalidateFileStateCache;
|
||||
fs:=TFileStream.Create(Filename,fmCreate);
|
||||
try
|
||||
if Src<>'' then
|
||||
fs.Write(Src[1],length(Src));
|
||||
finally
|
||||
fs.Free;
|
||||
end;
|
||||
except
|
||||
on E: Exception do begin
|
||||
Result:=MessageDlg(lisPkgMangErrorWritingFile,
|
||||
Format(lisUnableToWrite, [FileDescription, #13, '"', Filename, '"']),
|
||||
mtError,[mbCancel,mbAbort],0);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TMainIDE.LoadIDECodeBuffer(var ACodeBuffer: TCodeBuffer;
|
||||
const AFilename: string; Flags: TLoadBufferFlags): TModalResult;
|
||||
begin
|
||||
@ -6711,8 +6684,7 @@ begin
|
||||
end else
|
||||
DestFilename:=MainBuildBoss.GetTestUnitFilename(MainUnitInfo);
|
||||
if not SkipSavingMainSource then begin
|
||||
Result:=DoSaveCodeBufferToFile(MainUnitInfo.Source, DestFilename,
|
||||
not (sfSaveToTestDir in Flags));
|
||||
Result:=SaveCodeBufferToFile(MainUnitInfo.Source, DestFilename);
|
||||
if Result=mrAbort then exit;
|
||||
end;
|
||||
end;
|
||||
@ -7237,7 +7209,7 @@ begin
|
||||
AnUnitInfo:=Project1.Units[i];
|
||||
if (AnUnitInfo.IsPartOfProject) and (not AnUnitInfo.IsVirtual) then begin
|
||||
DestFilename:=MainBuildBoss.GetTargetUnitFilename(AnUnitInfo);
|
||||
Result:=DoCheckAmbiguousSources(DestFilename,true);
|
||||
Result:=MainBuildBoss.CheckAmbiguousSources(DestFilename,true);
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
end;
|
||||
@ -7348,7 +7320,8 @@ begin
|
||||
end;
|
||||
|
||||
// check all required packages
|
||||
Result:=PkgBoss.DoCheckIfDependenciesNeedCompilation(AProject,StateFileAge);
|
||||
Result:=PackageGraph.CheckIfDependenciesNeedCompilation(
|
||||
AProject.FirstRequiredDependency,StateFileAge);
|
||||
if Result<>mrNo then exit;
|
||||
|
||||
Result:=mrYes;
|
||||
@ -7506,9 +7479,9 @@ begin
|
||||
end;
|
||||
CompilerFilename:=Project1.CompilerOptions.CompilerPath;
|
||||
GlobalMacroList.SubstituteStr(CompilerFilename);
|
||||
DebugLn(['TMainIDE.DoBuildProject A Project1.GetCompilerFilename="',Project1.GetCompilerFilename,'" CompilerFilename="',CompilerFilename,'" CompilerPath="',Project1.CompilerOptions.CompilerPath,'"']);
|
||||
//DebugLn(['TMainIDE.DoBuildProject A Project1.GetCompilerFilename="',Project1.GetCompilerFilename,'" CompilerFilename="',CompilerFilename,'" CompilerPath="',Project1.CompilerOptions.CompilerPath,'"']);
|
||||
CompilerFilename:=Project1.GetCompilerFilename;
|
||||
DebugLn(['TMainIDE.DoBuildProject CompilerFilename="',CompilerFilename,'" CompilerPath="',Project1.CompilerOptions.CompilerPath,'"']);
|
||||
//DebugLn(['TMainIDE.DoBuildProject CompilerFilename="',CompilerFilename,'" CompilerPath="',Project1.CompilerOptions.CompilerPath,'"']);
|
||||
|
||||
CompilerParams:=Project1.CompilerOptions.MakeOptionsString(SrcFilename,nil,[])
|
||||
+' '+PrepareCmdLineOption(SrcFilename);
|
||||
@ -7538,9 +7511,8 @@ begin
|
||||
ToolBefore:=TProjectCompilationToolOptions(
|
||||
Project1.CompilerOptions.ExecuteBefore);
|
||||
if (AReason in ToolBefore.CompileReasons) then begin
|
||||
Result:=DoExecuteCompilationTool(Project1.CompilerOptions.ExecuteBefore,
|
||||
Project1.ProjectDirectory,
|
||||
lisExecutingCommandBefore);
|
||||
Result:=Project1.CompilerOptions.ExecuteBefore.Execute(
|
||||
Project1.ProjectDirectory,lisExecutingCommandBefore);
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
end;
|
||||
@ -7576,9 +7548,8 @@ begin
|
||||
Project1.CompilerOptions.ExecuteAfter);
|
||||
// no need to check for mrOk, we are exit if it wasn't
|
||||
if (AReason in ToolAfter.CompileReasons) then begin
|
||||
Result:=DoExecuteCompilationTool(Project1.CompilerOptions.ExecuteAfter,
|
||||
Project1.ProjectDirectory,
|
||||
lisExecutingCommandAfter);
|
||||
Result:=Project1.CompilerOptions.ExecuteAfter.Execute(
|
||||
Project1.ProjectDirectory,lisExecutingCommandAfter);
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
end;
|
||||
@ -7911,7 +7882,7 @@ begin
|
||||
if FPCPatch=0 then ;
|
||||
CompiledUnitExt:=MiscellaneousOptions.BuildLazOpts.CompiledUnitExt(
|
||||
FPCVersion,FPCRelease);
|
||||
Result:=DoCheckUnitPathForAmbiguousPascalFiles(
|
||||
Result:=MainBuildBoss.CheckUnitPathForAmbiguousPascalFiles(
|
||||
EnvironmentOptions.LazarusDirectory,
|
||||
InheritedOptionStrings[icoUnitPath],
|
||||
CompiledUnitExt,'IDE');
|
||||
@ -7949,45 +7920,6 @@ begin
|
||||
mnuRestartClicked(nil);
|
||||
end;
|
||||
|
||||
function TMainIDE.DoExecuteCompilationTool(Tool: TCompilationToolOptions;
|
||||
const WorkingDir, ToolTitle: string): TModalResult;
|
||||
var
|
||||
ProgramFilename, Params: string;
|
||||
ExtTool: TExternalToolOptions;
|
||||
Filename: String;
|
||||
begin
|
||||
if Tool.Command='' then begin
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
|
||||
SourceNotebook.ClearErrorLines;
|
||||
|
||||
SplitCmdLine(Tool.Command,ProgramFilename,Params);
|
||||
if not FilenameIsAbsolute(ProgramFilename) then begin
|
||||
Filename:=FindProgram(ProgramFilename,WorkingDir,true);
|
||||
if Filename<>'' then ProgramFilename:=Filename;
|
||||
end;
|
||||
|
||||
ExtTool:=TExternalToolOptions.Create;
|
||||
try
|
||||
ExtTool.Filename:=ProgramFilename;
|
||||
ExtTool.ScanOutputForFPCMessages:=Tool.ScanForFPCMessages;
|
||||
ExtTool.ScanOutputForMakeMessages:=Tool.ScanForMakeMessages;
|
||||
ExtTool.ScanOutput:=true;
|
||||
ExtTool.ShowAllOutput:=Tool.ShowAllMessages;
|
||||
ExtTool.Title:=ToolTitle;
|
||||
ExtTool.WorkingDirectory:=WorkingDir;
|
||||
ExtTool.CmdLineParams:=Params;
|
||||
|
||||
// run
|
||||
Result:=EnvironmentOptions.ExternalTools.Run(ExtTool,GlobalMacroList);
|
||||
finally
|
||||
// clean up
|
||||
ExtTool.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TMainIDE.DoBuildFile: TModalResult;
|
||||
var
|
||||
ActiveSrcEdit: TSourceEditor;
|
||||
@ -8435,7 +8367,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TMainIDE.RunExternalTool(Tool: TIDEExternalToolOptions): TModalResult;
|
||||
function TMainIDE.OnRunExternalTool(Tool: TIDEExternalToolOptions): TModalResult;
|
||||
begin
|
||||
SourceNotebook.ClearErrorLines;
|
||||
Result:=EnvironmentOptions.ExternalTools.Run(Tool,GlobalMacroList);
|
||||
@ -8570,26 +8502,6 @@ begin
|
||||
Result:=SourceNoteBook.FindSourceEditorWithPageIndex(AnUnitInfo.EditorIndex);
|
||||
end;
|
||||
|
||||
function TMainIDE.DoSaveStreamToFile(AStream:TStream;
|
||||
const Filename:string; IsPartOfProject:boolean):TModalResult;
|
||||
// save to file with backup and user interaction
|
||||
var AText,ACaption:string;
|
||||
NewBuf: TCodeBuffer;
|
||||
begin
|
||||
Result:=DoBackupFile(Filename,IsPartOfProject);
|
||||
if Result<>mrOk then exit;
|
||||
repeat
|
||||
NewBuf:=CodeToolBoss.CreateFile(FileName);
|
||||
if (NewBuf<>nil) or (not NewBuf.SaveToFile(Filename)) then begin
|
||||
ACaption:=lisCodeToolsDefsWriteError;
|
||||
AText:=Format(lisUnableToSaveFile, ['"', Filename, '"']);
|
||||
Result:=MessageDlg(ACaption,AText,mterror, [mbabort, mbretry, mbignore],0);
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
if Result=mrAbort then exit;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
|
||||
function TMainIDE.DoLoadMemoryStreamFromFile(MemStream: TMemoryStream;
|
||||
const AFilename:string): TModalResult;
|
||||
var FileStream: TFileStream;
|
||||
@ -8615,168 +8527,6 @@ begin
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
|
||||
function TMainIDE.DoSaveCodeBufferToFile(ABuffer: TCodeBuffer;
|
||||
const AFilename: string; IsPartOfProject:boolean): TModalResult;
|
||||
var
|
||||
ACaption,AText:string;
|
||||
begin
|
||||
Result:=DoBackupFile(AFilename,IsPartOfProject);
|
||||
if Result<>mrOk then exit;
|
||||
repeat
|
||||
if ABuffer.SaveToFile(AFilename) then begin
|
||||
Result:=mrOk;
|
||||
end else begin
|
||||
ACaption:=lisWriteError;
|
||||
AText:=Format(lisUnableToWriteToFile, ['"', AFilename, '"']);
|
||||
Result:=MessageDlg(ACaption,AText,mtError,[mbAbort, mbRetry, mbIgnore],0);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
TMainIDE DoBackupFile
|
||||
|
||||
Params: const Filename:string;
|
||||
IsPartOfProject:boolean
|
||||
Returns: TModalResult
|
||||
|
||||
Rename existing file to backup file.
|
||||
-------------------------------------------------------------------------------}
|
||||
function TMainIDE.DoBackupFile(const Filename:string;
|
||||
IsPartOfProject:boolean): TModalResult;
|
||||
var BackupFilename, CounterFilename: string;
|
||||
AText,ACaption:string;
|
||||
BackupInfo: TBackupInfo;
|
||||
FilePath, FileNameOnly, FileExt, SubDir: string;
|
||||
i: integer;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if not (FileExists(Filename)) then exit;
|
||||
if IsPartOfProject then
|
||||
BackupInfo:=EnvironmentOptions.BackupInfoProjectFiles
|
||||
else
|
||||
BackupInfo:=EnvironmentOptions.BackupInfoOtherFiles;
|
||||
if (BackupInfo.BackupType=bakNone)
|
||||
or ((BackupInfo.BackupType=bakSameName) and (BackupInfo.SubDirectory='')) then
|
||||
exit;
|
||||
FilePath:=ExtractFilePath(Filename);
|
||||
FileExt:=ExtractFileExt(Filename);
|
||||
FileNameOnly:=ExtractFilenameOnly(Filename);
|
||||
if BackupInfo.SubDirectory<>'' then begin
|
||||
SubDir:=FilePath+BackupInfo.SubDirectory;
|
||||
repeat
|
||||
if not DirPathExists(SubDir) then begin
|
||||
if not CreateDir(SubDir) then begin
|
||||
Result:=MessageDlg(Format(lisUnableToCreateBackupDirectory, ['"',
|
||||
SubDir, '"'])
|
||||
,mtWarning,[mbAbort,mbRetry,mbIgnore],0);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
if BackupInfo.BackupType in
|
||||
[bakSymbolInFront,bakSymbolBehind,bakUserDefinedAddExt,bakSameName] then
|
||||
begin
|
||||
case BackupInfo.BackupType of
|
||||
bakSymbolInFront:
|
||||
BackupFilename:=FileNameOnly+'.~'+copy(FileExt,2,length(FileExt)-1);
|
||||
bakSymbolBehind:
|
||||
BackupFilename:=FileNameOnly+FileExt+'~';
|
||||
bakUserDefinedAddExt:
|
||||
BackupFilename:=FileNameOnly+FileExt+'.'+BackupInfo.AdditionalExtension;
|
||||
bakSameName:
|
||||
BackupFilename:=FileNameOnly+FileExt;
|
||||
end;
|
||||
if BackupInfo.SubDirectory<>'' then
|
||||
BackupFilename:=SubDir+PathDelim+BackupFilename
|
||||
else
|
||||
BackupFilename:=FilePath+BackupFilename;
|
||||
// remove old backup file
|
||||
repeat
|
||||
if FileExists(BackupFilename) then begin
|
||||
if not DeleteFile(BackupFilename) then begin
|
||||
ACaption:=lisDeleteFileFailed;
|
||||
AText:=Format(lisUnableToRemoveOldBackupFile, ['"', BackupFilename,
|
||||
'"']);
|
||||
Result:=MessageDlg(ACaption,AText,mtError,[mbAbort,mbRetry,mbIgnore],
|
||||
0);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end else begin
|
||||
// backup with counter
|
||||
if BackupInfo.SubDirectory<>'' then
|
||||
BackupFilename:=SubDir+PathDelim+FileNameOnly+FileExt+';'
|
||||
else
|
||||
BackupFilename:=Filename+';';
|
||||
if BackupInfo.MaxCounter<=0 then begin
|
||||
// search first non existing backup filename
|
||||
i:=1;
|
||||
while FileExists(BackupFilename+IntToStr(i)) do inc(i);
|
||||
BackupFilename:=BackupFilename+IntToStr(i);
|
||||
end else begin
|
||||
// rename all backup files (increase number)
|
||||
i:=1;
|
||||
while FileExists(BackupFilename+IntToStr(i))
|
||||
and (i<=BackupInfo.MaxCounter) do inc(i);
|
||||
if i>BackupInfo.MaxCounter then begin
|
||||
dec(i);
|
||||
CounterFilename:=BackupFilename+IntToStr(BackupInfo.MaxCounter);
|
||||
// remove old backup file
|
||||
repeat
|
||||
if FileExists(CounterFilename) then begin
|
||||
if not DeleteFile(CounterFilename) then begin
|
||||
ACaption:=lisDeleteFileFailed;
|
||||
AText:=Format(lisUnableToRemoveOldBackupFile, ['"',
|
||||
CounterFilename, '"']);
|
||||
Result:=MessageDlg(ACaption,AText,mtError,
|
||||
[mbAbort,mbRetry,mbIgnore],0);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
// rename all old backup files
|
||||
dec(i);
|
||||
while i>=1 do begin
|
||||
repeat
|
||||
if not RenameFile(BackupFilename+IntToStr(i),
|
||||
BackupFilename+IntToStr(i+1)) then
|
||||
begin
|
||||
ACaption:=lisRenameFileFailed;
|
||||
AText:=Format(lisUnableToRenameFileTo, ['"', BackupFilename+IntToStr
|
||||
(i), '"', '"', BackupFilename+IntToStr(i+1), '"']);
|
||||
Result:=MessageDlg(ACaption,AText,mtError,
|
||||
[mbAbort,mbRetry,mbIgnore],0);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
dec(i);
|
||||
end;
|
||||
BackupFilename:=BackupFilename+'1';
|
||||
end;
|
||||
end;
|
||||
// backup file
|
||||
repeat
|
||||
if not BackupFile(Filename,BackupFilename) then begin
|
||||
ACaption:=lisBackupFileFailed;
|
||||
AText:=Format(lisUnableToBackupFileTo, ['"', Filename, '"', '"',
|
||||
BackupFilename, '"']);
|
||||
Result:=MessageDlg(ACaption,AText,mterror,[mbabort,mbretry,mbignore],0);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
end;
|
||||
|
||||
function TMainIDE.DoRenameUnitLowerCase(AnUnitInfo: TUnitInfo;
|
||||
AskUser: boolean): TModalresult;
|
||||
var
|
||||
|
303
ide/mainbase.pas
303
ide/mainbase.pas
@ -143,13 +143,6 @@ type
|
||||
var ActiveSourceEditor: TSourceEditor; var ActiveUnitInfo: TUnitInfo); virtual; abstract;
|
||||
function GetSourceEditorForUnitInfo(AnUnitInfo: TUnitInfo): TSourceEditor; virtual; abstract;
|
||||
|
||||
function DoCheckAmbiguousSources(const AFilename: string;
|
||||
Compiling: boolean): TModalResult; override;
|
||||
function DoDeleteAmbiguousFiles(const Filename:string
|
||||
): TModalResult; override;
|
||||
function DoCheckUnitPathForAmbiguousPascalFiles(const BaseDir, TheUnitPath,
|
||||
CompiledExt, ContextDescription: string
|
||||
): TModalResult; override;
|
||||
function DoOpenMacroFile(Sender: TObject; const AFilename: string
|
||||
): TModalResult; override;
|
||||
|
||||
@ -178,24 +171,6 @@ var
|
||||
implementation
|
||||
|
||||
|
||||
type
|
||||
TUnitFile = record
|
||||
UnitName: string;
|
||||
Filename: string;
|
||||
end;
|
||||
PUnitFile = ^TUnitFile;
|
||||
|
||||
function CompareUnitFiles(UnitFile1, UnitFile2: PUnitFile): integer;
|
||||
begin
|
||||
Result:=AnsiCompareText(UnitFile1^.UnitName,UnitFile2^.UnitName);
|
||||
end;
|
||||
|
||||
function CompareUnitNameAndUnitFile(UnitName: PChar;
|
||||
UnitFile: PUnitFile): integer;
|
||||
begin
|
||||
Result:=CompareStringPointerI(UnitName,PChar(UnitFile^.UnitName));
|
||||
end;
|
||||
|
||||
{ TMainIDEBase }
|
||||
|
||||
procedure TMainIDEBase.mnuWindowsItemClick(Sender: TObject);
|
||||
@ -957,286 +932,14 @@ begin
|
||||
[ofOnlyIfExists,ofAddToRecent,ofRegularFile,ofConvertMacros]);
|
||||
end;
|
||||
|
||||
function TMainIDEBase.DoDeleteAmbiguousFiles(const Filename: string
|
||||
): TModalResult;
|
||||
var
|
||||
ADirectory: String;
|
||||
FileInfo: TSearchRec;
|
||||
ShortFilename: String;
|
||||
CurFilename: String;
|
||||
IsPascalUnit: Boolean;
|
||||
UnitName: String;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if EnvironmentOptions.AmbiguousFileAction=afaIgnore then exit;
|
||||
if EnvironmentOptions.AmbiguousFileAction
|
||||
in [afaAsk,afaAutoDelete,afaAutoRename]
|
||||
then begin
|
||||
ADirectory:=AppendPathDelim(ExtractFilePath(Filename));
|
||||
if SysUtils.FindFirst(ADirectory+GetAllFilesMask,faAnyFile,FileInfo)=0 then
|
||||
begin
|
||||
ShortFilename:=ExtractFileName(Filename);
|
||||
IsPascalUnit:=FilenameIsPascalUnit(ShortFilename);
|
||||
UnitName:=ExtractFilenameOnly(ShortFilename);
|
||||
repeat
|
||||
if (FileInfo.Name='.') or (FileInfo.Name='..')
|
||||
or (FileInfo.Name='')
|
||||
or ((FileInfo.Attr and faDirectory)<>0) then continue;
|
||||
if (ShortFilename=FileInfo.Name) then continue;
|
||||
if (AnsiCompareText(ShortFilename,FileInfo.Name)<>0)
|
||||
and ((not IsPascalUnit) or (not FilenameIsPascalUnit(FileInfo.Name))
|
||||
or (AnsiCompareText(UnitName,ExtractFilenameOnly(FileInfo.Name))<>0))
|
||||
then
|
||||
continue;
|
||||
|
||||
CurFilename:=ADirectory+FileInfo.Name;
|
||||
if EnvironmentOptions.AmbiguousFileAction=afaAsk then begin
|
||||
if MessageDlg(lisDeleteAmbiguousFile,
|
||||
Format(lisAmbiguousFileFoundThisFileCanBeMistakenWithDelete, ['"',
|
||||
CurFilename, '"', #13, '"', ShortFilename, '"', #13, #13]),
|
||||
mtConfirmation,[mbYes,mbNo],0)=mrNo
|
||||
then continue;
|
||||
end;
|
||||
if EnvironmentOptions.AmbiguousFileAction in [afaAutoDelete,afaAsk]
|
||||
then begin
|
||||
if not DeleteFile(CurFilename) then begin
|
||||
MessageDlg(lisDeleteFileFailed,
|
||||
Format(lisPkgMangUnableToDeleteFile, ['"', CurFilename, '"']),
|
||||
mtError,[mbOk],0);
|
||||
end;
|
||||
end else if EnvironmentOptions.AmbiguousFileAction=afaAutoRename then
|
||||
begin
|
||||
Result:=DoBackupFile(CurFilename,false);
|
||||
if Result=mrABort then exit;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
until SysUtils.FindNext(FileInfo)<>0;
|
||||
end;
|
||||
FindClose(FileInfo);
|
||||
end;
|
||||
end;
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
function TMainIDEBase.DoCheckUnitPathForAmbiguousPascalFiles(
|
||||
const BaseDir, TheUnitPath, CompiledExt, ContextDescription: string
|
||||
): TModalResult;
|
||||
|
||||
Collect all pascal files and all compiled units in the unit path and check
|
||||
for ambiguous files. For example: doubles.
|
||||
-------------------------------------------------------------------------------}
|
||||
function TMainIDEBase.DoCheckUnitPathForAmbiguousPascalFiles(
|
||||
const BaseDir, TheUnitPath, CompiledExt, ContextDescription: string): TModalResult;
|
||||
|
||||
procedure FreeUnitTree(var Tree: TAVLTree);
|
||||
var
|
||||
ANode: TAVLTreeNode;
|
||||
AnUnitFile: PUnitFile;
|
||||
begin
|
||||
if Tree<>nil then begin
|
||||
ANode:=Tree.FindLowest;
|
||||
while ANode<>nil do begin
|
||||
AnUnitFile:=PUnitFile(ANode.Data);
|
||||
Dispose(AnUnitFile);
|
||||
ANode:=Tree.FindSuccessor(ANode);
|
||||
end;
|
||||
Tree.Free;
|
||||
Tree:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
EndPos: Integer;
|
||||
StartPos: Integer;
|
||||
CurDir: String;
|
||||
FileInfo: TSearchRec;
|
||||
SourceUnitTree, CompiledUnitTree: TAVLTree;
|
||||
ANode: TAVLTreeNode;
|
||||
CurUnitName: String;
|
||||
CurFilename: String;
|
||||
AnUnitFile: PUnitFile;
|
||||
CurUnitTree: TAVLTree;
|
||||
FileInfoNeedClose: Boolean;
|
||||
UnitPath: String;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
UnitPath:=TrimSearchPath(TheUnitPath,BaseDir);
|
||||
|
||||
//writeln('TMainIDEBase.DoCheckUnitPathForAmbiguousPascalFiles A UnitPath="',UnitPath,'" Ext=',CompiledExt,' Context=',ContextDescription);
|
||||
|
||||
SourceUnitTree:=TAVLTree.Create(TListSortCompare(@CompareUnitFiles));
|
||||
CompiledUnitTree:=TAVLTree.Create(TListSortCompare(@CompareUnitFiles));
|
||||
FileInfoNeedClose:=false;
|
||||
try
|
||||
// collect all units (.pas, .pp, compiled units)
|
||||
EndPos:=1;
|
||||
while EndPos<=length(UnitPath) do begin
|
||||
StartPos:=EndPos;
|
||||
while (StartPos<=length(UnitPath)) and (UnitPath[StartPos]=';') do
|
||||
inc(StartPos);
|
||||
EndPos:=StartPos;
|
||||
while (EndPos<=length(UnitPath)) and (UnitPath[EndPos]<>';') do
|
||||
inc(EndPos);
|
||||
if EndPos>StartPos then begin
|
||||
CurDir:=AppendPathDelim(TrimFilename(copy(
|
||||
UnitPath,StartPos,EndPos-StartPos)));
|
||||
FileInfoNeedClose:=true;
|
||||
if SysUtils.FindFirst(CurDir+GetAllFilesMask,faAnyFile,FileInfo)=0 then begin
|
||||
repeat
|
||||
if (FileInfo.Name='.') or (FileInfo.Name='..') or (FileInfo.Name='')
|
||||
or ((FileInfo.Attr and faDirectory)<>0) then continue;
|
||||
if FilenameIsPascalUnit(FileInfo.Name) then
|
||||
CurUnitTree:=SourceUnitTree
|
||||
else if (CompareFileExt(FileInfo.Name,CompiledExt,false)=0) then
|
||||
CurUnitTree:=CompiledUnitTree
|
||||
else
|
||||
continue;
|
||||
CurUnitName:=ExtractFilenameOnly(FileInfo.Name);
|
||||
CurFilename:=CurDir+FileInfo.Name;
|
||||
// check if unit already found
|
||||
ANode:=CurUnitTree.FindKey(PChar(CurUnitName),
|
||||
TListSortCompare(@CompareUnitNameAndUnitFile));
|
||||
if ANode<>nil then begin
|
||||
// pascal unit exists twice
|
||||
Result:=MessageDlg('Ambiguous unit found',
|
||||
'The unit '+CurUnitName+' exists twice in the unit path of the '
|
||||
+ContextDescription+':'#13
|
||||
+#13
|
||||
+'1. "'+PUnitFile(ANode.Data)^.Filename+'"'#13
|
||||
+'2. "'+CurFilename+'"'#13
|
||||
+#13
|
||||
+'Hint: Check if two packages contain a unit with the same name.',
|
||||
mtWarning,[mbAbort,mbIgnore],0);
|
||||
if Result<>mrIgnore then exit;
|
||||
end;
|
||||
// add unit to tree
|
||||
New(AnUnitFile);
|
||||
AnUnitFile^.UnitName:=CurUnitName;
|
||||
AnUnitFile^.Filename:=CurFilename;
|
||||
CurUnitTree.Add(AnUnitFile);
|
||||
until SysUtils.FindNext(FileInfo)<>0;
|
||||
end;
|
||||
FindClose(FileInfo);
|
||||
FileInfoNeedClose:=false;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
// clean up
|
||||
if FileInfoNeedClose then FindClose(FileInfo);
|
||||
FreeUnitTree(SourceUnitTree);
|
||||
FreeUnitTree(CompiledUnitTree);
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
function TMainIDEBase.DoCheckAmbiguousSources(const AFilename: string
|
||||
): TModalResult;
|
||||
|
||||
Checks if file exists with same name and similar extension. The compiler
|
||||
prefers for example .pp to .pas files. So, if we save a .pas file delete .pp
|
||||
file, so that compiling does what is expected.
|
||||
-------------------------------------------------------------------------------}
|
||||
function TMainIDEBase.DoCheckAmbiguousSources(const AFilename: string;
|
||||
Compiling: boolean): TModalResult;
|
||||
|
||||
function DeleteAmbiguousFile(const AmbiguousFilename: string): TModalResult;
|
||||
begin
|
||||
if not DeleteFile(AmbiguousFilename) then begin
|
||||
Result:=MessageDlg(lisErrorDeletingFile,
|
||||
Format(lisUnableToDeleteAmbiguousFile, ['"', AmbiguousFilename, '"']),
|
||||
mtError,[mbOk,mbAbort],0);
|
||||
end else
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function RenameAmbiguousFile(const AmbiguousFilename: string): TModalResult;
|
||||
var
|
||||
NewFilename: string;
|
||||
begin
|
||||
NewFilename:=AmbiguousFilename+'.ambiguous';
|
||||
if not RenameFile(AmbiguousFilename,NewFilename) then
|
||||
begin
|
||||
Result:=MessageDlg(lisErrorRenamingFile,
|
||||
Format(lisUnableToRenameAmbiguousFileTo, ['"', AmbiguousFilename, '"',
|
||||
#13, '"', NewFilename, '"']),
|
||||
mtError,[mbOk,mbAbort],0);
|
||||
end else
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function AddCompileWarning(const AmbiguousFilename: string): TModalResult;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if Compiling then begin
|
||||
TheOutputFilter.ReadConstLine(Format(lisWarningAmbiguousFileFoundSourceFileIs,
|
||||
['"', AmbiguousFilename, '"', '"', AFilename, '"']), true);
|
||||
end;
|
||||
end;
|
||||
|
||||
function CheckFile(const AmbiguousFilename: string): TModalResult;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if not FileExists(AmbiguousFilename) then exit;
|
||||
if Compiling then begin
|
||||
Result:=AddCompileWarning(AmbiguousFilename);
|
||||
exit;
|
||||
end;
|
||||
case EnvironmentOptions.AmbiguousFileAction of
|
||||
afaAsk:
|
||||
begin
|
||||
Result:=MessageDlg(lisAmbiguousFileFound,
|
||||
Format(lisThereIsAFileWithTheSameNameAndASimilarExtension, [#13,
|
||||
AFilename, #13, AmbiguousFilename, #13, #13]),
|
||||
mtWarning,[mbYes,mbIgnore,mbAbort],0);
|
||||
case Result of
|
||||
mrYes: Result:=DeleteAmbiguousFile(AmbiguousFilename);
|
||||
mrIgnore: Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
|
||||
afaAutoDelete:
|
||||
Result:=DeleteAmbiguousFile(AmbiguousFilename);
|
||||
|
||||
afaAutoRename:
|
||||
Result:=RenameAmbiguousFile(AmbiguousFilename);
|
||||
|
||||
afaWarnOnCompile:
|
||||
Result:=AddCompileWarning(AmbiguousFilename);
|
||||
|
||||
else
|
||||
Result:=mrOk;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
Ext, LowExt: string;
|
||||
i: integer;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if EnvironmentOptions.AmbiguousFileAction=afaIgnore then exit;
|
||||
if (EnvironmentOptions.AmbiguousFileAction=afaWarnOnCompile)
|
||||
and not Compiling then exit;
|
||||
|
||||
if FilenameIsPascalUnit(AFilename) then begin
|
||||
Ext:=ExtractFileExt(AFilename);
|
||||
LowExt:=lowercase(Ext);
|
||||
for i:=Low(PascalFileExt) to High(PascalFileExt) do begin
|
||||
if LowExt<>PascalFileExt[i] then begin
|
||||
Result:=CheckFile(ChangeFileExt(AFilename,PascalFileExt[i]));
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainIDEBase.UpdateWindowsMenu;
|
||||
var
|
||||
WindowsList: TList;
|
||||
WindowsList: TFPList;
|
||||
i: Integer;
|
||||
CurMenuItem: TIDEMenuItem;
|
||||
AForm: TForm;
|
||||
begin
|
||||
WindowsList:=TList.Create;
|
||||
WindowsList:=TFPList.Create;
|
||||
// add typical IDE windows at the start of the list
|
||||
if (SourceNotebook<>nil) and (SourceNotebook.Visible) then
|
||||
WindowsList.Add(SourceNotebook);
|
||||
@ -1245,7 +948,7 @@ begin
|
||||
// add special IDE windows
|
||||
for i:=0 to Screen.FormCount-1 do begin
|
||||
AForm:=Screen.Forms[i];
|
||||
if (AForm<>MainIDEBar) and (AForm<>SplashForm)
|
||||
if (AForm.Parent=nil) and (AForm<>MainIDEBar) and (AForm<>SplashForm)
|
||||
and (AForm.Designer=nil) and (AForm.Visible)
|
||||
and (WindowsList.IndexOf(AForm)<0) then
|
||||
WindowsList.Add(AForm);
|
||||
|
@ -154,28 +154,11 @@ type
|
||||
function PrepareForCompile: TModalResult; virtual; abstract;
|
||||
function DoSaveBuildIDEConfigs(Flags: TBuildLazarusFlags): TModalResult; virtual; abstract;
|
||||
function DoBuildLazarus(Flags: TBuildLazarusFlags): TModalResult; virtual; abstract;
|
||||
function DoExecuteCompilationTool(Tool: TCompilationToolOptions;
|
||||
const WorkingDir, ToolTitle: string
|
||||
): TModalResult; virtual; abstract;
|
||||
function DoSaveForBuild: TModalResult; virtual; abstract;
|
||||
function DoCheckFilesOnDisk(Instantaneous: boolean = false): TModalResult; virtual; abstract;
|
||||
function DoPublishModule(Options: TPublishModuleOptions;
|
||||
const SrcDirectory, DestDirectory: string
|
||||
): TModalResult; virtual; abstract;
|
||||
function DoCheckAmbiguousSources(const AFilename: string;
|
||||
Compiling: boolean): TModalResult; virtual; abstract;
|
||||
function DoSaveStringToFile(const Filename, Src,
|
||||
FileDescription: string): TModalResult; virtual; abstract;
|
||||
function DoSaveCodeBufferToFile(ABuffer: TCodeBuffer;
|
||||
const AFilename: string;
|
||||
IsPartOfProject:boolean): TModalResult; virtual; abstract;
|
||||
function DoBackupFile(const Filename:string;
|
||||
IsPartOfProject:boolean): TModalResult; virtual; abstract;
|
||||
function DoDeleteAmbiguousFiles(const Filename:string
|
||||
): TModalResult; virtual; abstract;
|
||||
function DoCheckUnitPathForAmbiguousPascalFiles(const BaseDir, TheUnitPath,
|
||||
CompiledExt, ContextDescription: string
|
||||
): TModalResult; virtual; abstract;
|
||||
|
||||
procedure UpdateWindowsMenu; virtual; abstract;
|
||||
procedure SaveEnvironment; virtual; abstract;
|
||||
|
@ -119,8 +119,8 @@ type
|
||||
procedure ShowTopMessage;
|
||||
procedure Clear; override;
|
||||
procedure GetVisibleMessageAt(Index: integer; var Msg, MsgDirectory: string);
|
||||
procedure BeginBlock;
|
||||
procedure EndBlock;
|
||||
procedure BeginBlock; override;
|
||||
procedure EndBlock; override;
|
||||
procedure ClearItems;
|
||||
function LinesCount: integer; override;
|
||||
function VisibleItemCount: integer;
|
||||
|
@ -26,15 +26,6 @@ unit OutputFilter;
|
||||
|
||||
interface
|
||||
|
||||
// TODO: Test on all platforms
|
||||
{$IFNDEF DisableAsyncProcess}
|
||||
{$IFDEF Linux}
|
||||
{$IFDEF CPUI386}
|
||||
{off $DEFINE UseAsyncProcess}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
uses
|
||||
Classes, Math, SysUtils, Forms, Controls, CompilerOptions, Project, Process,
|
||||
AsyncProcess, LCLProc, DynQueue, FileUtil,
|
||||
@ -48,12 +39,6 @@ type
|
||||
TOnGetIncludePath = function(const Directory: string;
|
||||
UseCache: boolean): string of object;
|
||||
|
||||
{$IFDEF UseAsyncProcess}
|
||||
TOutputFilterProcess = TAsyncProcess;
|
||||
{$ELSE}
|
||||
TOutputFilterProcess = TProcess;
|
||||
{$ENDIF}
|
||||
|
||||
TOuputFilterOption = (
|
||||
ofoShowAll, // don't filter
|
||||
ofoSearchForFPCMessages, // scan for freepascal compiler messages
|
||||
@ -192,6 +177,12 @@ type
|
||||
EOutputFilterError = class(Exception)
|
||||
end;
|
||||
|
||||
type
|
||||
TProcessClass = class of TProcess;
|
||||
|
||||
var
|
||||
TOutputFilterProcess: TProcessClass = nil;
|
||||
|
||||
const
|
||||
ErrorTypeNames : array[TErrorType] of string = (
|
||||
'None','Hint','Note','Warning','Error','Fatal','Panic'
|
||||
@ -274,7 +265,7 @@ begin
|
||||
|
||||
fProcess.Execute;
|
||||
repeat
|
||||
Application.ProcessMessages;
|
||||
if Application<>nil then Application.ProcessMessages;
|
||||
if StopExecute then begin
|
||||
fProcess.Terminate(0);
|
||||
Aborted:=true;
|
||||
@ -1285,4 +1276,3 @@ end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
@ -57,8 +57,7 @@ type
|
||||
TUnitInfo = class;
|
||||
TProject = class;
|
||||
|
||||
TOnFileBackup = function(const FileToBackup:string;
|
||||
IsPartOfProject:boolean):TModalResult of object;
|
||||
TOnFileBackup = function(const FileToBackup: string):TModalResult of object;
|
||||
TOnUnitNameChange = procedure(AnUnitInfo: TUnitInfo;
|
||||
const OldUnitName, NewUnitName: string;
|
||||
CheckIfAllowed: boolean;
|
||||
@ -484,8 +483,7 @@ type
|
||||
function GetUnits(Index: integer): TUnitInfo;
|
||||
function JumpHistoryCheckPosition(
|
||||
APosition:TProjectJumpHistoryPosition): boolean;
|
||||
function OnUnitFileBackup(const Filename: string;
|
||||
IsPartOfProject:boolean): TModalResult;
|
||||
function OnUnitFileBackup(const Filename: string): TModalResult;
|
||||
procedure OnLoadSaveFilename(var AFilename: string; Load: boolean);
|
||||
procedure OnUnitNameChange(AnUnitInfo: TUnitInfo;
|
||||
const OldUnitName, NewUnitName: string;
|
||||
@ -766,7 +764,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
if Assigned(fOnFileBackup) then begin
|
||||
Result:=fOnFileBackup(Filename,IsPartOfProject);
|
||||
Result:=fOnFileBackup(Filename);
|
||||
if Result=mrAbort then exit;
|
||||
end;
|
||||
repeat
|
||||
@ -795,7 +793,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
if Assigned(fOnFileBackup) then begin
|
||||
Result:=fOnFileBackup(Filename,false);
|
||||
Result:=fOnFileBackup(Filename);
|
||||
if Result=mrAbort then exit;
|
||||
end;
|
||||
repeat
|
||||
@ -1579,7 +1577,7 @@ begin
|
||||
else
|
||||
CfgFilename := ProjectInfoFile;
|
||||
if Assigned(fOnFileBackup) then begin
|
||||
Result:=fOnFileBackup(CfgFilename,true);
|
||||
Result:=fOnFileBackup(CfgFilename);
|
||||
if Result=mrAbort then exit;
|
||||
end;
|
||||
CfgFilename:=SetDirSeparators(CfgFilename);
|
||||
@ -1695,7 +1693,7 @@ begin
|
||||
//DebugLn('TProject.WriteProject Write Session File="',CurSessionFilename,'"');
|
||||
|
||||
if Assigned(fOnFileBackup) then begin
|
||||
Result:=fOnFileBackup(CurSessionFilename,true);
|
||||
Result:=fOnFileBackup(CurSessionFilename);
|
||||
if Result=mrAbort then exit;
|
||||
end;
|
||||
CurSessionFilename:=SetDirSeparators(CurSessionFilename);
|
||||
@ -2806,11 +2804,10 @@ begin
|
||||
UpdateSessionFilename;
|
||||
end;
|
||||
|
||||
function TProject.OnUnitFileBackup(const Filename:string;
|
||||
IsPartOfProject: boolean):TModalResult;
|
||||
function TProject.OnUnitFileBackup(const Filename: string): TModalResult;
|
||||
begin
|
||||
if Assigned(fOnFileBackup) then
|
||||
Result:=fOnFileBackup(Filename,IsPartOfProject)
|
||||
Result:=fOnFileBackup(Filename)
|
||||
else
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
@ -621,7 +621,7 @@ type
|
||||
function SomethingModified: boolean;
|
||||
procedure UpdateStatusBar;
|
||||
Procedure ClearUnusedEditorComponents(Force: boolean);
|
||||
procedure ClearErrorLines;
|
||||
procedure ClearErrorLines; override;
|
||||
procedure ClearExecutionLines;
|
||||
|
||||
procedure CloseTabClicked(Sender: TObject);
|
||||
|
@ -104,6 +104,12 @@ type
|
||||
property ShowAllOutput: boolean read FShowAllOutput write SetShowAllOutput;
|
||||
property OnParseLine: TOnIDEExtToolParseLine read FOnParseLine write FOnParseLine;
|
||||
end;
|
||||
|
||||
type
|
||||
TRunExternalTool = function (Tool: TIDEExternalToolOptions): TModalResult of object;
|
||||
|
||||
var
|
||||
RunExternalTool: TRunExternalTool = nil;// set by the IDE
|
||||
|
||||
implementation
|
||||
|
||||
|
@ -183,11 +183,13 @@ type
|
||||
procedure AddMsg(const Msg, CurDir: string; OriginalIndex: integer); virtual; abstract;
|
||||
property Lines[Index: integer]: TIDEMessageLine read GetLines; default;
|
||||
function LinesCount: integer; virtual; abstract;
|
||||
procedure BeginBlock; virtual; abstract;
|
||||
procedure EndBlock; virtual; abstract;
|
||||
end;
|
||||
|
||||
var
|
||||
IDEMsgQuickFixes: TIDEMsgQuickFixItems; // initialized by the IDE
|
||||
IDEMessagesWindow: TIDEMessagesWindowInterface;// initialized by the IDE
|
||||
IDEMsgQuickFixes: TIDEMsgQuickFixItems = nil; // initialized by the IDE
|
||||
IDEMessagesWindow: TIDEMessagesWindowInterface = nil;// initialized by the IDE
|
||||
|
||||
procedure RegisterIDEMsgQuickFix(Item: TIDEMsgQuickFixItem);
|
||||
function RegisterIDEMsgQuickFix(const Name, Caption, RegExpr: string;
|
||||
|
@ -120,7 +120,7 @@ type
|
||||
trtMatchCase, // search case sensitive
|
||||
trtWholeWord, // search at word boundaries
|
||||
trtRegExpr, // use regular expressions for find and replace
|
||||
trtMultiLine // ignore line boundaries. The expression can span multiple lines.
|
||||
trtMultiLine // ignore type of line endings in pattern (e.g. #10 = #13#10)
|
||||
//TODO trtSearchInReplacement,// when replaced, continue search at start of replacement, instead of end of replacement
|
||||
//TODO trtReplaceUntilNotFound// restart replace until pattern not found
|
||||
);
|
||||
@ -578,7 +578,7 @@ begin
|
||||
if aText=nil then exit;
|
||||
if SearchFor='' then exit(mrOk);
|
||||
Source:=aText.Source;
|
||||
Flags:=[];
|
||||
Flags:=[sesoReplace,sesoReplaceAll];
|
||||
if trtMatchCase in Options then Include(Flags,sesoMatchCase);
|
||||
if trtWholeWord in Options then Include(Flags,sesoWholeWord);
|
||||
if trtRegExpr in Options then Include(Flags,sesoRegExpr);
|
||||
|
@ -199,9 +199,6 @@ type
|
||||
function GetProjectFileWithRootComponent(AComponent: TComponent): TLazProjectFile; virtual; abstract;
|
||||
function GetProjectFileWithDesigner(ADesigner: TIDesigner): TLazProjectFile; virtual; abstract;
|
||||
|
||||
// external tools
|
||||
function RunExternalTool(Tool: TIDEExternalToolOptions): TModalResult; virtual; abstract;
|
||||
|
||||
// events
|
||||
procedure RemoveAllHandlersOfObject(AnObject: TObject);
|
||||
procedure AddHandlerOnSavingAll(const OnSaveAllEvent: TModalResultFunction;
|
||||
@ -213,7 +210,7 @@ type
|
||||
end;
|
||||
|
||||
var
|
||||
LazarusIDE: TLazIDEInterface; // will be set by the IDE
|
||||
LazarusIDE: TLazIDEInterface = nil; // will be set by the IDE
|
||||
|
||||
implementation
|
||||
|
||||
|
@ -524,7 +524,7 @@ type
|
||||
|
||||
{ TObjectInspector }
|
||||
|
||||
TObjectInspector = class (TForm)
|
||||
TObjectInspector = class(TForm)
|
||||
AvailPersistentComboBox: TComboBox;
|
||||
Splitter1: TSplitter;
|
||||
ComponentTree: TComponentTreeView;
|
||||
@ -1106,6 +1106,7 @@ begin
|
||||
DoPaint(true)
|
||||
else
|
||||
FPropertyEditorHook.RefreshPropertyValues;
|
||||
//DebugLn(['TOICustomPropertyGrid.SetRowValue ',CurRow.Name,' ',CurRow.Editor.GetVisualValue,' ',Assigned(FOnModified)]);
|
||||
if Assigned(FOnModified) then FOnModified(Self);
|
||||
end;
|
||||
|
||||
|
@ -53,6 +53,18 @@ type
|
||||
);
|
||||
TPkgCompileFlags = set of TPkgCompileFlag;
|
||||
|
||||
const
|
||||
PkgCompileFlagNames: array[TPkgCompileFlag] of string = (
|
||||
'pcfCleanCompile',
|
||||
'pcfDoNotCompileDependencies',
|
||||
'pcfDoNotCompilePackage',
|
||||
'pcfCompileDependenciesClean',
|
||||
'pcfOnlyIfNeeded',
|
||||
'pcfDoNotSaveEditorFiles',
|
||||
'pcfCreateMakefile'
|
||||
);
|
||||
|
||||
type
|
||||
{ TPackageEditingInterface }
|
||||
|
||||
TPackageEditingInterface = class(TComponent)
|
||||
@ -134,10 +146,25 @@ var
|
||||
procedure RegisterPackageDescriptor(PkgDesc: TPackageDescriptor);
|
||||
function PackageDescriptorStd: TPackageDescriptor;
|
||||
|
||||
function PkgCompileFlagsToString(Flags: TPkgCompileFlags): string;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
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;
|
||||
|
||||
procedure RegisterPackageDescriptor(PkgDesc: TPackageDescriptor);
|
||||
var
|
||||
NewItemPkg: TNewItemPackage;
|
||||
|
@ -148,6 +148,7 @@ type
|
||||
|
||||
function GetEditorControlSettings(EditControl: TControl): boolean; virtual; abstract;
|
||||
function GetHighlighterSettings(Highlighter: TObject): boolean; virtual; abstract;
|
||||
procedure ClearErrorLines; virtual; abstract;
|
||||
end;
|
||||
|
||||
|
||||
|
14
lcl/forms.pp
14
lcl/forms.pp
@ -1244,7 +1244,7 @@ type
|
||||
function(AComponent: TComponent): TCustomForm of object;
|
||||
|
||||
var
|
||||
OnGetDesignerForm: TGetDesignerFormEvent;
|
||||
OnGetDesignerForm: TGetDesignerFormEvent = nil;
|
||||
|
||||
function GetParentForm(Control:TControl): TCustomForm;
|
||||
function GetFirstParentForm(Control:TControl): TCustomForm;
|
||||
@ -1263,16 +1263,16 @@ function GetLongHint(const Hint: string): string;
|
||||
|
||||
|
||||
var
|
||||
Application: TApplication;
|
||||
Screen: TScreen;
|
||||
Application: TApplication = nil;
|
||||
Screen: TScreen = nil;
|
||||
ExceptionObject: TExceptObject;
|
||||
HintWindowClass: THintWindowClass=THintWindow;
|
||||
HintWindowClass: THintWindowClass = THintWindow;
|
||||
|
||||
type
|
||||
TMessageBoxFunction =
|
||||
function(Text, Caption : PChar; Flags : Longint) : Integer;
|
||||
var
|
||||
MessageBoxFunction: TMessageBoxFunction;
|
||||
MessageBoxFunction: TMessageBoxFunction = nil;
|
||||
|
||||
const
|
||||
DefaultBorderIcons : array[TFormBorderStyle] of TBorderIcons =
|
||||
@ -1747,8 +1747,8 @@ end;
|
||||
|
||||
initialization
|
||||
LCLProc.OwnerFormDesignerModifiedProc:=@IfOwnerIsFormThenDesignerModified;
|
||||
Screen:= TScreen.Create(nil);
|
||||
Application:= TApplication.Create(nil);
|
||||
Screen:=TScreen.Create(nil);
|
||||
Application:=TApplication.Create(nil);
|
||||
|
||||
{$IFDEF UseFCLDataModule}
|
||||
RegisterInitComponentHandler(TComponent,@InitResourceComponent);
|
||||
|
@ -642,7 +642,6 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TCustomForm.DoDestroy;
|
||||
begin
|
||||
DebugLn(['TCustomForm.DoDestroy ',dbgsName(Self)]);
|
||||
if Assigned(FOnDestroy) then FOnDestroy(Self);
|
||||
end;
|
||||
|
||||
|
@ -102,14 +102,18 @@ begin
|
||||
FFormList.Insert(0, ACustomForm);
|
||||
end;
|
||||
end;
|
||||
MoveFormToZFront(ACustomForm);
|
||||
end;
|
||||
|
||||
procedure TScreen.MoveFormToZFront(ACustomForm: TCustomForm);
|
||||
//var i: Integer;
|
||||
begin
|
||||
if (FCustomFormsZOrdered.Count=0)
|
||||
or (TObject(FCustomFormsZOrdered[0])<>ACustomForm) then begin
|
||||
FCustomFormsZOrdered.Remove(ACustomForm);
|
||||
FCustomFormsZOrdered.Insert(0, ACustomForm);
|
||||
//for i:=0 to FCustomFormsZOrdered.Count-1 do
|
||||
// DebugLn(['TScreen.MoveFormToZFront ',i,'/',FCustomFormsZOrdered.Count,' ',dbgsName(CustomFormsZOrdered[i])]);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -44,7 +44,7 @@ uses
|
||||
{$IFDEF IDE_MEM_CHECK}
|
||||
MemCheck,
|
||||
{$ENDIF}
|
||||
Classes, SysUtils, Forms, FileUtil,
|
||||
Classes, SysUtils, Forms, FileUtil, LCLProc,
|
||||
LazIDEIntf, PackageIntf, MenuIntf,
|
||||
LazarusIDEStrConsts, EnvironmentOpts,
|
||||
PackageDefs, ComponentReg, CompilerOptions, Project;
|
||||
@ -114,10 +114,6 @@ type
|
||||
Flags: TPkgCompileFlags): TModalResult; virtual; abstract;
|
||||
function DoCompilePackage(APackage: TLazPackage; Flags: TPkgCompileFlags;
|
||||
Globals: TGlobalCompilerOptions = nil): TModalResult; virtual; abstract;
|
||||
function DoSavePackageMainSource(APackage: TLazPackage;
|
||||
Flags: TPkgCompileFlags): TModalResult; virtual; abstract;
|
||||
function DoCheckIfDependenciesNeedCompilation(DependencyOwner: TObject;
|
||||
StateFileAge: longint): TModalResult; virtual; abstract;
|
||||
|
||||
// package installation
|
||||
procedure LoadInstalledPackages; virtual; abstract;
|
||||
@ -145,24 +141,13 @@ const
|
||||
'pofRevert'
|
||||
);
|
||||
|
||||
PkgCompileFlagNames: array[TPkgCompileFlag] of string = (
|
||||
'pcfCleanCompile',
|
||||
'pcfDoNotCompileDependencies',
|
||||
'pcfDoNotCompilePackage',
|
||||
'pcfCompileDependenciesClean',
|
||||
'pcfOnlyIfNeeded',
|
||||
'pcfDoNotSaveEditorFiles',
|
||||
'pcfCreateMakefile'
|
||||
);
|
||||
|
||||
function PkgSaveFlagsToString(Flags: TPkgSaveFlags): string;
|
||||
function PkgOpenFlagsToString(Flags: TPkgOpenFlags): string;
|
||||
function PkgCompileFlagsToString(Flags: TPkgCompileFlags): string;
|
||||
|
||||
procedure GetDescriptionOfDependencyOwner(Dependency: TPkgDependency;
|
||||
var Description: string);
|
||||
out Description: string);
|
||||
procedure GetDirectoryOfDependencyOwner(Dependency: TPkgDependency;
|
||||
var Directory: string);
|
||||
out Directory: string);
|
||||
|
||||
|
||||
implementation
|
||||
@ -193,21 +178,8 @@ begin
|
||||
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;
|
||||
|
||||
procedure GetDescriptionOfDependencyOwner(Dependency: TPkgDependency;
|
||||
var Description: string);
|
||||
out Description: string);
|
||||
var
|
||||
DepOwner: TObject;
|
||||
begin
|
||||
@ -222,7 +194,7 @@ begin
|
||||
end else if DepOwner=PkgBoss then begin
|
||||
Description:=lisPkgMangLazarus;
|
||||
end else begin
|
||||
Description:=DepOwner.ClassName
|
||||
Description:=dbgsName(DepOwner)
|
||||
end;
|
||||
end else begin
|
||||
Description:=Format(lisPkgMangDependencyWithoutOwner, [Dependency.AsString]
|
||||
@ -231,7 +203,7 @@ begin
|
||||
end;
|
||||
|
||||
procedure GetDirectoryOfDependencyOwner(Dependency: TPkgDependency;
|
||||
var Directory: string);
|
||||
out Directory: string);
|
||||
var
|
||||
DepOwner: TObject;
|
||||
begin
|
||||
|
@ -64,9 +64,9 @@ type
|
||||
TGetAllRequiredPackagesEvent =
|
||||
procedure(FirstDependency: TPkgDependency; var List: TFPList) of object;
|
||||
TGetDependencyOwnerDescription =
|
||||
procedure(Dependency: TPkgDependency; var Description: string) of object;
|
||||
procedure(Dependency: TPkgDependency; out Description: string) of object;
|
||||
TGetDependencyOwnerDirectory =
|
||||
procedure(Dependency: TPkgDependency; var Directory: string) of object;
|
||||
procedure(Dependency: TPkgDependency; out Directory: string) of object;
|
||||
TGetWritablePkgOutputDirectory =
|
||||
procedure(APackage: TLazPackage; var AnOutDirectory: string) of object;
|
||||
|
||||
@ -814,12 +814,12 @@ const
|
||||
|
||||
var
|
||||
// All TPkgDependency are added to this AVL tree (sorted for names, not version!)
|
||||
PackageDependencies: TAVLTree; // tree of TPkgDependency
|
||||
PackageDependencies: TAVLTree = nil; // tree of TPkgDependency
|
||||
|
||||
OnGetAllRequiredPackages: TGetAllRequiredPackagesEvent;
|
||||
OnGetDependencyOwnerDescription: TGetDependencyOwnerDescription;
|
||||
OnGetDependencyOwnerDirectory: TGetDependencyOwnerDirectory;
|
||||
OnGetWritablePkgOutputDirectory: TGetWritablePkgOutputDirectory;
|
||||
OnGetAllRequiredPackages: TGetAllRequiredPackagesEvent = nil;
|
||||
OnGetDependencyOwnerDescription: TGetDependencyOwnerDescription = nil;
|
||||
OnGetDependencyOwnerDirectory: TGetDependencyOwnerDirectory = nil;
|
||||
OnGetWritablePkgOutputDirectory: TGetWritablePkgOutputDirectory = nil;
|
||||
|
||||
function CompareLazPackageID(Data1, Data2: Pointer): integer;
|
||||
function CompareNameWithPackageID(Key, Data: Pointer): integer;
|
||||
|
@ -45,9 +45,14 @@ uses
|
||||
{$IFDEF IDE_MEM_CHECK}
|
||||
MemCheck,
|
||||
{$ENDIF}
|
||||
Classes, SysUtils, FileUtil,
|
||||
AVL_Tree, Laz_XMLCfg,
|
||||
LCLProc, Forms, Controls, Dialogs, LazarusIDEStrConsts, IDEProcs, LazConf,
|
||||
// FPC + LCL
|
||||
Classes, SysUtils, FileUtil, LCLProc, Forms, Controls, Dialogs,
|
||||
// codetools
|
||||
AVL_Tree, Laz_XMLCfg, CodeCache, BasicCodeTools, CodeToolManager,
|
||||
// IDEIntf,
|
||||
SrcEditorIntf, IDEExternToolIntf, IDEDialogs, IDEMsgIntf, PackageIntf,
|
||||
// IDE
|
||||
LazarusIDEStrConsts, IDEProcs, LazConf, TransferMacros, DialogProcs,
|
||||
CompilerOptions, PackageLinks, PackageDefs, LazarusPackageIntf, ComponentReg,
|
||||
RegisterFCL, RegisterLCL, RegisterSynEdit, RegisterIDEIntf;
|
||||
|
||||
@ -70,12 +75,23 @@ const
|
||||
fpfSearchAllExisting = fpfSearchEverywhere+[fpfPkgLinkMustExist];
|
||||
|
||||
type
|
||||
TPkgUninstallFlag = (
|
||||
puifDoNotConfirm,
|
||||
puifDoNotBuildIDE
|
||||
);
|
||||
|
||||
TPkgUninstallFlags = set of TPkgUninstallFlag;
|
||||
|
||||
TPkgAddedEvent = procedure(APackage: TLazPackage) of object;
|
||||
TPkgDeleteEvent = procedure(APackage: TLazPackage) of object;
|
||||
TPkgWriteMakeFile = function(APackage: TLazPackage): TModalResult of object;
|
||||
TPkgUninstall = function(APackage: TLazPackage;
|
||||
Flags: TPkgUninstallFlags): TModalResult of object;
|
||||
TDependencyModifiedEvent = procedure(ADependency: TPkgDependency) of object;
|
||||
TEndUpdateEvent = procedure(Sender: TObject; GraphChanged: boolean) of object;
|
||||
TFindFPCUnitEvent = procedure(const UnitName, Directory: string;
|
||||
var Filename: string) of object;
|
||||
TPkgDeleteAmbiguousFiles = function(const Filename: string): TModalResult of object;
|
||||
|
||||
{ TLazPackageGraph }
|
||||
|
||||
@ -93,9 +109,12 @@ type
|
||||
FOnAddPackage: TPkgAddedEvent;
|
||||
FOnBeginUpdate: TNotifyEvent;
|
||||
FOnChangePackageName: TPkgChangeNameEvent;
|
||||
FOnDeleteAmbiguousFiles: TPkgDeleteAmbiguousFiles;
|
||||
FOnDeletePackage: TPkgDeleteEvent;
|
||||
FOnDependencyModified: TDependencyModifiedEvent;
|
||||
FOnEndUpdate: TEndUpdateEvent;
|
||||
FOnUninstallPackage: TPkgUninstall;
|
||||
FOnWriteMakeFile: TPkgWriteMakeFile;
|
||||
FRegistrationFile: TPkgFile;
|
||||
FRegistrationPackage: TLazPackage;
|
||||
FRegistrationUnitName: string;
|
||||
@ -115,6 +134,8 @@ type
|
||||
procedure UpdateBrokenDependenciesToPackage(APackage: TLazPackage);
|
||||
function OpenDependencyWithPackageLink(Dependency: TPkgDependency;
|
||||
PkgLink: TPackageLink): boolean;
|
||||
function DeleteAmbiguousFiles(const Filename: string): TModalResult;
|
||||
procedure AddMessage(const Msg, Directory: string);
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
@ -213,6 +234,26 @@ type
|
||||
procedure ChangePackageID(APackage: TLazPackage;
|
||||
const NewName: string; NewVersion: TPkgVersion;
|
||||
RenameDependencies: boolean);
|
||||
function SavePackageCompiledState(APackage: TLazPackage;
|
||||
const CompilerFilename, CompilerParams: string): TModalResult;
|
||||
function LoadPackageCompiledState(APackage: TLazPackage;
|
||||
IgnoreErrors: boolean): TModalResult;
|
||||
function CheckIfDependenciesNeedCompilation(FirstDependency: TPkgDependency;
|
||||
StateFileAge: longint): TModalResult;
|
||||
function CheckIfPackageNeedsCompilation(APackage: TLazPackage;
|
||||
const CompilerFilename, CompilerParams, SrcFilename: string
|
||||
): TModalResult;
|
||||
function PreparePackageOutputDirectory(APackage: TLazPackage;
|
||||
CleanUp: boolean): TModalResult;
|
||||
function CheckAmbiguousPackageUnits(APackage: TLazPackage): TModalResult;
|
||||
function SavePackageMainSource(APackage: TLazPackage;
|
||||
Flags: TPkgCompileFlags): TModalResult;
|
||||
function CompileRequiredPackages(APackage: TLazPackage;
|
||||
FirstDependency: TPkgDependency;
|
||||
Globals: TGlobalCompilerOptions;
|
||||
Policies: TPackageUpdatePolicies): TModalResult;
|
||||
function CompilePackage(APackage: TLazPackage; Flags: TPkgCompileFlags;
|
||||
Globals: TGlobalCompilerOptions = nil): TModalResult;
|
||||
public
|
||||
// registration
|
||||
procedure RegisterUnitHandler(const TheUnitName: string;
|
||||
@ -260,6 +301,12 @@ type
|
||||
property OnDeletePackage: TPkgDeleteEvent read FOnDeletePackage
|
||||
write FOnDeletePackage;
|
||||
property OnEndUpdate: TEndUpdateEvent read FOnEndUpdate write FOnEndUpdate;
|
||||
property OnDeleteAmbiguousFiles: TPkgDeleteAmbiguousFiles
|
||||
read FOnDeleteAmbiguousFiles write FOnDeleteAmbiguousFiles;
|
||||
property OnWriteMakeFile: TPkgWriteMakeFile read FOnWriteMakeFile
|
||||
write FOnWriteMakeFile;
|
||||
property OnUninstallPackage: TPkgUninstall read FOnUninstallPackage
|
||||
write FOnUninstallPackage;
|
||||
property Packages[Index: integer]: TLazPackage read GetPackages; default; // see Count for the number
|
||||
property RegistrationFile: TPkgFile read FRegistrationFile;
|
||||
property RegistrationPackage: TLazPackage read FRegistrationPackage
|
||||
@ -269,7 +316,7 @@ type
|
||||
end;
|
||||
|
||||
var
|
||||
PackageGraph: TLazPackageGraph;
|
||||
PackageGraph: TLazPackageGraph = nil;
|
||||
|
||||
implementation
|
||||
|
||||
@ -375,7 +422,7 @@ begin
|
||||
DebugLn('invalid Package file "'+AFilename+'".');
|
||||
exit;
|
||||
end;
|
||||
if CompareText(PkgLink.Name,NewPackage.Name)<>0 then exit;
|
||||
if SysUtils.CompareText(PkgLink.Name,NewPackage.Name)<>0 then exit;
|
||||
// ok
|
||||
Result:=true;
|
||||
AddPackage(NewPackage);
|
||||
@ -386,6 +433,23 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.DeleteAmbiguousFiles(const Filename: string
|
||||
): TModalResult;
|
||||
begin
|
||||
if Assigned(OnDeleteAmbiguousFiles) then
|
||||
Result:=OnDeleteAmbiguousFiles(Filename)
|
||||
else
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
procedure TLazPackageGraph.AddMessage(const Msg, Directory: string);
|
||||
begin
|
||||
if Assigned(IDEMessagesWindow) then
|
||||
IDEMessagesWindow.AddMsg(Msg, Directory,-1)
|
||||
else
|
||||
DebugLn(['TLazPackageGraph.AddMessage Msg="',Msg,'" Directory="',Directory,'"']);
|
||||
end;
|
||||
|
||||
constructor TLazPackageGraph.Create;
|
||||
begin
|
||||
OnGetAllRequiredPackages:=@GetAllRequiredPackages;
|
||||
@ -1909,6 +1973,756 @@ begin
|
||||
EndUpdate;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.SavePackageCompiledState(APackage: TLazPackage;
|
||||
const CompilerFilename, CompilerParams: string): TModalResult;
|
||||
var
|
||||
XMLConfig: TXMLConfig;
|
||||
StateFile: String;
|
||||
CompilerFileDate: Integer;
|
||||
begin
|
||||
Result:=mrCancel;
|
||||
StateFile:=APackage.GetStateFilename;
|
||||
try
|
||||
CompilerFileDate:=FileAge(CompilerFilename);
|
||||
XMLConfig:=TXMLConfig.CreateClean(StateFile);
|
||||
try
|
||||
XMLConfig.SetValue('Compiler/Value',CompilerFilename);
|
||||
XMLConfig.SetValue('Compiler/Date',CompilerFileDate);
|
||||
XMLConfig.SetValue('Params/Value',CompilerParams);
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
finally
|
||||
XMLConfig.Free;
|
||||
end;
|
||||
APackage.LastCompilerFilename:=CompilerFilename;
|
||||
APackage.LastCompilerFileDate:=CompilerFileDate;
|
||||
APackage.LastCompilerParams:=CompilerParams;
|
||||
APackage.StateFileDate:=FileAge(StateFile);
|
||||
APackage.Flags:=APackage.Flags+[lpfStateFileLoaded];
|
||||
except
|
||||
on E: Exception do begin
|
||||
Result:=IDEMessageDialog(lisPkgMangErrorWritingFile,
|
||||
Format(lisPkgMangUnableToWriteStateFileOfPackageError, ['"', StateFile,
|
||||
'"', #13, APackage.IDAsString, #13, E.Message]),
|
||||
mtError,[mbAbort,mbCancel]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.LoadPackageCompiledState(APackage: TLazPackage;
|
||||
IgnoreErrors: boolean): TModalResult;
|
||||
var
|
||||
XMLConfig: TXMLConfig;
|
||||
StateFile: String;
|
||||
StateFileAge: Integer;
|
||||
begin
|
||||
StateFile:=APackage.GetStateFilename;
|
||||
if not FileExists(StateFile) then begin
|
||||
DebugLn('TLazPackageGraph.LoadPackageCompiledState Statefile not found: ',StateFile);
|
||||
APackage.Flags:=APackage.Flags-[lpfStateFileLoaded];
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
|
||||
// read the state file
|
||||
StateFileAge:=FileAge(StateFile);
|
||||
if (not (lpfStateFileLoaded in APackage.Flags))
|
||||
or (APackage.StateFileDate<>StateFileAge) then begin
|
||||
APackage.Flags:=APackage.Flags-[lpfStateFileLoaded];
|
||||
try
|
||||
XMLConfig:=TXMLConfig.Create(StateFile);
|
||||
try
|
||||
APackage.LastCompilerFilename:=XMLConfig.GetValue('Compiler/Value','');
|
||||
APackage.LastCompilerFileDate:=XMLConfig.GetValue('Compiler/Date',0);
|
||||
APackage.LastCompilerParams:=XMLConfig.GetValue('Params/Value','');
|
||||
finally
|
||||
XMLConfig.Free;
|
||||
end;
|
||||
APackage.StateFileDate:=StateFileAge;
|
||||
except
|
||||
on E: Exception do begin
|
||||
if IgnoreErrors then begin
|
||||
Result:=mrOk;
|
||||
end else begin
|
||||
Result:=IDEMessageDialog(lisPkgMangErrorReadingFile,
|
||||
Format(lisPkgMangUnableToReadStateFileOfPackageError, ['"',
|
||||
StateFile, '"', #13, APackage.IDAsString, #13, E.Message]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
APackage.Flags:=APackage.Flags+[lpfStateFileLoaded];
|
||||
end;
|
||||
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.CheckIfDependenciesNeedCompilation(
|
||||
FirstDependency: TPkgDependency; StateFileAge: longint): TModalResult;
|
||||
|
||||
function GetOwnerID: string;
|
||||
begin
|
||||
OnGetDependencyOwnerDescription(FirstDependency,Result);
|
||||
end;
|
||||
|
||||
var
|
||||
Dependency: TPkgDependency;
|
||||
RequiredPackage: TLazPackage;
|
||||
OtherStateFile: String;
|
||||
begin
|
||||
Dependency:=FirstDependency;
|
||||
if Dependency=nil then begin
|
||||
Result:=mrNo;
|
||||
exit;
|
||||
end;
|
||||
|
||||
while Dependency<>nil do begin
|
||||
if (Dependency.LoadPackageResult=lprSuccess) then begin
|
||||
RequiredPackage:=Dependency.RequiredPackage;
|
||||
// check compile state file of required package
|
||||
if not RequiredPackage.AutoCreated then begin
|
||||
Result:=LoadPackageCompiledState(RequiredPackage,false);
|
||||
if Result<>mrOk then exit;
|
||||
Result:=mrYes;
|
||||
if not (lpfStateFileLoaded in RequiredPackage.Flags) then begin
|
||||
DebugLn('TPkgManager.CheckIfDependenciesNeedCompilation No state file for ',RequiredPackage.IDAsString);
|
||||
exit;
|
||||
end;
|
||||
if StateFileAge<RequiredPackage.StateFileDate then begin
|
||||
DebugLn('TPkgManager.CheckIfDependenciesNeedCompilation Required ',
|
||||
RequiredPackage.IDAsString,' State file is newer than ',
|
||||
'State file ',GetOwnerID);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
// check output state file of required package
|
||||
if RequiredPackage.OutputStateFile<>'' then begin
|
||||
OtherStateFile:=RequiredPackage.OutputStateFile;
|
||||
GlobalMacroList.SubstituteStr(OtherStateFile);
|
||||
if FileExists(OtherStateFile)
|
||||
and (FileAge(OtherStateFile)>StateFileAge) then begin
|
||||
DebugLn('TPkgManager.CheckIfDependenciesNeedCompilation Required ',
|
||||
RequiredPackage.IDAsString,' OtherState file "',OtherStateFile,'"'
|
||||
,' is newer than State file ',GetOwnerID);
|
||||
Result:=mrYes;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Dependency:=Dependency.NextRequiresDependency;
|
||||
end;
|
||||
Result:=mrNo;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.CheckIfPackageNeedsCompilation(APackage: TLazPackage;
|
||||
const CompilerFilename, CompilerParams, SrcFilename: string): TModalResult;
|
||||
var
|
||||
StateFilename: String;
|
||||
StateFileAge: Integer;
|
||||
i: Integer;
|
||||
CurFile: TPkgFile;
|
||||
begin
|
||||
Result:=mrYes;
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TLazPackageGraph.CheckIfPackageNeedsCompilation A ',APackage.IDAsString);
|
||||
{$ENDIF}
|
||||
|
||||
// check state file
|
||||
StateFilename:=APackage.GetStateFilename;
|
||||
Result:=LoadPackageCompiledState(APackage,false);
|
||||
if Result<>mrOk then exit;
|
||||
if not (lpfStateFileLoaded in APackage.Flags) then begin
|
||||
DebugLn('TLazPackageGraph.CheckIfPackageNeedsCompilation No state file for ',APackage.IDAsString);
|
||||
Result:=mrYes;
|
||||
exit;
|
||||
end;
|
||||
|
||||
StateFileAge:=FileAge(StateFilename);
|
||||
|
||||
// check main source file
|
||||
if FileExists(SrcFilename) and (StateFileAge<FileAge(SrcFilename)) then
|
||||
begin
|
||||
DebugLn('TLazPackageGraph.CheckIfPackageNeedsCompilation SrcFile outdated ',APackage.IDAsString);
|
||||
Result:=mrYes;
|
||||
exit;
|
||||
end;
|
||||
|
||||
// check all required packages
|
||||
Result:=CheckIfDependenciesNeedCompilation(APackage.FirstRequiredDependency,
|
||||
StateFileAge);
|
||||
if Result<>mrNo then exit;
|
||||
|
||||
Result:=mrYes;
|
||||
|
||||
// check compiler and params
|
||||
if CompilerFilename<>APackage.LastCompilerFilename then begin
|
||||
DebugLn('TLazPackageGraph.CheckIfPackageNeedsCompilation Compiler filename changed for ',APackage.IDAsString);
|
||||
DebugLn(' Old="',APackage.LastCompilerFilename,'"');
|
||||
DebugLn(' Now="',CompilerFilename,'"');
|
||||
exit;
|
||||
end;
|
||||
if not FileExists(CompilerFilename) then begin
|
||||
DebugLn('TLazPackageGraph.CheckIfPackageNeedsCompilation Compiler filename not found for ',APackage.IDAsString);
|
||||
DebugLn(' File="',CompilerFilename,'"');
|
||||
exit;
|
||||
end;
|
||||
if FileAge(CompilerFilename)<>APackage.LastCompilerFileDate then begin
|
||||
DebugLn('TLazPackageGraph.CheckIfPackageNeedsCompilation Compiler file changed for ',APackage.IDAsString);
|
||||
DebugLn(' File="',CompilerFilename,'"');
|
||||
exit;
|
||||
end;
|
||||
if CompilerParams<>APackage.LastCompilerParams then begin
|
||||
DebugLn('TLazPackageGraph.CheckIfPackageNeedsCompilation Compiler params changed for ',APackage.IDAsString);
|
||||
DebugLn(' Old="',APackage.LastCompilerParams,'"');
|
||||
DebugLn(' Now="',CompilerParams,'"');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// check package files
|
||||
if StateFileAge<FileAge(APackage.Filename) then begin
|
||||
DebugLn('TLazPackageGraph.CheckIfPackageNeedsCompilation StateFile older than lpk ',APackage.IDAsString);
|
||||
exit;
|
||||
end;
|
||||
for i:=0 to APackage.FileCount-1 do begin
|
||||
CurFile:=APackage.Files[i];
|
||||
//debugln('TLazPackageGraph.CheckIfPackageNeedsCompilation CurFile.Filename="',CurFile.Filename,'" ',FileExists(CurFile.Filename),' ',StateFileAge<FileAge(CurFile.Filename));
|
||||
if FileExists(CurFile.Filename)
|
||||
and (StateFileAge<FileAge(CurFile.Filename)) then begin
|
||||
DebugLn('TLazPackageGraph.CheckIfPackageNeedsCompilation Src has changed ',APackage.IDAsString,' ',CurFile.Filename);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TLazPackageGraph.CheckIfPackageNeedsCompilation END ',APackage.IDAsString);
|
||||
{$ENDIF}
|
||||
Result:=mrNo;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.CompileRequiredPackages(APackage: TLazPackage;
|
||||
FirstDependency: TPkgDependency; Globals: TGlobalCompilerOptions;
|
||||
Policies: TPackageUpdatePolicies): TModalResult;
|
||||
var
|
||||
AutoPackages: TFPList;
|
||||
i: Integer;
|
||||
begin
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TLazPackageGraph.CompileRequiredPackages A ');
|
||||
{$ENDIF}
|
||||
AutoPackages:=PackageGraph.GetAutoCompilationOrder(APackage,FirstDependency,
|
||||
Policies);
|
||||
if AutoPackages<>nil then begin
|
||||
//DebugLn('TLazPackageGraph.CompileRequiredPackages B Count=',IntToStr(AutoPackages.Count));
|
||||
try
|
||||
i:=0;
|
||||
while i<AutoPackages.Count do begin
|
||||
Result:=CompilePackage(TLazPackage(AutoPackages[i]),
|
||||
[pcfDoNotCompileDependencies,pcfOnlyIfNeeded,
|
||||
pcfDoNotSaveEditorFiles],Globals);
|
||||
if Result<>mrOk then exit;
|
||||
inc(i);
|
||||
end;
|
||||
finally
|
||||
AutoPackages.Free;
|
||||
end;
|
||||
end;
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TLazPackageGraph.CompileRequiredPackages END ');
|
||||
{$ENDIF}
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.CompilePackage(APackage: TLazPackage;
|
||||
Flags: TPkgCompileFlags; Globals: TGlobalCompilerOptions): TModalResult;
|
||||
var
|
||||
PkgCompileTool: TIDEExternalToolOptions;
|
||||
CompilerFilename: String;
|
||||
CompilerParams: String;
|
||||
EffektiveCompilerParams: String;
|
||||
SrcFilename: String;
|
||||
CompilePolicies: TPackageUpdatePolicies;
|
||||
begin
|
||||
Result:=mrCancel;
|
||||
|
||||
DebugLn('TLazPackageGraph.CompilePackage A ',APackage.IDAsString,' Flags=',PkgCompileFlagsToString(Flags));
|
||||
|
||||
if APackage.AutoCreated then begin
|
||||
DebugLn(['TLazPackageGraph.CompilePackage failed because autocreated: ',APackage.IDAsString]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
BeginUpdate(false);
|
||||
try
|
||||
// automatically compile required packages
|
||||
if not (pcfDoNotCompileDependencies in Flags) then begin
|
||||
CompilePolicies:=[pupAsNeeded];
|
||||
if pcfCompileDependenciesClean in Flags then
|
||||
Include(CompilePolicies,pupOnRebuildingAll);
|
||||
Result:=CompileRequiredPackages(APackage,nil,Globals,
|
||||
CompilePolicies);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn(['TLazPackageGraph.CompilePackage CompileRequiredPackages failed: ',APackage.IDAsString]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
SrcFilename:=APackage.GetSrcFilename;
|
||||
CompilerFilename:=APackage.GetCompilerFilename;
|
||||
CompilerParams:=APackage.CompilerOptions.MakeOptionsString(Globals,
|
||||
APackage.CompilerOptions.DefaultMakeOptionsFlags)
|
||||
+' '+CreateRelativePath(SrcFilename,APackage.Directory);
|
||||
//DebugLn(['TLazPackageGraph.CompilePackage SrcFilename="',SrcFilename,'" CompilerFilename="',CompilerFilename,'" CompilerParams="',CompilerParams,'"']);
|
||||
|
||||
// check if compilation is neccessary
|
||||
if (pcfOnlyIfNeeded in Flags) then begin
|
||||
Result:=CheckIfPackageNeedsCompilation(APackage,
|
||||
CompilerFilename,CompilerParams,
|
||||
SrcFilename);
|
||||
if Result=mrNo then begin
|
||||
DebugLn(['TLazPackageGraph.CompilePackage ',APackage.IDAsString,' does not need compilation.']);
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
if Result<>mrYes then begin
|
||||
DebugLn(['TLazPackageGraph.CompilePackage CheckIfPackageNeedsCompilation failed: ',APackage.IDAsString]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// auto increase version
|
||||
// ToDo
|
||||
|
||||
if IDEMessagesWindow<>nil then
|
||||
IDEMessagesWindow.BeginBlock;
|
||||
try
|
||||
Result:=PreparePackageOutputDirectory(APackage,pcfCleanCompile in Flags);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TLazPackageGraph.CompilePackage PreparePackageOutputDirectory failed: ',APackage.IDAsString);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// create package main source file
|
||||
Result:=SavePackageMainSource(APackage,Flags);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TLazPackageGraph.CompilePackage SavePackageMainSource failed: ',APackage.IDAsString);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// check ambiguous units
|
||||
Result:=CheckAmbiguousPackageUnits(APackage);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TLazPackageGraph.CompilePackage CheckAmbiguousPackageUnits failed: ',APackage.IDAsString);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// create Makefile
|
||||
if ((pcfCreateMakefile in Flags)
|
||||
or (APackage.CompilerOptions.CreateMakefileOnBuild))
|
||||
and Assigned(OnWriteMakeFile) then begin
|
||||
Result:=OnWriteMakeFile(APackage);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TLazPackageGraph.CompilePackage DoWriteMakefile failed: ',APackage.IDAsString);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// run compilation tool 'Before'
|
||||
if not (pcfDoNotCompilePackage in Flags) then begin
|
||||
Result:=APackage.CompilerOptions.ExecuteBefore.Execute(
|
||||
APackage.Directory,'Executing command before');
|
||||
if Result<>mrOk then begin
|
||||
DebugLn(['TLazPackageGraph.CompilePackage ExecuteBefore failed: ',APackage.IDAsString]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// create external tool to run the compiler
|
||||
DebugLn('TPkgManager.DoCompilePackage Compiler="',CompilerFilename,'"');
|
||||
DebugLn('TPkgManager.DoCompilePackage Params="',CompilerParams,'"');
|
||||
DebugLn('TPkgManager.DoCompilePackage WorkingDir="',APackage.Directory,'"');
|
||||
|
||||
if (not APackage.CompilerOptions.SkipCompiler)
|
||||
and (not (pcfDoNotCompilePackage in Flags)) then begin
|
||||
// check compiler filename
|
||||
try
|
||||
CheckIfFileIsExecutable(CompilerFilename);
|
||||
except
|
||||
on e: Exception do begin
|
||||
DebugLn(['TLazPackageGraph.CompilePackage ',APackage.IDAsString,' ',e.Message]);
|
||||
Result:=IDEMessageDialog(lisPkgManginvalidCompilerFilename,
|
||||
Format(lisPkgMangTheCompilerFileForPackageIsNotAValidExecutable, [
|
||||
APackage.IDAsString, #13, E.Message]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// change compiler parameters for compiling clean
|
||||
EffektiveCompilerParams:=CompilerParams;
|
||||
if pcfCleanCompile in Flags then begin
|
||||
if EffektiveCompilerParams<>'' then
|
||||
EffektiveCompilerParams:='-B '+EffektiveCompilerParams
|
||||
else
|
||||
EffektiveCompilerParams:='-B';
|
||||
end;
|
||||
|
||||
PkgCompileTool:=TIDEExternalToolOptions.Create;
|
||||
try
|
||||
PkgCompileTool.Title:='Compiling package '+APackage.IDAsString;
|
||||
PkgCompileTool.ScanOutputForFPCMessages:=true;
|
||||
PkgCompileTool.ScanOutputForMakeMessages:=true;
|
||||
PkgCompileTool.WorkingDirectory:=APackage.Directory;
|
||||
PkgCompileTool.Filename:=CompilerFilename;
|
||||
PkgCompileTool.CmdLineParams:=EffektiveCompilerParams;
|
||||
|
||||
// clear old errors
|
||||
if SourceEditorWindow<>nil then
|
||||
SourceEditorWindow.ClearErrorLines;
|
||||
|
||||
// compile package
|
||||
Result:=RunCompilerWithOptions(PkgCompileTool,APackage.CompilerOptions);
|
||||
if Result<>mrOk then exit;
|
||||
// compilation succeded -> write state file
|
||||
Result:=SavePackageCompiledState(APackage,
|
||||
CompilerFilename,CompilerParams);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn(['TLazPackageGraph.CompilePackage SavePackageCompiledState failed: ',APackage.IDAsString]);
|
||||
exit;
|
||||
end;
|
||||
finally
|
||||
// clean up
|
||||
PkgCompileTool.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
// run compilation tool 'After'
|
||||
if not (pcfDoNotCompilePackage in Flags) then begin
|
||||
Result:=APackage.CompilerOptions.ExecuteAfter.Execute(
|
||||
APackage.Directory,'Executing command after');
|
||||
if Result<>mrOk then begin
|
||||
DebugLn(['TLazPackageGraph.CompilePackage ExecuteAfter failed: ',APackage.IDAsString]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
if IDEMessagesWindow<>nil then
|
||||
IDEMessagesWindow.BeginBlock;
|
||||
if Result<>mrOk then begin
|
||||
if (APackage.AutoInstall<>pitNope) and (APackage.Installed=pitNope)
|
||||
and (OnUninstallPackage<>nil) then begin
|
||||
// package was tried to install, but failed
|
||||
// -> ask user if the package should be removed from the installation
|
||||
// list
|
||||
if IDEMessageDialog(lisInstallationFailed,
|
||||
Format(lisPkgMangThePackageFailedToCompileRemoveItFromTheInstallati,
|
||||
['"', APackage.IDAsString, '"', #13]), mtConfirmation,
|
||||
[mbYes,mbIgnore])=mrYes then
|
||||
begin
|
||||
OnUninstallPackage(APackage,[puifDoNotConfirm,puifDoNotBuildIDE]);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
PackageGraph.EndUpdate;
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.PreparePackageOutputDirectory(APackage: TLazPackage;
|
||||
CleanUp: boolean): TModalResult;
|
||||
var
|
||||
OutputDir: String;
|
||||
StateFile: String;
|
||||
PkgSrcDir: String;
|
||||
i: Integer;
|
||||
CurFile: TPkgFile;
|
||||
OutputFileName: String;
|
||||
begin
|
||||
OutputDir:=APackage.GetOutputDirectory;
|
||||
StateFile:=APackage.GetStateFilename;
|
||||
PkgSrcDir:=ExtractFilePath(APackage.GetSrcFilename);
|
||||
|
||||
// create the output directory
|
||||
if not ForceDirectory(OutputDir) then begin
|
||||
Result:=IDEMessageDialog(lisPkgMangUnableToCreateDirectory,
|
||||
Format(lisPkgMangUnableToCreateOutputDirectoryForPackage, ['"',
|
||||
OutputDir, '"', #13, APackage.IDAsString]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// delete old Compile State file
|
||||
if FileExists(StateFile) and not DeleteFile(StateFile) then begin
|
||||
Result:=IDEMessageDialog(lisPkgMangUnableToDeleteFilename,
|
||||
Format(lisPkgMangUnableToDeleteOldStateFileForPackage, ['"', StateFile,
|
||||
'"', #13, APackage.IDAsString]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
APackage.Flags:=APackage.Flags-[lpfStateFileLoaded];
|
||||
|
||||
// create the package src directory
|
||||
if not ForceDirectory(PkgSrcDir) then begin
|
||||
Result:=IDEMessageDialog(lisPkgMangUnableToCreateDirectory,
|
||||
Format(lisPkgMangUnableToCreatePackageSourceDirectoryForPackage, ['"',
|
||||
PkgSrcDir, '"', #13, APackage.IDAsString]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// clean up if wanted
|
||||
if CleanUp then begin
|
||||
for i:=0 to APackage.FileCount-1 do begin
|
||||
CurFile:=APackage.Files[i];
|
||||
if not (CurFile.FileType in PkgFileUnitTypes) then continue;
|
||||
OutputFileName:=AppendPathDelim(OutputDir)+CurFile.UnitName+'.ppu';
|
||||
Result:=DeleteFileInteractive(OutputFileName,[mbIgnore,mbAbort]);
|
||||
if Result in [mrCancel,mrAbort] then exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.CheckAmbiguousPackageUnits(APackage: TLazPackage
|
||||
): TModalResult;
|
||||
var
|
||||
i: Integer;
|
||||
CurFile: TPkgFile;
|
||||
CurUnitName: String;
|
||||
SrcDirs: String;
|
||||
PkgDir: String;
|
||||
PkgOutputDir: String;
|
||||
YesToAll: Boolean;
|
||||
|
||||
function CheckFile(const ShortFilename: string): TModalResult;
|
||||
var
|
||||
AmbiguousFilename: String;
|
||||
SearchFlags: TSearchFileInPathFlags;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
SearchFlags:=[];
|
||||
if CompareFilenames(PkgDir,PkgOutputDir)=0 then
|
||||
Include(SearchFlags,sffDontSearchInBasePath);
|
||||
repeat
|
||||
AmbiguousFilename:=SearchFileInPath(ShortFilename,PkgDir,SrcDirs,';',
|
||||
SearchFlags);
|
||||
if (AmbiguousFilename='') then exit;
|
||||
if not YesToAll then
|
||||
Result:=IDEMessageDialog(lisAmbiguousUnitFound,
|
||||
Format(lisTheFileWasFoundInOneOfTheSourceDirectoriesOfThePac, ['"',
|
||||
AmbiguousFilename, '"', #13, APackage.IDAsString, #13, #13]),
|
||||
mtWarning,[mbYes,mbYesToAll,mbNo,mbAbort])
|
||||
else
|
||||
Result:=mrYesToAll;
|
||||
if Result=mrNo then
|
||||
Result:=mrOk;
|
||||
if Result in [mrYes,mrYesToAll] then begin
|
||||
YesToAll:=Result=mrYesToAll;
|
||||
if (not DeleteFile(AmbiguousFilename))
|
||||
and (IDEMessageDialog(lisPkgMangDeleteFailed, Format(lisDeletingOfFileFailed,
|
||||
['"', AmbiguousFilename, '"']), mtError, [mbIgnore, mbCancel])
|
||||
<>mrIgnore) then
|
||||
begin
|
||||
Result:=mrCancel;
|
||||
exit;
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end else
|
||||
break;
|
||||
until false;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result:=mrOk;
|
||||
YesToAll:=False;
|
||||
// search in every source directory for compiled versions of the units
|
||||
// A source directory is a directory with a used unit and it is not the output
|
||||
// directory
|
||||
SrcDirs:=APackage.GetSourceDirs(true,true);
|
||||
PkgOutputDir:=AppendPathDelim(APackage.GetOutputDirectory);
|
||||
SrcDirs:=RemoveSearchPaths(SrcDirs,PkgOutputDir);
|
||||
if SrcDirs='' then exit;
|
||||
PkgDir:=AppendPathDelim(APackage.Directory);
|
||||
for i:=0 to APackage.FileCount-1 do begin
|
||||
CurFile:=APackage.Files[i];
|
||||
if CurFile.FileType<>pftUnit then continue;
|
||||
CurUnitName:=lowercase(CurFile.UnitName);
|
||||
if CurUnitName='' then continue;
|
||||
Result:=CheckFile(CurUnitName+'.ppu');
|
||||
if Result<>mrOk then exit;
|
||||
Result:=CheckFile(CurUnitName+'.ppw');
|
||||
if Result<>mrOk then exit;
|
||||
Result:=CheckFile(CurUnitName+'.ppl');
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.SavePackageMainSource(APackage: TLazPackage;
|
||||
Flags: TPkgCompileFlags): TModalResult;
|
||||
var
|
||||
SrcFilename: String;
|
||||
UsedUnits: String;
|
||||
Src: String;
|
||||
i: Integer;
|
||||
e: String;
|
||||
CurFile: TPkgFile;
|
||||
CodeBuffer: TCodeBuffer;
|
||||
CurUnitName: String;
|
||||
RegistrationCode: String;
|
||||
HeaderSrc: String;
|
||||
OutputDir: String;
|
||||
OldShortenSrc: String;
|
||||
NeedsRegisterProcCall: boolean;
|
||||
CurSrcUnitName: String;
|
||||
NewShortenSrc: String;
|
||||
begin
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TLazPackageGraph.SavePackageMainSource A');
|
||||
{$ENDIF}
|
||||
// check if package is ready for saving
|
||||
OutputDir:=APackage.GetOutputDirectory;
|
||||
if not DirPathExists(OutputDir) then begin
|
||||
Result:=IDEMessageDialog(lisEnvOptDlgDirectoryNotFound,
|
||||
Format(lisPkgMangPackageHasNoValidOutputDirectory, ['"',
|
||||
APackage.IDAsString, '"', #13, '"', OutputDir, '"']),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
SrcFilename:=APackage.GetSrcFilename;
|
||||
|
||||
// delete ambiguous files
|
||||
Result:=DeleteAmbiguousFiles(SrcFilename);
|
||||
if Result=mrAbort then begin
|
||||
DebugLn('TLazPackageGraph.SavePackageMainSource DoDeleteAmbiguousFiles failed');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// collect unitnames
|
||||
e:=LineEnding;
|
||||
UsedUnits:='';
|
||||
RegistrationCode:='';
|
||||
for i:=0 to APackage.FileCount-1 do begin
|
||||
CurFile:=APackage.Files[i];
|
||||
// update unitname
|
||||
if FilenameIsPascalUnit(CurFile.Filename)
|
||||
and (CurFile.FileType in PkgFileUnitTypes) then begin
|
||||
CurUnitName:=ExtractFileNameOnly(CurFile.Filename);
|
||||
|
||||
if CurUnitName=lowercase(CurUnitName) then begin
|
||||
// the filename is all lowercase, so we can use the nicer unitname from
|
||||
// the source.
|
||||
|
||||
CodeBuffer:=CodeToolBoss.LoadFile(CurFile.Filename,false,false);
|
||||
if CodeBuffer<>nil then begin
|
||||
// if the unit is edited, the unitname is probably already cached
|
||||
CurSrcUnitName:=CodeToolBoss.GetCachedSourceName(CodeBuffer);
|
||||
// if not then parse it
|
||||
if SysUtils.CompareText(CurSrcUnitName,CurUnitName)<>0 then
|
||||
CurSrcUnitName:=CodeToolBoss.GetSourceName(CodeBuffer,false);
|
||||
// if it makes sense, update unitname
|
||||
if SysUtils.CompareText(CurSrcUnitName,CurFile.UnitName)=0 then
|
||||
CurFile.UnitName:=CurSrcUnitName;
|
||||
end;
|
||||
if SysUtils.CompareText(CurUnitName,CurFile.UnitName)=0 then
|
||||
CurUnitName:=CurFile.UnitName
|
||||
else
|
||||
CurFile.UnitName:=CurUnitName;
|
||||
end;
|
||||
|
||||
if (CurUnitName<>'') and IsValidIdent(CurUnitName) then begin
|
||||
NeedsRegisterProcCall:=CurFile.HasRegisterProc
|
||||
and (APackage.PackageType in [lptDesignTime,lptRunAndDesignTime]);
|
||||
if NeedsRegisterProcCall or CurFile.AddToUsesPkgSection then begin
|
||||
if UsedUnits<>'' then
|
||||
UsedUnits:=UsedUnits+', ';
|
||||
UsedUnits:=UsedUnits+CurUnitName;
|
||||
end;
|
||||
if NeedsRegisterProcCall then begin
|
||||
RegistrationCode:=RegistrationCode+
|
||||
' RegisterUnit('''+CurUnitName+''',@'+CurUnitName+'.Register);'+e;
|
||||
end;
|
||||
end else begin
|
||||
AddMessage('WARNING: unit name invalid '+CurFile.Filename
|
||||
+', package='+APackage.IDAsString,
|
||||
APackage.Directory);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
// append registration code only for design time packages
|
||||
if (APackage.PackageType in [lptDesignTime,lptRunAndDesignTime]) then begin
|
||||
RegistrationCode:=
|
||||
'procedure Register;'+e
|
||||
+'begin'+e
|
||||
+RegistrationCode
|
||||
+'end;'+e
|
||||
+e
|
||||
+'initialization'+e
|
||||
+' RegisterPackage('''+APackage.Name+''',@Register);'
|
||||
+e;
|
||||
if UsedUnits<>'' then UsedUnits:=UsedUnits+', ';
|
||||
UsedUnits:=UsedUnits+'LazarusPackageIntf';
|
||||
end;
|
||||
|
||||
// create source
|
||||
HeaderSrc:=lisPkgMangThisSourceIsOnlyUsedToCompileAndInstallThePackage;
|
||||
HeaderSrc:= '{ '
|
||||
+lisPkgMangThisFileWasAutomaticallyCreatedByLazarusDoNotEdit+e
|
||||
+lisPkgMangThisSourceIsOnlyUsedToCompileAndInstallThePackage+e
|
||||
+' }'+e+e;
|
||||
Src:='unit '+APackage.Name+';'+e
|
||||
+e
|
||||
+'interface'+e
|
||||
+e;
|
||||
if UsedUnits<>'' then
|
||||
Src:=Src
|
||||
+'uses'+e
|
||||
+' '+UsedUnits+';'+e
|
||||
+e;
|
||||
Src:=Src
|
||||
+'implementation'+e
|
||||
+e
|
||||
+RegistrationCode
|
||||
+'end.'+e;
|
||||
Src:=CodeToolBoss.SourceChangeCache.BeautifyCodeOptions.
|
||||
BeautifyStatement(Src,0);
|
||||
Src:=HeaderSrc+Src;
|
||||
|
||||
// check if old code is already uptodate
|
||||
Result:=LoadCodeBuffer(CodeBuffer,SrcFilename,[lbfQuiet,lbfCheckIfText,
|
||||
lbfUpdateFromDisk,lbfCreateClearOnError]);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TLazPackageGraph.SavePackageMainSource LoadCodeBuffer ',SrcFilename,' failed');
|
||||
exit;
|
||||
end;
|
||||
OldShortenSrc:=CodeToolBoss.ExtractCodeWithoutComments(CodeBuffer);
|
||||
NewShortenSrc:=CleanCodeFromComments(Src,
|
||||
CodeToolBoss.GetNestedCommentsFlagForFile(CodeBuffer.Filename));
|
||||
if CompareTextIgnoringSpace(OldShortenSrc,NewShortenSrc,true)=0 then begin
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
if OldShortenSrc<>NewShortenSrc then begin
|
||||
DebugLn('TLazPackageGraph.SavePackageMainSource Src changed ',dbgs(length(OldShortenSrc)),' ',dbgs(length(NewShortenSrc)));
|
||||
end;
|
||||
|
||||
// save source
|
||||
Result:=SaveStringToFile(SrcFilename,Src,[],lisPkgMangpackageMainSourceFile);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TLazPackageGraph.SavePackageMainSource SaveStringToFile ',SrcFilename,' failed');
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.GetBrokenDependenciesWhenChangingPkgID(
|
||||
APackage: TLazPackage; const NewName: string; NewVersion: TPkgVersion
|
||||
): TFPList;
|
||||
@ -2250,7 +3064,8 @@ begin
|
||||
// try defaultfilename
|
||||
AFilename:=Dependency.DefaultFilename;
|
||||
if (CompareFileExt(AFilename,'lpk')=0)
|
||||
and (CompareText(ExtractFileNameOnly(AFilename),Dependency.PackageName)=0)
|
||||
and (SysUtils.CompareText(
|
||||
ExtractFileNameOnly(AFilename),Dependency.PackageName)=0)
|
||||
then begin
|
||||
if not FilenameIsAbsolute(AFilename) then begin
|
||||
CurDir:=GetDependencyOwnerDirectory(Dependency);
|
||||
|
@ -51,7 +51,7 @@ uses
|
||||
AVL_Tree, Laz_XMLCfg,
|
||||
// IDE Interface
|
||||
IDEExternToolIntf, NewItemIntf, ProjectIntf, PackageIntf, MenuIntf,
|
||||
MacroIntf, LazIDEIntf,
|
||||
IDEMsgIntf, MacroIntf, LazIDEIntf,
|
||||
// IDE
|
||||
LazConf, LazarusIDEStrConsts, IDEProcs, ObjectLists, DialogProcs, IDECommands,
|
||||
EnvironmentOpts, MiscOptions, InputHistory, ProjectDefs, Project,
|
||||
@ -62,17 +62,10 @@ uses
|
||||
ProjectInspector, ComponentPalette, UnitEditor, AddFileToAPackageDlg,
|
||||
LazarusPackageIntf, PublishProjectDlg, InstallPkgSetDlg,
|
||||
// bosses
|
||||
BasePkgManager,
|
||||
BaseBuildManager, BasePkgManager,
|
||||
MainBar, MainIntf, MainBase;
|
||||
|
||||
type
|
||||
TPkgUninstallFlag = (
|
||||
puifDoNotConfirm,
|
||||
puifDoNotBuildIDE
|
||||
);
|
||||
|
||||
TPkgUninstallFlags = set of TPkgUninstallFlag;
|
||||
|
||||
{ TPkgManager }
|
||||
|
||||
TPkgManager = class(TBasePkgManager)
|
||||
@ -152,9 +145,9 @@ type
|
||||
|
||||
// misc
|
||||
procedure GetDependencyOwnerDescription(Dependency: TPkgDependency;
|
||||
var Description: string);
|
||||
out Description: string);
|
||||
procedure GetDependencyOwnerDirectory(Dependency: TPkgDependency;
|
||||
var Directory: string);
|
||||
out Directory: string);
|
||||
procedure GetWritablePkgOutputDirectory(APackage: TLazPackage;
|
||||
var AnOutDirectory: string);
|
||||
procedure OnCheckInstallPackageList(PkgIDList: TFPList; var Ok: boolean);
|
||||
@ -165,23 +158,9 @@ type
|
||||
// helper functions
|
||||
function DoShowSavePackageAsDialog(APackage: TLazPackage): TModalResult;
|
||||
function DoWriteMakefile(APackage: TLazPackage): TModalResult;
|
||||
function CompileRequiredPackages(APackage: TLazPackage;
|
||||
FirstDependency: TPkgDependency;
|
||||
Globals: TGlobalCompilerOptions;
|
||||
Policies: TPackageUpdatePolicies): TModalResult;
|
||||
function CheckPackageGraphForCompilation(APackage: TLazPackage;
|
||||
FirstDependency: TPkgDependency;
|
||||
const Directory: string): TModalResult;
|
||||
function DoPreparePackageOutputDirectory(APackage: TLazPackage;
|
||||
CleanUp: boolean): TModalResult;
|
||||
function DoSavePackageCompiledState(APackage: TLazPackage;
|
||||
const CompilerFilename, CompilerParams: string): TModalResult;
|
||||
function DoLoadPackageCompiledState(APackage: TLazPackage;
|
||||
IgnoreErrors: boolean): TModalResult;
|
||||
function CheckIfPackageNeedsCompilation(APackage: TLazPackage;
|
||||
const CompilerFilename, CompilerParams,
|
||||
SrcFilename: string): TModalResult;
|
||||
function CheckAmbiguousPackageUnits(APackage: TLazPackage): TModalResult;
|
||||
function MacroFunctionPkgSrcPath(Data: Pointer): boolean;
|
||||
function MacroFunctionPkgUnitPath(Data: Pointer): boolean;
|
||||
function MacroFunctionPkgIncPath(Data: Pointer): boolean;
|
||||
@ -282,11 +261,7 @@ type
|
||||
Flags: TPkgCompileFlags): TModalResult; override;
|
||||
function DoCompilePackage(APackage: TLazPackage; Flags: TPkgCompileFlags;
|
||||
Globals: TGlobalCompilerOptions = nil): TModalResult; override;
|
||||
function DoSavePackageMainSource(APackage: TLazPackage;
|
||||
Flags: TPkgCompileFlags): TModalResult; override;
|
||||
function DoCreatePackageMakefile(APackage: TLazPackage): TModalResult;
|
||||
function DoCheckIfDependenciesNeedCompilation(DependencyOwner: TObject;
|
||||
StateFileAge: longint): TModalResult; override;
|
||||
|
||||
// package installation
|
||||
procedure LoadInstalledPackages; override;
|
||||
@ -556,13 +531,13 @@ begin
|
||||
end;
|
||||
|
||||
procedure TPkgManager.GetDependencyOwnerDescription(
|
||||
Dependency: TPkgDependency; var Description: string);
|
||||
Dependency: TPkgDependency; out Description: string);
|
||||
begin
|
||||
GetDescriptionOfDependencyOwner(Dependency,Description);
|
||||
end;
|
||||
|
||||
procedure TPkgManager.GetDependencyOwnerDirectory(Dependency: TPkgDependency;
|
||||
var Directory: string);
|
||||
out Directory: string);
|
||||
begin
|
||||
GetDirectoryOfDependencyOwner(Dependency,Directory);
|
||||
end;
|
||||
@ -775,7 +750,7 @@ end;
|
||||
function TPkgManager.OnPackageEditorDeleteAmbiguousFiles(Sender: TObject;
|
||||
APackage: TLazPackage; const Filename: string): TModalResult;
|
||||
begin
|
||||
Result:=MainIDE.DoDeleteAmbiguousFiles(Filename);
|
||||
Result:=BuildBoss.DeleteAmbiguousFiles(Filename);
|
||||
end;
|
||||
|
||||
function TPkgManager.OnPackageEditorAddToProject(Sender: TObject;
|
||||
@ -1248,7 +1223,7 @@ var
|
||||
MakefileFPCFilename: String;
|
||||
UnitOutputPath: String;
|
||||
UnitPath: String;
|
||||
FPCMakeTool: TExternalToolOptions;
|
||||
FPCMakeTool: TIDEExternalToolOptions;
|
||||
CodeBuffer: TCodeBuffer;
|
||||
MainSrcFile: String;
|
||||
CustomOptions: String;
|
||||
@ -1339,11 +1314,11 @@ begin
|
||||
CodeBuffer.Source:=s;
|
||||
|
||||
//debugln('TPkgManager.DoWriteMakefile MakefileFPCFilename="',MakefileFPCFilename,'"');
|
||||
Result:=MainIDE.DoSaveCodeBufferToFile(CodeBuffer,MakefileFPCFilename,false);
|
||||
Result:=SaveCodeBufferToFile(CodeBuffer,MakefileFPCFilename);
|
||||
if Result<>mrOk then exit;
|
||||
|
||||
// call fpcmake to create the Makefile
|
||||
FPCMakeTool:=TExternalToolOptions.Create;
|
||||
FPCMakeTool:=TIDEExternalToolOptions.Create;
|
||||
try
|
||||
FPCMakeTool.Title:='Creating Makefile for package '+APackage.IDAsString;
|
||||
FPCMakeTool.WorkingDirectory:=APackage.Directory;
|
||||
@ -1357,7 +1332,7 @@ begin
|
||||
SourceNotebook.ClearErrorLines;
|
||||
|
||||
// compile package
|
||||
Result:=LazarusIDE.RunExternalTool(FPCMakeTool);
|
||||
Result:=RunExternalTool(FPCMakeTool);
|
||||
if Result<>mrOk then begin
|
||||
Result:=IDEMessageDialog('fpcmake failed',
|
||||
'Calling '+FPCMakeTool.Filename+' to create Makefile from '
|
||||
@ -1373,39 +1348,6 @@ begin
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TPkgManager.CompileRequiredPackages(APackage: TLazPackage;
|
||||
FirstDependency: TPkgDependency; Globals: TGlobalCompilerOptions;
|
||||
Policies: TPackageUpdatePolicies): TModalResult;
|
||||
var
|
||||
AutoPackages: TFPList;
|
||||
i: Integer;
|
||||
begin
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TPkgManager.CompileRequiredPackages A ');
|
||||
{$ENDIF}
|
||||
AutoPackages:=PackageGraph.GetAutoCompilationOrder(APackage,FirstDependency,
|
||||
Policies);
|
||||
if AutoPackages<>nil then begin
|
||||
//DebugLn('TPkgManager.CompileRequiredPackages B Count=',IntToStr(AutoPackages.Count));
|
||||
try
|
||||
i:=0;
|
||||
while i<AutoPackages.Count do begin
|
||||
Result:=DoCompilePackage(TLazPackage(AutoPackages[i]),
|
||||
[pcfDoNotCompileDependencies,pcfOnlyIfNeeded,
|
||||
pcfDoNotSaveEditorFiles],Globals);
|
||||
if Result<>mrOk then exit;
|
||||
inc(i);
|
||||
end;
|
||||
finally
|
||||
AutoPackages.Free;
|
||||
end;
|
||||
end;
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TPkgManager.CompileRequiredPackages END ');
|
||||
{$ENDIF}
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TPkgManager.CheckPackageGraphForCompilation(APackage: TLazPackage;
|
||||
FirstDependency: TPkgDependency; const Directory: string): TModalResult;
|
||||
var
|
||||
@ -1514,380 +1456,6 @@ begin
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TPkgManager.DoSavePackageCompiledState(APackage: TLazPackage;
|
||||
const CompilerFilename, CompilerParams: string): TModalResult;
|
||||
var
|
||||
XMLConfig: TXMLConfig;
|
||||
StateFile: String;
|
||||
CompilerFileDate: Integer;
|
||||
begin
|
||||
StateFile:=APackage.GetStateFilename;
|
||||
try
|
||||
CompilerFileDate:=FileAge(CompilerFilename);
|
||||
XMLConfig:=TXMLConfig.CreateClean(StateFile);
|
||||
try
|
||||
XMLConfig.SetValue('Compiler/Value',CompilerFilename);
|
||||
XMLConfig.SetValue('Compiler/Date',CompilerFileDate);
|
||||
XMLConfig.SetValue('Params/Value',CompilerParams);
|
||||
InvalidateFileStateCache;
|
||||
XMLConfig.Flush;
|
||||
finally
|
||||
XMLConfig.Free;
|
||||
end;
|
||||
APackage.LastCompilerFilename:=CompilerFilename;
|
||||
APackage.LastCompilerFileDate:=CompilerFileDate;
|
||||
APackage.LastCompilerParams:=CompilerParams;
|
||||
APackage.StateFileDate:=FileAge(StateFile);
|
||||
APackage.Flags:=APackage.Flags+[lpfStateFileLoaded];
|
||||
except
|
||||
on E: Exception do begin
|
||||
Result:=IDEMessageDialog(lisPkgMangErrorWritingFile,
|
||||
Format(lisPkgMangUnableToWriteStateFileOfPackageError, ['"', StateFile,
|
||||
'"', #13, APackage.IDAsString, #13, E.Message]),
|
||||
mtError,[mbAbort,mbCancel]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result:=MainIDE.DoDeleteAmbiguousFiles(StateFile);
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
|
||||
function TPkgManager.DoLoadPackageCompiledState(APackage: TLazPackage;
|
||||
IgnoreErrors: boolean): TModalResult;
|
||||
var
|
||||
XMLConfig: TXMLConfig;
|
||||
StateFile: String;
|
||||
StateFileAge: Integer;
|
||||
begin
|
||||
StateFile:=APackage.GetStateFilename;
|
||||
if not FileExists(StateFile) then begin
|
||||
DebugLn('TPkgManager.DoLoadPackageCompiledState Statefile not found: ',StateFile);
|
||||
APackage.Flags:=APackage.Flags-[lpfStateFileLoaded];
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
|
||||
// read the state file
|
||||
StateFileAge:=FileAge(StateFile);
|
||||
if (not (lpfStateFileLoaded in APackage.Flags))
|
||||
or (APackage.StateFileDate<>StateFileAge) then begin
|
||||
APackage.Flags:=APackage.Flags-[lpfStateFileLoaded];
|
||||
try
|
||||
XMLConfig:=TXMLConfig.Create(StateFile);
|
||||
try
|
||||
APackage.LastCompilerFilename:=XMLConfig.GetValue('Compiler/Value','');
|
||||
APackage.LastCompilerFileDate:=XMLConfig.GetValue('Compiler/Date',0);
|
||||
APackage.LastCompilerParams:=XMLConfig.GetValue('Params/Value','');
|
||||
finally
|
||||
XMLConfig.Free;
|
||||
end;
|
||||
APackage.StateFileDate:=StateFileAge;
|
||||
except
|
||||
on E: Exception do begin
|
||||
if IgnoreErrors then begin
|
||||
Result:=mrOk;
|
||||
end else begin
|
||||
Result:=IDEMessageDialog(lisPkgMangErrorReadingFile,
|
||||
Format(lisPkgMangUnableToReadStateFileOfPackageError, ['"',
|
||||
StateFile, '"', #13, APackage.IDAsString, #13, E.Message]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
APackage.Flags:=APackage.Flags+[lpfStateFileLoaded];
|
||||
end;
|
||||
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TPkgManager.DoPreparePackageOutputDirectory(APackage: TLazPackage;
|
||||
CleanUp: boolean): TModalResult;
|
||||
var
|
||||
OutputDir: String;
|
||||
StateFile: String;
|
||||
PkgSrcDir: String;
|
||||
i: Integer;
|
||||
CurFile: TPkgFile;
|
||||
CompiledUnitExt: String;
|
||||
FPCVersion, FPCRelease, FPCPatch: integer;
|
||||
OutputFileName: String;
|
||||
begin
|
||||
OutputDir:=APackage.GetOutputDirectory;
|
||||
StateFile:=APackage.GetStateFilename;
|
||||
PkgSrcDir:=ExtractFilePath(APackage.GetSrcFilename);
|
||||
|
||||
// create the output directory
|
||||
if not ForceDirectory(OutputDir) then begin
|
||||
Result:=IDEMessageDialog(lisPkgMangUnableToCreateDirectory,
|
||||
Format(lisPkgMangUnableToCreateOutputDirectoryForPackage, ['"',
|
||||
OutputDir, '"', #13, APackage.IDAsString]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// delete old Compile State file
|
||||
if FileExists(StateFile) and not DeleteFile(StateFile) then begin
|
||||
Result:=IDEMessageDialog(lisPkgMangUnableToDeleteFilename,
|
||||
Format(lisPkgMangUnableToDeleteOldStateFileForPackage, ['"', StateFile,
|
||||
'"', #13, APackage.IDAsString]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
APackage.Flags:=APackage.Flags-[lpfStateFileLoaded];
|
||||
|
||||
// create the package src directory
|
||||
if not ForceDirectory(PkgSrcDir) then begin
|
||||
Result:=IDEMessageDialog(lisPkgMangUnableToCreateDirectory,
|
||||
Format(lisPkgMangUnableToCreatePackageSourceDirectoryForPackage, ['"',
|
||||
PkgSrcDir, '"', #13, APackage.IDAsString]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// clean up if wanted
|
||||
if CleanUp then begin
|
||||
CodeToolBoss.GetFPCVersionForDirectory(PkgSrcDir,
|
||||
FPCVersion,FPCRelease,FPCPatch);
|
||||
if FPCPatch=0 then ;
|
||||
CompiledUnitExt:=GetDefaultCompiledUnitExt(FPCVersion,FPCRelease);
|
||||
for i:=0 to APackage.FileCount-1 do begin
|
||||
CurFile:=APackage.Files[i];
|
||||
if not (CurFile.FileType in PkgFileUnitTypes) then continue;
|
||||
OutputFileName:=AppendPathDelim(OutputDir)+CurFile.UnitName+CompiledUnitExt;
|
||||
Result:=DeleteFileInteractive(OutputFileName,[mbIgnore,mbAbort]);
|
||||
if Result in [mrCancel,mrAbort] then exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TPkgManager.CheckIfPackageNeedsCompilation(APackage: TLazPackage;
|
||||
const CompilerFilename, CompilerParams, SrcFilename: string): TModalResult;
|
||||
var
|
||||
StateFilename: String;
|
||||
StateFileAge: Integer;
|
||||
i: Integer;
|
||||
CurFile: TPkgFile;
|
||||
begin
|
||||
Result:=mrYes;
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TPkgManager.CheckIfPackageNeedsCompilation A ',APackage.IDAsString);
|
||||
{$ENDIF}
|
||||
|
||||
// check state file
|
||||
StateFilename:=APackage.GetStateFilename;
|
||||
Result:=DoLoadPackageCompiledState(APackage,false);
|
||||
if Result<>mrOk then exit;
|
||||
if not (lpfStateFileLoaded in APackage.Flags) then begin
|
||||
DebugLn('TPkgManager.CheckIfPackageNeedsCompilation No state file for ',APackage.IDAsString);
|
||||
Result:=mrYes;
|
||||
exit;
|
||||
end;
|
||||
|
||||
StateFileAge:=FileAge(StateFilename);
|
||||
|
||||
// check main source file
|
||||
if FileExists(SrcFilename) and (StateFileAge<FileAge(SrcFilename)) then
|
||||
begin
|
||||
DebugLn('TPkgManager.CheckIfPackageNeedsCompilation SrcFile outdated ',APackage.IDAsString);
|
||||
Result:=mrYes;
|
||||
exit;
|
||||
end;
|
||||
|
||||
// check all required packages
|
||||
Result:=DoCheckIfDependenciesNeedCompilation(APackage,StateFileAge);
|
||||
if Result<>mrNo then exit;
|
||||
|
||||
Result:=mrYes;
|
||||
|
||||
// check compiler and params
|
||||
if CompilerFilename<>APackage.LastCompilerFilename then begin
|
||||
DebugLn('TPkgManager.CheckIfPackageNeedsCompilation Compiler filename changed for ',APackage.IDAsString);
|
||||
DebugLn(' Old="',APackage.LastCompilerFilename,'"');
|
||||
DebugLn(' Now="',CompilerFilename,'"');
|
||||
exit;
|
||||
end;
|
||||
if not FileExists(CompilerFilename) then begin
|
||||
DebugLn('TPkgManager.CheckIfPackageNeedsCompilation Compiler filename not found for ',APackage.IDAsString);
|
||||
DebugLn(' File="',CompilerFilename,'"');
|
||||
exit;
|
||||
end;
|
||||
if FileAge(CompilerFilename)<>APackage.LastCompilerFileDate then begin
|
||||
DebugLn('TPkgManager.CheckIfPackageNeedsCompilation Compiler file changed for ',APackage.IDAsString);
|
||||
DebugLn(' File="',CompilerFilename,'"');
|
||||
exit;
|
||||
end;
|
||||
if CompilerParams<>APackage.LastCompilerParams then begin
|
||||
DebugLn('TPkgManager.CheckIfPackageNeedsCompilation Compiler params changed for ',APackage.IDAsString);
|
||||
DebugLn(' Old="',APackage.LastCompilerParams,'"');
|
||||
DebugLn(' Now="',CompilerParams,'"');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// check package files
|
||||
if StateFileAge<FileAge(APackage.Filename) then begin
|
||||
DebugLn('TPkgManager.CheckIfPackageNeedsCompilation StateFile older than lpk ',APackage.IDAsString);
|
||||
exit;
|
||||
end;
|
||||
for i:=0 to APackage.FileCount-1 do begin
|
||||
CurFile:=APackage.Files[i];
|
||||
//writeln('TPkgManager.CheckIfPackageNeedsCompilation CurFile.Filename="',CurFile.Filename,'" ',FileExists(CurFile.Filename),' ',StateFileAge<FileAge(CurFile.Filename));
|
||||
if FileExists(CurFile.Filename)
|
||||
and (StateFileAge<FileAge(CurFile.Filename)) then begin
|
||||
DebugLn('TPkgManager.CheckIfPackageNeedsCompilation Src has changed ',APackage.IDAsString,' ',CurFile.Filename);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TPkgManager.CheckIfPackageNeedsCompilation END ',APackage.IDAsString);
|
||||
{$ENDIF}
|
||||
Result:=mrNo;
|
||||
end;
|
||||
|
||||
function TPkgManager.DoCheckIfDependenciesNeedCompilation(
|
||||
DependencyOwner: TObject; StateFileAge: longint): TModalResult;
|
||||
|
||||
function GetOwnerID: string;
|
||||
begin
|
||||
if DependencyOwner is TLazPackageID then
|
||||
Result:=TLazPackageID(DependencyOwner).IDAsString
|
||||
else if DependencyOwner is TProject then
|
||||
Result:=TProject(DependencyOwner).IDAsString
|
||||
else
|
||||
Result:=dbgsName(DependencyOwner);
|
||||
end;
|
||||
|
||||
var
|
||||
Dependency: TPkgDependency;
|
||||
RequiredPackage: TLazPackage;
|
||||
OtherStateFile: String;
|
||||
begin
|
||||
if DependencyOwner is TLazPackage then
|
||||
Dependency:=TLazPackage(DependencyOwner).FirstRequiredDependency
|
||||
else if DependencyOwner is TProject then
|
||||
Dependency:=TProject(DependencyOwner).FirstRequiredDependency
|
||||
else begin
|
||||
Result:=mrNo;
|
||||
exit;
|
||||
end;
|
||||
|
||||
while Dependency<>nil do begin
|
||||
if (Dependency.LoadPackageResult=lprSuccess) then begin
|
||||
RequiredPackage:=Dependency.RequiredPackage;
|
||||
// check compile state file of required package
|
||||
if not RequiredPackage.AutoCreated then begin
|
||||
Result:=DoLoadPackageCompiledState(RequiredPackage,false);
|
||||
if Result<>mrOk then exit;
|
||||
Result:=mrYes;
|
||||
if not (lpfStateFileLoaded in RequiredPackage.Flags) then begin
|
||||
DebugLn('TPkgManager.CheckIfDependenciesNeedCompilation No state file for ',RequiredPackage.IDAsString);
|
||||
exit;
|
||||
end;
|
||||
if StateFileAge<RequiredPackage.StateFileDate then begin
|
||||
DebugLn('TPkgManager.CheckIfDependenciesNeedCompilation Required ',
|
||||
RequiredPackage.IDAsString,' State file is newer than ',
|
||||
'State file ',GetOwnerID);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
// check output state file of required package
|
||||
if RequiredPackage.OutputStateFile<>'' then begin
|
||||
OtherStateFile:=RequiredPackage.OutputStateFile;
|
||||
IDEMacros.SubstituteMacros(OtherStateFile);
|
||||
if FileExists(OtherStateFile)
|
||||
and (FileAge(OtherStateFile)>StateFileAge) then begin
|
||||
DebugLn('TPkgManager.CheckIfDependenciesNeedCompilation Required ',
|
||||
RequiredPackage.IDAsString,' OtherState file "',OtherStateFile,'"'
|
||||
,' is newer than State file ',GetOwnerID);
|
||||
Result:=mrYes;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Dependency:=Dependency.NextRequiresDependency;
|
||||
end;
|
||||
Result:=mrNo;
|
||||
end;
|
||||
|
||||
function TPkgManager.CheckAmbiguousPackageUnits(APackage: TLazPackage
|
||||
): TModalResult;
|
||||
var
|
||||
i: Integer;
|
||||
CurFile: TPkgFile;
|
||||
CurUnitName: String;
|
||||
SrcDirs: String;
|
||||
PkgDir: String;
|
||||
PkgOutputDir: String;
|
||||
YesToAll: Boolean;
|
||||
|
||||
function CheckFile(const ShortFilename: string): TModalResult;
|
||||
var
|
||||
AmbiguousFilename: String;
|
||||
SearchFlags: TSearchFileInPathFlags;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
SearchFlags:=[];
|
||||
if CompareFilenames(PkgDir,PkgOutputDir)=0 then
|
||||
Include(SearchFlags,sffDontSearchInBasePath);
|
||||
repeat
|
||||
AmbiguousFilename:=SearchFileInPath(ShortFilename,PkgDir,SrcDirs,';',
|
||||
SearchFlags);
|
||||
if (AmbiguousFilename='') then exit;
|
||||
if not YesToAll then
|
||||
Result:=IDEMessageDialog(lisAmbiguousUnitFound,
|
||||
Format(lisTheFileWasFoundInOneOfTheSourceDirectoriesOfThePac, ['"',
|
||||
AmbiguousFilename, '"', #13, APackage.IDAsString, #13, #13]),
|
||||
mtWarning,[mbYes,mbYesToAll,mbNo,mbAbort])
|
||||
else
|
||||
Result:=mrYesToAll;
|
||||
if Result=mrNo then
|
||||
Result:=mrOk;
|
||||
if Result in [mrYes,mrYesToAll] then begin
|
||||
YesToAll:=Result=mrYesToAll;
|
||||
if (not DeleteFile(AmbiguousFilename))
|
||||
and (IDEMessageDialog(lisPkgMangDeleteFailed, Format(lisDeletingOfFileFailed,
|
||||
['"', AmbiguousFilename, '"']), mtError, [mbIgnore, mbCancel])
|
||||
<>mrIgnore) then
|
||||
begin
|
||||
Result:=mrCancel;
|
||||
exit;
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end else
|
||||
break;
|
||||
until false;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result:=mrOk;
|
||||
YesToAll:=False;
|
||||
// search in every source directory for compiled versions of the units
|
||||
// A source directory is a directory with a used unit and it is not the output
|
||||
// directory
|
||||
SrcDirs:=APackage.GetSourceDirs(true,true);
|
||||
PkgOutputDir:=AppendPathDelim(APackage.GetOutputDirectory);
|
||||
SrcDirs:=RemoveSearchPaths(SrcDirs,PkgOutputDir);
|
||||
if SrcDirs='' then exit;
|
||||
PkgDir:=AppendPathDelim(APackage.Directory);
|
||||
for i:=0 to APackage.FileCount-1 do begin
|
||||
CurFile:=APackage.Files[i];
|
||||
if CurFile.FileType<>pftUnit then continue;
|
||||
CurUnitName:=lowercase(CurFile.UnitName);
|
||||
if CurUnitName='' then continue;
|
||||
Result:=CheckFile(CurUnitName+'.ppu');
|
||||
if Result<>mrOk then exit;
|
||||
Result:=CheckFile(CurUnitName+'.ppw');
|
||||
if Result<>mrOk then exit;
|
||||
Result:=CheckFile(CurUnitName+'.ppl');
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TPkgManager.MacroFunctionPkgSrcPath(Data: Pointer): boolean;
|
||||
var
|
||||
FuncData: PReadFunctionData;
|
||||
@ -2192,6 +1760,9 @@ begin
|
||||
PackageGraph.OnDependencyModified:=@PackageGraphDependencyModified;
|
||||
PackageGraph.OnBeginUpdate:=@PackageGraphBeginUpdate;
|
||||
PackageGraph.OnEndUpdate:=@PackageGraphEndUpdate;
|
||||
PackageGraph.OnDeleteAmbiguousFiles:=@BuildBoss.DeleteAmbiguousFiles;
|
||||
PackageGraph.OnWriteMakeFile:=@DoWriteMakefile;
|
||||
PackageGraph.OnUninstallPackage:=@DoUninstallPackage;
|
||||
|
||||
// package editors
|
||||
PackageEditors:=TPackageEditors.Create;
|
||||
@ -2721,11 +2292,11 @@ begin
|
||||
end;
|
||||
|
||||
// backup old file
|
||||
Result:=MainIDE.DoBackupFile(APackage.Filename,true);
|
||||
Result:=BuildBoss.BackupFile(APackage.Filename);
|
||||
if Result=mrAbort then exit;
|
||||
|
||||
// delete ambiguous files
|
||||
Result:=MainIDE.DoDeleteAmbiguousFiles(APackage.Filename);
|
||||
Result:=BuildBoss.DeleteAmbiguousFiles(APackage.Filename);
|
||||
if Result=mrAbort then exit;
|
||||
|
||||
// save
|
||||
@ -2855,7 +2426,8 @@ begin
|
||||
try
|
||||
// automatically compile required packages
|
||||
if not (pcfDoNotCompileDependencies in Flags) then begin
|
||||
Result:=CompileRequiredPackages(nil,AProject.FirstRequiredDependency,
|
||||
Result:=PackageGraph.CompileRequiredPackages(nil,
|
||||
AProject.FirstRequiredDependency,
|
||||
AProject.CompilerOptions.Globals,
|
||||
[pupAsNeeded]);
|
||||
if Result<>mrOk then exit;
|
||||
@ -2869,13 +2441,6 @@ end;
|
||||
|
||||
function TPkgManager.DoCompilePackage(APackage: TLazPackage;
|
||||
Flags: TPkgCompileFlags; Globals: TGlobalCompilerOptions): TModalResult;
|
||||
var
|
||||
PkgCompileTool: TExternalToolOptions;
|
||||
CompilerFilename: String;
|
||||
CompilerParams: String;
|
||||
EffektiveCompilerParams: String;
|
||||
SrcFilename: String;
|
||||
CompilePolicies: TPackageUpdatePolicies;
|
||||
begin
|
||||
Result:=mrCancel;
|
||||
|
||||
@ -2904,330 +2469,7 @@ begin
|
||||
Result:=WarnAboutMissingPackageFiles(APackage);
|
||||
if Result<>mrOk then exit;
|
||||
|
||||
PackageGraph.BeginUpdate(false);
|
||||
try
|
||||
// automatically compile required packages
|
||||
if not (pcfDoNotCompileDependencies in Flags) then begin
|
||||
CompilePolicies:=[pupAsNeeded];
|
||||
if pcfCompileDependenciesClean in Flags then
|
||||
Include(CompilePolicies,pupOnRebuildingAll);
|
||||
Result:=CompileRequiredPackages(APackage,nil,Globals,CompilePolicies);
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
|
||||
SrcFilename:=APackage.GetSrcFilename;
|
||||
CompilerFilename:=APackage.GetCompilerFilename;
|
||||
CompilerParams:=APackage.CompilerOptions.MakeOptionsString(Globals,
|
||||
APackage.CompilerOptions.DefaultMakeOptionsFlags)
|
||||
+' '+CreateRelativePath(SrcFilename,APackage.Directory);
|
||||
|
||||
// check if compilation is neccessary
|
||||
if (pcfOnlyIfNeeded in Flags) then begin
|
||||
Result:=CheckIfPackageNeedsCompilation(APackage,
|
||||
CompilerFilename,CompilerParams,
|
||||
SrcFilename);
|
||||
if Result=mrNo then begin
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
if Result<>mrYes then exit;
|
||||
end;
|
||||
|
||||
// auto increase version
|
||||
// ToDo
|
||||
|
||||
MessagesView.BeginBlock;
|
||||
try
|
||||
Result:=DoPreparePackageOutputDirectory(APackage,pcfCleanCompile in Flags);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TPkgManager.DoCompilePackage DoPreparePackageOutputDirectory failed');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// create package main source file
|
||||
Result:=DoSavePackageMainSource(APackage,Flags);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TPkgManager.DoCompilePackage DoSavePackageMainSource failed');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// check ambiguous units
|
||||
Result:=CheckAmbiguousPackageUnits(APackage);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TPkgManager.DoCompilePackage CheckAmbiguousPackageUnits failed');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// create Makefile
|
||||
if (pcfCreateMakefile in Flags)
|
||||
or (APackage.CompilerOptions.CreateMakefileOnBuild) then begin
|
||||
Result:=DoWriteMakefile(APackage);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TPkgManager.DoCompilePackage DoWriteMakefile failed');
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// run compilation tool 'Before'
|
||||
if not (pcfDoNotCompilePackage in Flags) then begin
|
||||
Result:=MainIDE.DoExecuteCompilationTool(
|
||||
APackage.CompilerOptions.ExecuteBefore,
|
||||
APackage.Directory,'Executing command before');
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
|
||||
// create external tool to run the compiler
|
||||
DebugLn('TPkgManager.DoCompilePackage Compiler="',CompilerFilename,'"');
|
||||
DebugLn('TPkgManager.DoCompilePackage Params="',CompilerParams,'"');
|
||||
DebugLn('TPkgManager.DoCompilePackage WorkingDir="',APackage.Directory,'"');
|
||||
|
||||
if (not APackage.CompilerOptions.SkipCompiler)
|
||||
and (not (pcfDoNotCompilePackage in Flags)) then begin
|
||||
// check compiler filename
|
||||
try
|
||||
CheckIfFileIsExecutable(CompilerFilename);
|
||||
except
|
||||
on e: Exception do begin
|
||||
Result:=IDEMessageDialog(lisPkgManginvalidCompilerFilename,
|
||||
Format(lisPkgMangTheCompilerFileForPackageIsNotAValidExecutable, [
|
||||
APackage.IDAsString, #13, E.Message]),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// change compiler parameters for compiling clean
|
||||
EffektiveCompilerParams:=CompilerParams;
|
||||
if pcfCleanCompile in Flags then begin
|
||||
if EffektiveCompilerParams<>'' then
|
||||
EffektiveCompilerParams:='-B '+EffektiveCompilerParams
|
||||
else
|
||||
EffektiveCompilerParams:='-B';
|
||||
end;
|
||||
|
||||
PkgCompileTool:=TExternalToolOptions.Create;
|
||||
try
|
||||
PkgCompileTool.Title:='Compiling package '+APackage.IDAsString;
|
||||
PkgCompileTool.ScanOutputForFPCMessages:=true;
|
||||
PkgCompileTool.ScanOutputForMakeMessages:=true;
|
||||
PkgCompileTool.WorkingDirectory:=APackage.Directory;
|
||||
PkgCompileTool.Filename:=CompilerFilename;
|
||||
PkgCompileTool.CmdLineParams:=EffektiveCompilerParams;
|
||||
|
||||
// clear old errors
|
||||
SourceNotebook.ClearErrorLines;
|
||||
|
||||
// compile package
|
||||
Result:=EnvironmentOptions.ExternalTools.Run(PkgCompileTool,
|
||||
GlobalMacroList,nil,APackage.CompilerOptions);
|
||||
if Result<>mrOk then exit;
|
||||
// compilation succeded -> write state file
|
||||
Result:=DoSavePackageCompiledState(APackage,
|
||||
CompilerFilename,CompilerParams);
|
||||
if Result<>mrOk then exit;
|
||||
finally
|
||||
// clean up
|
||||
PkgCompileTool.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
// run compilation tool 'After'
|
||||
if not (pcfDoNotCompilePackage in Flags) then begin
|
||||
Result:=MainIDE.DoExecuteCompilationTool(
|
||||
APackage.CompilerOptions.ExecuteAfter,
|
||||
APackage.Directory,'Executing command after');
|
||||
if Result<>mrOk then exit;
|
||||
end;
|
||||
finally
|
||||
MessagesView.EndBlock;
|
||||
|
||||
if Result<>mrOk then begin
|
||||
if (APackage.AutoInstall<>pitNope) and (APackage.Installed=pitNope) then
|
||||
begin
|
||||
// package was tried to install, but failed
|
||||
// -> ask user if the package should be removed from the installation
|
||||
// list
|
||||
if IDEMessageDialog(lisInstallationFailed,
|
||||
Format(
|
||||
lisPkgMangThePackageFailedToCompileRemoveItFromTheInstallati, [
|
||||
'"', APackage.IDAsString, '"', #13]), mtConfirmation,
|
||||
[mbYes,mbIgnore])=mrYes then
|
||||
begin
|
||||
DoUninstallPackage(APackage,[puifDoNotConfirm,puifDoNotBuildIDE]);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
finally
|
||||
if not (pcfDoNotSaveEditorFiles in Flags) then begin
|
||||
// check for changed files on disk
|
||||
MainIDE.DoCheckFilesOnDisk;
|
||||
end;
|
||||
|
||||
PackageGraph.EndUpdate;
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
|
||||
function TPkgManager.DoSavePackageMainSource(APackage: TLazPackage;
|
||||
Flags: TPkgCompileFlags): TModalResult;
|
||||
var
|
||||
SrcFilename: String;
|
||||
UsedUnits: String;
|
||||
Src: String;
|
||||
i: Integer;
|
||||
e: String;
|
||||
CurFile: TPkgFile;
|
||||
CodeBuffer: TCodeBuffer;
|
||||
CurUnitName: String;
|
||||
RegistrationCode: String;
|
||||
HeaderSrc: String;
|
||||
OutputDir: String;
|
||||
OldShortenSrc: String;
|
||||
NeedsRegisterProcCall: boolean;
|
||||
CurSrcUnitName: String;
|
||||
NewShortenSrc: String;
|
||||
begin
|
||||
{$IFDEF VerbosePkgCompile}
|
||||
writeln('TPkgManager.DoSavePackageMainSource A');
|
||||
{$ENDIF}
|
||||
// check if package is ready for saving
|
||||
OutputDir:=APackage.GetOutputDirectory;
|
||||
if not DirPathExists(OutputDir) then begin
|
||||
Result:=IDEMessageDialog(lisEnvOptDlgDirectoryNotFound,
|
||||
Format(lisPkgMangPackageHasNoValidOutputDirectory, ['"',
|
||||
APackage.IDAsString, '"', #13, '"', OutputDir, '"']),
|
||||
mtError,[mbCancel,mbAbort]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
SrcFilename:=APackage.GetSrcFilename;
|
||||
|
||||
// delete ambiguous files
|
||||
Result:=MainIDE.DoDeleteAmbiguousFiles(SrcFilename);
|
||||
if Result=mrAbort then begin
|
||||
DebugLn('TPkgManager.DoSavePackageMainSource DoDeleteAmbiguousFiles failed');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// collect unitnames
|
||||
e:=LineEnding;
|
||||
UsedUnits:='';
|
||||
RegistrationCode:='';
|
||||
for i:=0 to APackage.FileCount-1 do begin
|
||||
CurFile:=APackage.Files[i];
|
||||
// update unitname
|
||||
if FilenameIsPascalUnit(CurFile.Filename)
|
||||
and (CurFile.FileType in PkgFileUnitTypes) then begin
|
||||
CurUnitName:=ExtractFileNameOnly(CurFile.Filename);
|
||||
|
||||
if CurUnitName=lowercase(CurUnitName) then begin
|
||||
// the filename is all lowercase, so we can use the nicer unitname from
|
||||
// the source.
|
||||
|
||||
CodeBuffer:=CodeToolBoss.LoadFile(CurFile.Filename,false,false);
|
||||
if CodeBuffer<>nil then begin
|
||||
// if the unit is edited, the unitname is probably already cached
|
||||
CurSrcUnitName:=CodeToolBoss.GetCachedSourceName(CodeBuffer);
|
||||
// if not then parse it
|
||||
if SysUtils.CompareText(CurSrcUnitName,CurUnitName)<>0 then
|
||||
CurSrcUnitName:=CodeToolBoss.GetSourceName(CodeBuffer,false);
|
||||
// if it makes sense, update unitname
|
||||
if SysUtils.CompareText(CurSrcUnitName,CurFile.UnitName)=0 then
|
||||
CurFile.UnitName:=CurSrcUnitName;
|
||||
end;
|
||||
if SysUtils.CompareText(CurUnitName,CurFile.UnitName)=0 then
|
||||
CurUnitName:=CurFile.UnitName
|
||||
else
|
||||
CurFile.UnitName:=CurUnitName;
|
||||
end;
|
||||
|
||||
if (CurUnitName<>'') and IsValidIdent(CurUnitName) then begin
|
||||
NeedsRegisterProcCall:=CurFile.HasRegisterProc
|
||||
and (APackage.PackageType in [lptDesignTime,lptRunAndDesignTime]);
|
||||
if NeedsRegisterProcCall or CurFile.AddToUsesPkgSection then begin
|
||||
if UsedUnits<>'' then
|
||||
UsedUnits:=UsedUnits+', ';
|
||||
UsedUnits:=UsedUnits+CurUnitName;
|
||||
end;
|
||||
if NeedsRegisterProcCall then begin
|
||||
RegistrationCode:=RegistrationCode+
|
||||
' RegisterUnit('''+CurUnitName+''',@'+CurUnitName+'.Register);'+e;
|
||||
end;
|
||||
end else begin
|
||||
MessagesView.AddMsg('WARNING: unit name invalid '+CurFile.Filename
|
||||
+', package='+APackage.IDAsString,
|
||||
APackage.Directory,-1);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
// append registration code only for design time packages
|
||||
if (APackage.PackageType in [lptDesignTime,lptRunAndDesignTime]) then begin
|
||||
RegistrationCode:=
|
||||
'procedure Register;'+e
|
||||
+'begin'+e
|
||||
+RegistrationCode
|
||||
+'end;'+e
|
||||
+e
|
||||
+'initialization'+e
|
||||
+' RegisterPackage('''+APackage.Name+''',@Register);'
|
||||
+e;
|
||||
if UsedUnits<>'' then UsedUnits:=UsedUnits+', ';
|
||||
UsedUnits:=UsedUnits+'LazarusPackageIntf';
|
||||
end;
|
||||
|
||||
// create source
|
||||
HeaderSrc:=lisPkgMangThisSourceIsOnlyUsedToCompileAndInstallThePackage;
|
||||
HeaderSrc:= '{ '
|
||||
+lisPkgMangThisFileWasAutomaticallyCreatedByLazarusDoNotEdit+e
|
||||
+lisPkgMangThisSourceIsOnlyUsedToCompileAndInstallThePackage+e
|
||||
+' }'+e+e;
|
||||
Src:='unit '+APackage.Name+';'+e
|
||||
+e
|
||||
+'interface'+e
|
||||
+e;
|
||||
if UsedUnits<>'' then
|
||||
Src:=Src
|
||||
+'uses'+e
|
||||
+' '+UsedUnits+';'+e
|
||||
+e;
|
||||
Src:=Src
|
||||
+'implementation'+e
|
||||
+e
|
||||
+RegistrationCode
|
||||
+'end.'+e;
|
||||
Src:=CodeToolBoss.SourceChangeCache.BeautifyCodeOptions.
|
||||
BeautifyStatement(Src,0);
|
||||
Src:=HeaderSrc+Src;
|
||||
|
||||
// check if old code is already uptodate
|
||||
Result:=LoadCodeBuffer(CodeBuffer,SrcFilename,[lbfQuiet,lbfCheckIfText,
|
||||
lbfUpdateFromDisk,lbfCreateClearOnError]);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TPkgManager.DoSavePackageMainSource LoadCodeBuffer ',SrcFilename,' failed');
|
||||
exit;
|
||||
end;
|
||||
OldShortenSrc:=CodeToolBoss.ExtractCodeWithoutComments(CodeBuffer);
|
||||
NewShortenSrc:=CleanCodeFromComments(Src,
|
||||
CodeToolBoss.GetNestedCommentsFlagForFile(CodeBuffer.Filename));
|
||||
if CompareTextIgnoringSpace(OldShortenSrc,NewShortenSrc,true)=0 then begin
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
if OldShortenSrc<>NewShortenSrc then begin
|
||||
DebugLn('TPkgManager.DoSavePackageMainSource Src changed ',dbgs(length(OldShortenSrc)),' ',dbgs(length(NewShortenSrc)));
|
||||
end;
|
||||
|
||||
// save source
|
||||
Result:=MainIDE.DoSaveStringToFile(SrcFilename, Src,
|
||||
lisPkgMangpackageMainSourceFile);
|
||||
if Result<>mrOk then begin
|
||||
DebugLn('TPkgManager.DoSavePackageMainSource DoSaveStringToFile ',SrcFilename,' failed');
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result:=mrOk;
|
||||
Result:=PackageGraph.CompilePackage(APackage,Flags,Globals);
|
||||
end;
|
||||
|
||||
function TPkgManager.DoCreatePackageMakefile(APackage: TLazPackage
|
||||
@ -4081,7 +3323,7 @@ begin
|
||||
end;
|
||||
|
||||
// compile all auto install dependencies
|
||||
Result:=CompileRequiredPackages(nil,FirstAutoInstallDependency,
|
||||
Result:=PackageGraph.CompileRequiredPackages(nil,FirstAutoInstallDependency,
|
||||
MiscellaneousOptions.BuildLazOpts.Globals,[pupAsNeeded]);
|
||||
if Result<>mrOk then exit;
|
||||
|
||||
@ -4110,8 +3352,8 @@ begin
|
||||
Dependency:=Dependency.NextRequiresDependency;
|
||||
end;
|
||||
StaticPckIncludeFile:=ConfigDir+'staticpackages.inc';
|
||||
Result:=MainIDE.DoSaveStringToFile(StaticPckIncludeFile,StaticPackagesInc,
|
||||
lisPkgMangstaticPackagesConfigFile);
|
||||
Result:=SaveStringToFile(StaticPckIncludeFile,StaticPackagesInc,[],
|
||||
lisPkgMangstaticPackagesConfigFile);
|
||||
if Result<>mrOk then exit;
|
||||
|
||||
TargetDir:=MiscellaneousOptions.BuildLazOpts.TargetDirectory;
|
||||
|
Loading…
Reference in New Issue
Block a user