mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-10 03:16:10 +02:00
IDE: started checking orphaned ppu files of packages
git-svn-id: trunk@47981 -
This commit is contained in:
parent
2620f33806
commit
e89f096e51
@ -833,7 +833,8 @@ begin
|
||||
end;
|
||||
|
||||
type
|
||||
TPGInterPkgOwnerInfo = record
|
||||
TPGInterPkgOwnerInfo = class
|
||||
public
|
||||
Name: string;
|
||||
Owner: TObject;
|
||||
HasOptionUr: boolean;
|
||||
@ -842,14 +843,16 @@ type
|
||||
IncDirs: string; // incpath without inherited and without SrcDirs
|
||||
UnitOutDir: string; // can be empty -> if empty FPC creates ppu in SrcDirs
|
||||
end;
|
||||
POwnerInfo = ^TPGInterPkgOwnerInfo;
|
||||
|
||||
{ TPGInterPkgFile }
|
||||
|
||||
TPGInterPkgFile = class
|
||||
public
|
||||
FullFilename: string;
|
||||
ShortFilename: string;
|
||||
AnUnitName: string;
|
||||
Owner: TPGInterPkgOwnerInfo;
|
||||
OwnerInfo: TPGInterPkgOwnerInfo;
|
||||
constructor Create(TheFullFilename, TheUnitName: string; Owner: TPGInterPkgOwnerInfo);
|
||||
end;
|
||||
|
||||
function ComparePGInterPkgFullFilenames(File1, File2: Pointer): integer;
|
||||
@ -860,6 +863,33 @@ begin
|
||||
Result:=CompareFilenames(F1.FullFilename,F2.FullFilename);
|
||||
end;
|
||||
|
||||
function ComparePGInterPkgUnitnames(File1, File2: Pointer): integer;
|
||||
var
|
||||
F1: TPGInterPkgFile absolute File1;
|
||||
F2: TPGInterPkgFile absolute File2;
|
||||
begin
|
||||
Result:=CompareDottedIdentifiers(PChar(Pointer(F1.AnUnitName)),PChar(Pointer(F2.AnUnitName)));
|
||||
end;
|
||||
|
||||
function ComparePGInterPkgShortFilename(File1, File2: Pointer): integer;
|
||||
var
|
||||
F1: TPGInterPkgFile absolute File1;
|
||||
F2: TPGInterPkgFile absolute File2;
|
||||
begin
|
||||
Result:=CompareFilenames(F1.ShortFilename,F2.ShortFilename);
|
||||
end;
|
||||
|
||||
{ TPGInterPkgFile }
|
||||
|
||||
constructor TPGInterPkgFile.Create(TheFullFilename, TheUnitName: string;
|
||||
Owner: TPGInterPkgOwnerInfo);
|
||||
begin
|
||||
FullFilename:=TheFullFilename;
|
||||
ShortFilename:=ExtractFileName(FullFilename);
|
||||
AnUnitName:=TheUnitName;
|
||||
OwnerInfo:=Owner;
|
||||
end;
|
||||
|
||||
function TLazPackageGraph.CheckAmbiguousInterPkgFiles(IDEObject: TObject;
|
||||
PkgList: TFPList): TModalResult;
|
||||
{ Scan all source and output directories (Note: they are already cached, because
|
||||
@ -868,78 +898,82 @@ function TLazPackageGraph.CheckAmbiguousInterPkgFiles(IDEObject: TObject;
|
||||
|
||||
IDEObject can be a TProject, TLazPackage or TLazPackageGraph(building IDE)
|
||||
PkgList is list of TLazPackage
|
||||
|
||||
Check the following:
|
||||
|
||||
}
|
||||
var
|
||||
OwnerInfos: array of TPGInterPkgOwnerInfo;
|
||||
OwnerInfos: TObjectList; // list of TPGInterPkgOwnerInfo
|
||||
TargetOS: String;
|
||||
TargetCPU: String;
|
||||
LCLWidgetType: String;
|
||||
Files: TAVLTree;
|
||||
FullFiles: TAVLTree; // tree of TPGInterPkgFile sorted for FullFilename
|
||||
Units: TAVLTree; // tree of TPGInterPkgFile sorted for AnUnitName
|
||||
ShortFiles: TAVLTree; // tree of TPGInterPkgFile sorted for ShortFilename
|
||||
|
||||
procedure InitOwnerInfo(OwnerInfo: POwnerInfo; TheOwner: TObject);
|
||||
procedure AddOwnerInfo(TheOwner: TObject);
|
||||
var
|
||||
LazDir: String;
|
||||
CustomOptions: String;
|
||||
p: Integer;
|
||||
OwnerInfo: TPGInterPkgOwnerInfo;
|
||||
begin
|
||||
FillByte(OwnerInfo^,SizeOf(TPGInterPkgOwnerInfo),0);
|
||||
OwnerInfo^.Owner:=TheOwner;
|
||||
OwnerInfo:=TPGInterPkgOwnerInfo.Create;
|
||||
OwnerInfos.Add(OwnerInfo);
|
||||
OwnerInfo.Owner:=TheOwner;
|
||||
if TheOwner is TLazPackage then
|
||||
begin
|
||||
OwnerInfo^.Name:=TLazPackage(TheOwner).IDAsString;
|
||||
OwnerInfo^.CompOptions:=TLazPackage(TheOwner).LazCompilerOptions as TBaseCompilerOptions;
|
||||
OwnerInfo.Name:=TLazPackage(TheOwner).IDAsString;
|
||||
OwnerInfo.CompOptions:=TLazPackage(TheOwner).LazCompilerOptions as TBaseCompilerOptions;
|
||||
end else if TheOwner is TLazProject then
|
||||
begin
|
||||
OwnerInfo^.Name:=TLazProject(TheOwner).GetTitleOrName;
|
||||
OwnerInfo^.CompOptions:=TLazProject(TheOwner).LazCompilerOptions as TBaseCompilerOptions;
|
||||
OwnerInfo.Name:=TLazProject(TheOwner).GetTitleOrName;
|
||||
OwnerInfo.CompOptions:=TLazProject(TheOwner).LazCompilerOptions as TBaseCompilerOptions;
|
||||
end
|
||||
else if TheOwner=Self then begin
|
||||
// building IDE
|
||||
OwnerInfo^.Name:='#IDE';
|
||||
OwnerInfo.Name:='#IDE';
|
||||
LazDir:=AppendPathDelim(EnvironmentOptions.GetParsedLazarusDirectory);
|
||||
OwnerInfo^.SrcDirs:=LazDir+'ide'
|
||||
OwnerInfo.SrcDirs:=LazDir+'ide'
|
||||
+';'+LazDir+'debugger'
|
||||
+';'+LazDir+'packager'
|
||||
+';'+LazDir+'designer'
|
||||
+';'+LazDir+'converter';
|
||||
OwnerInfo^.IncDirs:=OwnerInfo^.SrcDirs
|
||||
OwnerInfo.IncDirs:=OwnerInfo.SrcDirs
|
||||
+';'+LazDir+'ide'+PathDelim+'include'+PathDelim+TargetOS
|
||||
+';'+LazDir+'ide'+PathDelim+'include'+PathDelim+GetDefaultSrcOSForTargetOS(TargetOS);
|
||||
OwnerInfo^.UnitOutDir:=LazDir+'units'+PathDelim+TargetCPU+'-'+TargetOS+PathDelim+LCLWidgetType;
|
||||
OwnerInfo.UnitOutDir:=LazDir+'units'+PathDelim+TargetCPU+'-'+TargetOS+PathDelim+LCLWidgetType;
|
||||
end;
|
||||
if OwnerInfo^.CompOptions<>nil then begin
|
||||
OwnerInfo^.SrcDirs:=OwnerInfo^.CompOptions.GetPath(
|
||||
if OwnerInfo.CompOptions<>nil then begin
|
||||
OwnerInfo.SrcDirs:=OwnerInfo.CompOptions.GetPath(
|
||||
pcosUnitPath,icoNone,false,coptParsed,true);
|
||||
OwnerInfo^.IncDirs:=OwnerInfo^.CompOptions.GetPath(
|
||||
OwnerInfo.IncDirs:=OwnerInfo.CompOptions.GetPath(
|
||||
pcosIncludePath,icoNone,false,coptParsed,true);
|
||||
if OwnerInfo^.CompOptions.UnitOutputDirectory<>'' then
|
||||
OwnerInfo^.UnitOutDir:=OwnerInfo^.CompOptions.GetUnitOutputDirectory(false);
|
||||
CustomOptions:=OwnerInfo^.CompOptions.ParsedOpts.GetParsedValue(pcosCustomOptions);
|
||||
if OwnerInfo.CompOptions.UnitOutputDirectory<>'' then
|
||||
OwnerInfo.UnitOutDir:=OwnerInfo.CompOptions.GetUnitOutputDirectory(false);
|
||||
CustomOptions:=OwnerInfo.CompOptions.ParsedOpts.GetParsedValue(pcosCustomOptions);
|
||||
p:=1;
|
||||
OwnerInfo^.HasOptionUr:=FindNextFPCParameter(CustomOptions,'-Ur',p)>0;
|
||||
OwnerInfo.HasOptionUr:=FindNextFPCParameter(CustomOptions,'-Ur',p)>0;
|
||||
end;
|
||||
OwnerInfo^.IncDirs:=TrimSearchPath(RemoveSearchPaths(OwnerInfo^.IncDirs,OwnerInfo^.SrcDirs),'');
|
||||
OwnerInfo^.UnitOutDir:=TrimFilename(OwnerInfo^.UnitOutDir);
|
||||
OwnerInfo^.SrcDirs:=TrimSearchPath(OwnerInfo^.SrcDirs,'');
|
||||
OwnerInfo.IncDirs:=TrimSearchPath(RemoveSearchPaths(OwnerInfo.IncDirs,OwnerInfo.SrcDirs),'');
|
||||
OwnerInfo.UnitOutDir:=TrimFilename(OwnerInfo.UnitOutDir);
|
||||
OwnerInfo.SrcDirs:=TrimSearchPath(OwnerInfo.SrcDirs,'');
|
||||
end;
|
||||
|
||||
procedure CollectFilesInDir(OwnerInfo: POwnerInfo; Dir: string;
|
||||
var SearchedDirs: string);
|
||||
procedure CollectFilesInDir(OwnerInfo: TPGInterPkgOwnerInfo; Dir: string;
|
||||
var SearchedDirs: string; IsIncDir: boolean);
|
||||
var
|
||||
Files: TStrings;
|
||||
aFilename: String;
|
||||
Ext: String;
|
||||
AnUnitName: String;
|
||||
NewFile: TPGInterPkgFile;
|
||||
begin
|
||||
if Dir='' then exit;
|
||||
if not FilenameIsAbsolute(Dir) then
|
||||
begin
|
||||
debugln(['Inconsistency: CollectFilesInDir dir no absolute: "',Dir,'" Owner=',OwnerInfo^.Name]);
|
||||
debugln(['Inconsistency: CollectFilesInDir dir no absolute: "',Dir,'" Owner=',OwnerInfo.Name]);
|
||||
exit;
|
||||
end;
|
||||
if SearchDirectoryInSearchPath(SearchedDirs,Dir)>0 then exit;
|
||||
SearchedDirs+=';'+Dir;
|
||||
Files:=nil;
|
||||
try
|
||||
CodeToolBoss.DirectoryCachePool.GetListing(Dir,Files,false);
|
||||
@ -947,29 +981,194 @@ var
|
||||
begin
|
||||
if (aFilename='') or (aFilename='.') or (aFilename='..') then continue;
|
||||
Ext:=LowerCase(ExtractFileExt(aFilename));
|
||||
if Ext='.ppu' then ;
|
||||
AnUnitName:='';
|
||||
case Ext of
|
||||
'.ppu','.o','.pas','.pp','.p':
|
||||
if IsIncDir then
|
||||
begin
|
||||
AnUnitName:=ExtractFilename(aFilename);
|
||||
if not IsDottedIdentifier(AnUnitName) then continue;
|
||||
end;
|
||||
'.inc': ;
|
||||
else
|
||||
continue;
|
||||
end;
|
||||
NewFile:=TPGInterPkgFile.Create(AppendPathDelim(Dir)+aFilename,
|
||||
AnUnitName,OwnerInfo);
|
||||
FullFiles.Add(NewFile);
|
||||
ShortFiles.Add(NewFile);
|
||||
if AnUnitName<>'' then
|
||||
Units.Add(NewFile);
|
||||
end;
|
||||
finally
|
||||
Files.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CollectFilesOfOwner(OwnerInfo: POwnerInfo);
|
||||
procedure CollectFilesOfOwner(OwnerInfo: TPGInterPkgOwnerInfo);
|
||||
var
|
||||
SearchedDirs: String;
|
||||
SearchPath: String;
|
||||
p: Integer;
|
||||
Dir: String;
|
||||
begin
|
||||
// find all unit and include files in src, inc and out dirs
|
||||
// find all unit and include FullFiles in src, inc and out dirs
|
||||
SearchedDirs:='';
|
||||
SearchPath:=OwnerInfo^.SrcDirs+';'+OwnerInfo^.IncDirs+';'+OwnerInfo^.UnitOutDir;
|
||||
CollectFilesInDir(OwnerInfo,OwnerInfo.UnitOutDir,SearchedDirs,false);
|
||||
SearchPath:=OwnerInfo.SrcDirs;
|
||||
p:=1;
|
||||
repeat
|
||||
Dir:=GetNextDirectoryInSearchPath(SearchPath,p);
|
||||
if Dir='' then break;
|
||||
CollectFilesInDir(OwnerInfo,Dir,SearchedDirs);
|
||||
CollectFilesInDir(OwnerInfo,Dir,SearchedDirs,false);
|
||||
until false;
|
||||
SearchPath:=OwnerInfo.IncDirs;
|
||||
p:=1;
|
||||
repeat
|
||||
Dir:=GetNextDirectoryInSearchPath(SearchPath,p);
|
||||
if Dir='' then break;
|
||||
CollectFilesInDir(OwnerInfo,Dir,SearchedDirs,true);
|
||||
until false;
|
||||
end;
|
||||
|
||||
procedure RemoveSecondaryFiles;
|
||||
// remove each .o file if there is an .ppu file, so that there is only one
|
||||
// warning per ppu file
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
ONode: TAVLTreeNode;
|
||||
OFile: TPGInterPkgFile;
|
||||
PPUFileName: String;
|
||||
SearchFile: TPGInterPkgFile;
|
||||
PPUNode: TAVLTreeNode;
|
||||
begin
|
||||
Node:=Units.FindLowest;
|
||||
while Node<>nil do begin
|
||||
// for each .o file
|
||||
ONode:=Node;
|
||||
Node:=Units.FindSuccessor(Node);
|
||||
OFile:=TPGInterPkgFile(ONode.Data);
|
||||
if CompareFileExt(OFile.ShortFilename,'o')<>0 then continue;
|
||||
// search corresponding .ppu
|
||||
PPUFileName:=ChangeFileExt(OFile.FullFilename,'.ppu');
|
||||
SearchFile:=TPGInterPkgFile.Create(PPUFileName,'',nil);
|
||||
PPUNode:=FullFiles.Find(SearchFile);
|
||||
SearchFile.Free;
|
||||
if PPUNode=nil then continue;
|
||||
// remove .o file
|
||||
Units.RemovePointer(OFile);
|
||||
ShortFiles.RemovePointer(OFile);
|
||||
FullFiles.Delete(ONode);
|
||||
end;
|
||||
end;
|
||||
|
||||
function OwnerHasDependency(Owner1, Owner2: TPGInterPkgOwnerInfo): boolean;
|
||||
// returns true if Owner1 depends on Owner2
|
||||
begin
|
||||
if Owner1=Owner2 then exit(true);
|
||||
if Owner1.Owner is TLazPackage then
|
||||
begin
|
||||
if Owner2.Owner is TLazPackage then
|
||||
begin
|
||||
Result:=FindDependencyRecursively(
|
||||
TLazPackage(Owner1.Owner).FirstRequiredDependency,
|
||||
TLazPackage(Owner2.Owner))<>nil;
|
||||
end else begin
|
||||
// Owner1 is package, Owner2 is project/IDE => not possible
|
||||
Result:=false;
|
||||
end;
|
||||
end else begin
|
||||
// Owner1 is project or IDE => true
|
||||
Result:=true;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CheckPPUFilesInWrongDirs;
|
||||
{ Check if a ppu/o of pkg A has a unit (source or ppu) in another package B
|
||||
Unless A uses B and B has -Ur or A has -Ur and B uses A
|
||||
=> IDE: delete+retry or ignore or cancel
|
||||
=> lazbuild: warn }
|
||||
var
|
||||
CurNode: TAVLTreeNode;
|
||||
CurFile: TPGInterPkgFile;
|
||||
Ext: String;
|
||||
FirstNodeSameUnitname: TAVLTreeNode;
|
||||
OtherNode: TAVLTreeNode;
|
||||
OtherFile: TPGInterPkgFile;
|
||||
SrcFileNode: TAVLTreeNode;
|
||||
SrcFile: TPGInterPkgFile;
|
||||
begin
|
||||
CurNode:=Units.FindLowest;
|
||||
FirstNodeSameUnitname:=nil;
|
||||
while CurNode<>nil do begin
|
||||
CurFile:=TPGInterPkgFile(CurNode.Data);
|
||||
if (FirstNodeSameUnitname=nil)
|
||||
or (ComparePGInterPkgUnitnames(CurFile,FirstNodeSameUnitname)<>0) then
|
||||
FirstNodeSameUnitname:=CurNode;
|
||||
CurNode:=Units.FindSuccessor(CurNode);
|
||||
Ext:=lowercase(ExtractFileExt(CurFile.ShortFilename));
|
||||
if (Ext<>'.ppu') and (Ext<>'.o') then continue;
|
||||
// check units with same name
|
||||
OtherNode:=FirstNodeSameUnitname;
|
||||
while (OtherNode<>nil) do begin
|
||||
OtherFile:=TPGInterPkgFile(OtherNode.Data);
|
||||
if (ComparePGInterPkgUnitnames(CurFile,OtherFile)<>0) then break;
|
||||
// other unit with same name found
|
||||
OtherNode:=Units.FindSuccessor(OtherNode);
|
||||
if OtherFile.OwnerInfo=CurFile.OwnerInfo then continue;
|
||||
// ppu in one package, unit with same name in another package
|
||||
debugln(['CheckPPUFilesInWrongDirs duplicate units found: file1="',CurFile.FullFilename,'"(',CurFile.OwnerInfo.Name,') file2="',OtherFile.FullFilename,'"(',OtherFile.OwnerInfo.Name,')']);
|
||||
if CurFile.OwnerInfo.HasOptionUr
|
||||
and OtherFile.OwnerInfo.HasOptionUr then
|
||||
continue;
|
||||
if CurFile.OwnerInfo.HasOptionUr
|
||||
and OwnerHasDependency(OtherFile.OwnerInfo,CurFile.OwnerInfo) then
|
||||
continue;
|
||||
if OtherFile.OwnerInfo.HasOptionUr
|
||||
and OwnerHasDependency(CurFile.OwnerInfo,OtherFile.OwnerInfo) then
|
||||
continue;
|
||||
// check if this package has a source for this ppu
|
||||
SrcFileNode:=FirstNodeSameUnitname;
|
||||
SrcFile:=nil;
|
||||
while SrcFileNode<>nil do begin
|
||||
SrcFile:=TPGInterPkgFile(SrcFileNode.Data);
|
||||
if (ComparePGInterPkgUnitnames(CurFile,SrcFile)<>0) then
|
||||
begin
|
||||
SrcFileNode:=nil;
|
||||
break;
|
||||
end;
|
||||
SrcFileNode:=Units.FindSuccessor(SrcFileNode);
|
||||
if SrcFile.OwnerInfo<>CurFile.OwnerInfo then continue;
|
||||
if FilenameIsPascalUnit(SrcFile.ShortFilename) then
|
||||
break;
|
||||
end;
|
||||
if SrcFileNode<>nil then
|
||||
begin
|
||||
// ppu with src in one package, duplicate unit in another package
|
||||
// Note: This could be right if the other package does not use the src file
|
||||
// Otherwise: duplicate name (-Ur has been checked)
|
||||
// ToDo: => warn
|
||||
debugln(['CheckPPUFilesInWrongDirs duplicate units found: file1="',CurFile.FullFilename,'"(',CurFile.OwnerInfo.Name,',source=',SrcFile.ShortFilename,') file2="',OtherFile.FullFilename,'"(',OtherFile.OwnerInfo.Name,')']);
|
||||
|
||||
end else begin
|
||||
// ppu with no src in one package, duplicate unit in another package
|
||||
// (-Ur has been checked)
|
||||
// => highly unlikely that this is right
|
||||
// ToDo: => warn
|
||||
debugln(['CheckPPUFilesInWrongDirs duplicate units found: file1="',CurFile.FullFilename,'"(',CurFile.OwnerInfo.Name,',no source) file2="',OtherFile.FullFilename,'"(',OtherFile.OwnerInfo.Name,')']);
|
||||
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CheckDuplicateSrcFiles;
|
||||
{ Check if a src file in pkg A with the same short name exist in another package B
|
||||
Unless A uses B and B has -Ur or A has -Ur and B uses A
|
||||
=> IDE: ignore or cancel
|
||||
=> lazbuild: warn }
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
var
|
||||
@ -977,7 +1176,10 @@ var
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if (PkgList=nil) or (PkgList.Count=0) then exit;
|
||||
Files:=TAVLTree.Create(@ComparePGInterPkgFullFilenames);
|
||||
OwnerInfos:=TObjectList.create(true);
|
||||
FullFiles:=TAVLTree.Create(@ComparePGInterPkgFullFilenames);
|
||||
Units:=TAVLTree.Create(@ComparePGInterPkgUnitnames);
|
||||
ShortFiles:=TAVLTree.Create(@ComparePGInterPkgShortFilename);
|
||||
try
|
||||
// get target OS, CPU and LCLWidgetType
|
||||
TargetOS:='$(TargetOS)';
|
||||
@ -991,17 +1193,24 @@ begin
|
||||
if LCLWidgetType='' then LCLWidgetType:=LCLPlatformDirNames[GetDefaultLCLWidgetType];
|
||||
|
||||
// get search paths
|
||||
SetLength(OwnerInfos,PkgList.Count+1);
|
||||
InitOwnerInfo(@OwnerInfos[0],IDEObject);
|
||||
for i:=1 to PkgList.Count do
|
||||
InitOwnerInfo(@OwnerInfos[i],TObject(PkgList[i-1]));
|
||||
AddOwnerInfo(IDEObject);
|
||||
for i:=0 to PkgList.Count-1 do
|
||||
AddOwnerInfo(TObject(PkgList[i]));
|
||||
|
||||
// collect files
|
||||
for i:=0 to length(OwnerInfos)-1 do
|
||||
CollectFilesOfOwner(@OwnerInfos[i]);
|
||||
// collect FullFiles
|
||||
for i:=0 to OwnerInfos.Count-1 do
|
||||
CollectFilesOfOwner(TPGInterPkgOwnerInfo(OwnerInfos[i]));
|
||||
RemoveSecondaryFiles;
|
||||
|
||||
// checks
|
||||
CheckPPUFilesInWrongDirs;
|
||||
CheckDuplicateSrcFiles;
|
||||
finally
|
||||
Files.FreeAndClear;
|
||||
Files.Free;
|
||||
Units.Free;
|
||||
ShortFiles.Free;
|
||||
FullFiles.FreeAndClear;
|
||||
FullFiles.Free;
|
||||
OwnerInfos.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1448,6 +1657,7 @@ function TLazPackageGraph.FindDependencyRecursively(
|
||||
end;
|
||||
|
||||
begin
|
||||
if FirstDependency=nil then exit(nil);
|
||||
MarkAllPackagesAsNotVisited;
|
||||
Result:=Find(FirstDependency);
|
||||
end;
|
||||
@ -1479,6 +1689,7 @@ function TLazPackageGraph.FindDependencyRecursively(
|
||||
end;
|
||||
|
||||
begin
|
||||
if FirstDependency=nil then exit(nil);
|
||||
MarkAllPackagesAsNotVisited;
|
||||
Result:=Find(FirstDependency);
|
||||
end;
|
||||
@ -1511,6 +1722,7 @@ function TLazPackageGraph.FindConflictRecursively(
|
||||
end;
|
||||
|
||||
begin
|
||||
if FirstDependency=nil then exit(nil);
|
||||
MarkAllPackagesAsNotVisited;
|
||||
Result:=Find(FirstDependency);
|
||||
end;
|
||||
@ -1540,6 +1752,7 @@ function TLazPackageGraph.FindRuntimePkgOnlyRecursively(
|
||||
end;
|
||||
|
||||
begin
|
||||
if FirstDependency=nil then exit(nil);
|
||||
MarkAllPackagesAsNotVisited;
|
||||
Result:=Find(FirstDependency);
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user