mirror of https://gitlab.com/basile.b/dexed.git
libman, use hashset and hash map to speed up the selection of the items, close #77
This commit is contained in:
parent
94eddd0ca8
commit
e1846a9466
|
|
@ -15,7 +15,7 @@ uses
|
||||||
{$IFNDEF CEBUILD}
|
{$IFNDEF CEBUILD}
|
||||||
forms,
|
forms,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
process, asyncprocess;
|
process, asyncprocess, ghashmap, ghashset;
|
||||||
|
|
||||||
const
|
const
|
||||||
exeExt = {$IFDEF WINDOWS} '.exe' {$ELSE} '' {$ENDIF};
|
exeExt = {$IFDEF WINDOWS} '.exe' {$ELSE} '' {$ENDIF};
|
||||||
|
|
@ -31,6 +31,21 @@ type
|
||||||
|
|
||||||
TCECompiler = (dmd, gdc, ldc);
|
TCECompiler = (dmd, gdc, ldc);
|
||||||
|
|
||||||
|
// function used as hash in gXXX sets & maps
|
||||||
|
TStringHash = class
|
||||||
|
class function hash(const key: string; maxBucketsPow2: longint): longint;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// HashMap for TValue by string
|
||||||
|
generic TStringHashMap<TValue> = class(specialize THashmap<string, TValue, TStringHash>);
|
||||||
|
|
||||||
|
// function used as objects in gXXX sets & maps
|
||||||
|
TObjectHash = class
|
||||||
|
class function hash(key: TObject; maxBucketsPow2: longint): longint;
|
||||||
|
end;
|
||||||
|
|
||||||
|
generic TObjectHashSet<TValue> = class(specialize THashSet<TValue, TObjectHash>);
|
||||||
|
|
||||||
// aliased to get a custom prop inspector
|
// aliased to get a custom prop inspector
|
||||||
TCEPathname = type string;
|
TCEPathname = type string;
|
||||||
TCEFilename = type string;
|
TCEFilename = type string;
|
||||||
|
|
@ -280,6 +295,32 @@ implementation
|
||||||
uses
|
uses
|
||||||
ce_main;
|
ce_main;
|
||||||
|
|
||||||
|
|
||||||
|
class function TStringHash.hash(const key: string; maxBucketsPow2: longint): longint;
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
{$PUSH}{$R-}
|
||||||
|
result := 5381;
|
||||||
|
for i:= 1 to key.length do
|
||||||
|
begin
|
||||||
|
result := ((result shl 5) + result) + Byte(key[i]);
|
||||||
|
end;
|
||||||
|
result := result and (maxBucketsPow2-1);
|
||||||
|
{$POP}
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TObjectHash.hash(key: TObject; maxBucketsPow2: longint): longint;
|
||||||
|
begin
|
||||||
|
{$PUSH}{$R-}{$WARNINGS OFF}{$HINTS OFF}
|
||||||
|
{$IFDEF CPU32}
|
||||||
|
Result := longint(Pointer(key)) and (maxBucketsPow2 -1);
|
||||||
|
{$ELSE}
|
||||||
|
Result := (longInt(Pointer(key)) xor PlongInt(PInteger(&key) + 4)^) and (maxBucketsPow2 -1);
|
||||||
|
{$ENDIF}
|
||||||
|
{$POP}
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCEPersistentShortcut.assign(aValue: TPersistent);
|
procedure TCEPersistentShortcut.assign(aValue: TPersistent);
|
||||||
var
|
var
|
||||||
src: TCEPersistentShortcut;
|
src: TCEPersistentShortcut;
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,17 @@ interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, FileUtil, ce_common, ce_writableComponent, ce_dcd, LazFileUtils,
|
Classes, SysUtils, FileUtil, ce_common, ce_writableComponent, ce_dcd, LazFileUtils,
|
||||||
ce_dialogs, ce_projutils, ce_interfaces, ce_dlang;
|
ce_dialogs, ce_projutils, ce_interfaces, ce_dlang, ghashmap, ghashset;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
// TODO-clibman: improve import analysis, caching, hashmap, backup, update.
|
// TODO-clibman: improve import analysis, update (currently always full).
|
||||||
|
|
||||||
(**
|
(**
|
||||||
* Information for a module in a library manager entry
|
* Information for a module in a library manager entry
|
||||||
*)
|
*)
|
||||||
TModuleInfo = class(TCollectionItem)
|
TModuleInfo = class(TCollectionItem)
|
||||||
private
|
strict private
|
||||||
fName: string;
|
fName: string;
|
||||||
fImports: TStringList;
|
fImports: TStringList;
|
||||||
procedure setImports(value: TStringList);
|
procedure setImports(value: TStringList);
|
||||||
|
|
@ -32,73 +32,100 @@ type
|
||||||
|
|
||||||
|
|
||||||
(**
|
(**
|
||||||
* Represents a D static library. In a project libAlias allows to
|
* Represents a D static library.
|
||||||
* resolve automatically the dependencies of a project.
|
|
||||||
*)
|
*)
|
||||||
TLibraryItem = class(TCollectionItem)
|
TLibraryItem = class(TCollectionItem)
|
||||||
private
|
type
|
||||||
|
TModulesByName = specialize TStringHashMap<TModuleInfo>;
|
||||||
|
strict private
|
||||||
fAlias: string;
|
fAlias: string;
|
||||||
fSourcePath: string;
|
fLibSourcePath: string;
|
||||||
fLibFile: string;
|
fLibFile: string;
|
||||||
fProjFile: string;
|
fLibProject: string;
|
||||||
fEnabled: boolean;
|
fEnabled: boolean;
|
||||||
fDependencies: TStringList;
|
fDependencies: TStringList;
|
||||||
fModules: TCollection;
|
fModules: TCollection;
|
||||||
|
fModulesByName: TModulesByName;
|
||||||
|
fHasValidSourcePath: boolean;
|
||||||
|
fHasValidLibFile: boolean;
|
||||||
|
fHasValidLibProject: boolean;
|
||||||
procedure setDependencies(value: TStringList);
|
procedure setDependencies(value: TStringList);
|
||||||
procedure setModules(value: TCollection);
|
procedure setModules(value: TCollection);
|
||||||
function getModuleInfo(ix: integer): TModuleInfo;
|
procedure setLibProject(const value: string);
|
||||||
|
procedure setLibFile(const value: string);
|
||||||
|
procedure setLibSourcePath(const value: string);
|
||||||
|
function getModule(value: integer): TModuleInfo;
|
||||||
|
function getModule(const value: string): TModuleInfo;
|
||||||
|
function moduleCount: integer;
|
||||||
published
|
published
|
||||||
property libAlias: string read fAlias write fAlias;
|
property libAlias: string read fAlias write fAlias;
|
||||||
property libSourcePath: string read fSourcePath write fSourcePath;
|
property libSourcePath: string read fLibSourcePath write setLibSourcePath;
|
||||||
property libFile: string read fLibFile write fLibFile;
|
property libFile: string read fLibFile write setLibFile;
|
||||||
property projectFile: string read fProjFile write fProjFile;
|
property libProject: string read fLibProject write setLibProject;
|
||||||
property enabled: boolean read fEnabled write fEnabled default true;
|
property enabled: boolean read fEnabled write fEnabled default true;
|
||||||
// TODO-clibman: dont forget that these props are not written
|
// TODO-clibman: dont forget that these props are not written
|
||||||
property dependencies: TStringList read fDependencies write setDependencies stored false;
|
property dependencies: TStringList read fDependencies write setDependencies stored false;
|
||||||
property modules: TCollection read fModules write setModules stored false;
|
property modules: TCollection read fModules write setModules stored false;
|
||||||
|
// TODO-cmaintenace: remove this property from 3 update 1
|
||||||
|
property projectFile: string read fLibProject write fLibProject stored false;
|
||||||
public
|
public
|
||||||
constructor Create(ACollection: TCollection); override;
|
constructor Create(ACollection: TCollection); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure updateModulesInfo;
|
procedure updateModulesInfo;
|
||||||
function addModuleInfo: TModuleInfo;
|
function addModuleInfo: TModuleInfo;
|
||||||
function hasModule(const value: string): boolean;
|
function hasModule(const value: string): boolean;
|
||||||
property moduleInfos[ix: integer]: TModuleInfo read getModuleInfo;
|
property hasValidLibFile: boolean read fHasValidLibFile;
|
||||||
|
property hasValidLibProject: boolean read fHasValidLibProject;
|
||||||
|
property hasValidLibSourcePath: boolean read fHasValidSourcePath;
|
||||||
|
property moduleByIndex[value: integer]: TModuleInfo read getModule;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TLibraryList = specialize TObjectHashSet<TLibraryItem>;
|
||||||
|
|
||||||
(**
|
(**
|
||||||
* Represents all the D libraries present on this system.
|
* Represents all the D libraries handled by Coedit.
|
||||||
*)
|
*)
|
||||||
TLibraryManager = class(TWritableLfmTextComponent)
|
TLibraryManager = class(TWritableLfmTextComponent)
|
||||||
private
|
type
|
||||||
fCol: TCollection;
|
TItemsByAlias = specialize TStringHashMap<TLibraryItem>;
|
||||||
function getItems(index: integer): TLibraryItem;
|
strict private
|
||||||
procedure setCol(value: TCollection);
|
fCollection: TCollection;
|
||||||
|
fItemsByAlias: TItemsByAlias;
|
||||||
|
function getLibraryByIndex(index: integer): TLibraryItem;
|
||||||
|
function getLibraryByAlias(const value: string): TLibraryItem;
|
||||||
|
function getLibraryByImport(const value: string): TLibraryItem;
|
||||||
|
procedure setCollection(value: TCollection);
|
||||||
|
procedure updateItemsByAlias;
|
||||||
|
function getLibrariesCount: integer;
|
||||||
published
|
published
|
||||||
property libraries: TCollection read fCol write setCol;
|
property libraries: TCollection read fCollection write setCollection;
|
||||||
public
|
public
|
||||||
constructor create(aOwner: TComponent); override;
|
constructor create(aOwner: TComponent); override;
|
||||||
destructor destroy; override;
|
destructor destroy; override;
|
||||||
(**
|
(**
|
||||||
* The caller gets all the static library files in list if aliases is nil
|
* The caller gets all the static library files in "list" if "aliases" is nil
|
||||||
* otherwise the static library files selected by the aliases.
|
* otherwise the static library files selected by "aliases".
|
||||||
*)
|
*)
|
||||||
procedure getLibFiles(aliases, list: TStrings);
|
procedure getLibFiles(aliases, list: TStrings);
|
||||||
(**
|
(**
|
||||||
* The caller gets all the paths were are located the library sources in list
|
* The caller gets all the paths were are located the library sources in "list"
|
||||||
* if aliases is nil otherwise the paths where are located the sources of the
|
* if "aliases" is nil otherwise the paths where are located the sources of the
|
||||||
* livraries selected by aliases.
|
* libraries selected by "aliases".
|
||||||
*)
|
*)
|
||||||
procedure getLibSources(aliases, list: TStrings);
|
procedure getLibSourcePath(aliases, list: TStrings);
|
||||||
(**
|
(**
|
||||||
* The caller gets all the static library files and the source path
|
* The caller gets static libraries files in "libs" and source paths
|
||||||
* that are required by the specified source code.
|
* in "paths", as required by the specified "source" code.
|
||||||
*)
|
*)
|
||||||
procedure getLibsForSource(source, libs, paths: TStrings);
|
procedure getLibsForSource(source, libs, paths: TStrings);
|
||||||
//
|
//
|
||||||
procedure updateDCD;
|
procedure updateDCD;
|
||||||
// find the aliases of the libraries used by this library.
|
// find the aliases of the libraries used by this library.
|
||||||
procedure updateCrossDependencies;
|
procedure updateCrossDependencies;
|
||||||
property items[index: integer]: TLibraryItem read getItems; default;
|
property librariesCount: integer read getLibrariesCount;
|
||||||
|
property libraryByIndex[value: integer]: TLibraryItem read getLibraryByIndex;
|
||||||
|
property libraryByAlias[const value: string]: TLibraryItem read getLibraryByAlias;
|
||||||
|
property libraryByImport[const value: string]: TLibraryItem read getLibraryByImport;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -130,20 +157,32 @@ constructor TLibraryItem.Create(ACollection: TCollection);
|
||||||
begin
|
begin
|
||||||
inherited create(ACollection);
|
inherited create(ACollection);
|
||||||
fModules := TCollection.Create(TModuleInfo);
|
fModules := TCollection.Create(TModuleInfo);
|
||||||
|
fModulesByName := TModulesByName.create;
|
||||||
fDependencies := TStringList.Create;
|
fDependencies := TStringList.Create;
|
||||||
fEnabled:=true;
|
fEnabled:=true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TLibraryItem.Destroy;
|
destructor TLibraryItem.Destroy;
|
||||||
begin
|
begin
|
||||||
|
fModulesByName.Free;
|
||||||
fDependencies.Free;
|
fDependencies.Free;
|
||||||
fModules.Free;
|
fModules.Free;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLibraryItem.getModuleInfo(ix: integer): TModuleInfo;
|
function TLibraryItem.moduleCount: integer;
|
||||||
begin
|
begin
|
||||||
exit(TModuleInfo(fModules.Items[ix]));
|
exit(fModules.Count);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLibraryItem.getModule(value: integer): TModuleInfo;
|
||||||
|
begin
|
||||||
|
exit(TModuleInfo(fModules.Items[value]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLibraryItem.getModule(const value: string): TModuleInfo;
|
||||||
|
begin
|
||||||
|
exit(fModulesByName.GetData(value));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLibraryItem.addModuleInfo: TModuleInfo;
|
function TLibraryItem.addModuleInfo: TModuleInfo;
|
||||||
|
|
@ -152,13 +191,8 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLibraryItem.hasModule(const value: string): boolean;
|
function TLibraryItem.hasModule(const value: string): boolean;
|
||||||
var
|
|
||||||
i: integer;
|
|
||||||
begin
|
begin
|
||||||
for i:= 0 to fModules.Count-1 do
|
exit(fModulesByName.contains(value));
|
||||||
if getModuleInfo(i).name = value then
|
|
||||||
exit(true);
|
|
||||||
exit(false);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLibraryItem.setModules(value: TCollection);
|
procedure TLibraryItem.setModules(value: TCollection);
|
||||||
|
|
@ -171,6 +205,30 @@ begin
|
||||||
fDependencies.Assign(value);
|
fDependencies.Assign(value);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TLibraryItem.setLibProject(const value: string);
|
||||||
|
begin
|
||||||
|
if fLibProject = value then
|
||||||
|
exit;
|
||||||
|
fLibProject:=value;
|
||||||
|
fHasValidLibProject:=value.fileExists;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLibraryItem.setLibFile(const value: string);
|
||||||
|
begin
|
||||||
|
if fLibFile = value then
|
||||||
|
exit;
|
||||||
|
fLibFile:=value;
|
||||||
|
fHasValidLibFile:=value.fileExists or value.dirExists;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TLibraryItem.setLibSourcePath(const value: string);
|
||||||
|
begin
|
||||||
|
if fLibSourcePath = value then
|
||||||
|
exit;
|
||||||
|
fLibSourcePath:=value;
|
||||||
|
fHasValidSourcePath:=value.dirExists;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TLibraryItem.updateModulesInfo;
|
procedure TLibraryItem.updateModulesInfo;
|
||||||
var
|
var
|
||||||
prj: ICECommonProject;
|
prj: ICECommonProject;
|
||||||
|
|
@ -182,9 +240,11 @@ var
|
||||||
i: integer;
|
i: integer;
|
||||||
begin
|
begin
|
||||||
fModules.Clear;
|
fModules.Clear;
|
||||||
if fProjFile.fileExists then
|
fModulesByName.Free;
|
||||||
|
fModulesByName := TModulesByName.create;
|
||||||
|
if hasValidLibProject then
|
||||||
begin
|
begin
|
||||||
prj := loadProject(fProjFile, true);
|
prj := loadProject(fLibProject, true);
|
||||||
tks := TLexTokenList.Create;
|
tks := TLexTokenList.Create;
|
||||||
str := TStringList.Create;
|
str := TStringList.Create;
|
||||||
try
|
try
|
||||||
|
|
@ -198,6 +258,7 @@ begin
|
||||||
lex(str.Text, tks, nil, [lxoNoComments]);
|
lex(str.Text, tks, nil, [lxoNoComments]);
|
||||||
mdi := addModuleInfo;
|
mdi := addModuleInfo;
|
||||||
mdi.name := getModuleName(tks);
|
mdi.name := getModuleName(tks);
|
||||||
|
fModulesByName.insert(mdi.name, mdi);
|
||||||
getImports(tks, mdi.imports);
|
getImports(tks, mdi.imports);
|
||||||
tks.Clear;
|
tks.Clear;
|
||||||
end;
|
end;
|
||||||
|
|
@ -206,13 +267,13 @@ begin
|
||||||
str.Free;
|
str.Free;
|
||||||
prj.getProject.Free;
|
prj.getProject.Free;
|
||||||
end;
|
end;
|
||||||
end else if fSourcePath.dirExists then
|
end else if hasValidLibSourcePath then
|
||||||
begin
|
begin
|
||||||
lst := TStringList.Create;
|
lst := TStringList.Create;
|
||||||
str := TStringList.Create;
|
str := TStringList.Create;
|
||||||
tks := TLexTokenList.Create;
|
tks := TLexTokenList.Create;
|
||||||
try
|
try
|
||||||
listFiles(lst, fSourcePath, true);
|
listFiles(lst, fLibSourcePath, true);
|
||||||
for i := 0 to lst.Count-1 do
|
for i := 0 to lst.Count-1 do
|
||||||
begin
|
begin
|
||||||
fle := lst[i];
|
fle := lst[i];
|
||||||
|
|
@ -222,6 +283,7 @@ begin
|
||||||
lex(str.Text, tks, nil, [lxoNoComments]);
|
lex(str.Text, tks, nil, [lxoNoComments]);
|
||||||
mdi := addModuleInfo;
|
mdi := addModuleInfo;
|
||||||
mdi.name := getModuleName(tks);
|
mdi.name := getModuleName(tks);
|
||||||
|
fModulesByName.insert(mdi.name, mdi);
|
||||||
getImports(tks, mdi.imports);
|
getImports(tks, mdi.imports);
|
||||||
tks.Clear;
|
tks.Clear;
|
||||||
end;
|
end;
|
||||||
|
|
@ -242,11 +304,12 @@ var
|
||||||
i: integer;
|
i: integer;
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
fCol := TCollection.Create(TLibraryItem);
|
fItemsByAlias:= TItemsByAlias.create;
|
||||||
|
fCollection := TCollection.Create(TLibraryItem);
|
||||||
fname := getCoeditDocPath + libFname;
|
fname := getCoeditDocPath + libFname;
|
||||||
if fname.fileExists then
|
if fname.fileExists then
|
||||||
loadFromFile(fname);
|
loadFromFile(fname);
|
||||||
if fCol.Count = 0 then
|
if fCollection.Count = 0 then
|
||||||
begin
|
begin
|
||||||
{$IFDEF WINDOWS}
|
{$IFDEF WINDOWS}
|
||||||
fDmdPath := ExeSearch('dmd.exe');
|
fDmdPath := ExeSearch('dmd.exe');
|
||||||
|
|
@ -274,16 +337,16 @@ begin
|
||||||
// add phobos
|
// add phobos
|
||||||
if '/usr/include/dmd/phobos'.dirExists then
|
if '/usr/include/dmd/phobos'.dirExists then
|
||||||
begin
|
begin
|
||||||
with TLibraryItem(fCol.Add) do begin
|
with TLibraryItem(fCollection.Add) do begin
|
||||||
libAlias := 'phobos';
|
libAlias := 'phobos';
|
||||||
libFile := '';
|
libFile := '';
|
||||||
libSourcePath := '/usr/include/dmd/phobos';
|
libSourcePath := '/usr/include/dmd/phobos';
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
// add druntime (no items - only for DCD)
|
// add druntime (no libraryByIndex - only for DCD)
|
||||||
if '/usr/include/dmd/druntime/import'.dirExists then
|
if '/usr/include/dmd/druntime/import'.dirExists then
|
||||||
begin
|
begin
|
||||||
with TLibraryItem(fCol.Add) do begin
|
with TLibraryItem(fCollection.Add) do begin
|
||||||
libAlias := 'druntime';
|
libAlias := 'druntime';
|
||||||
libFile := '';
|
libFile := '';
|
||||||
libSourcePath := '/usr/include/dmd/druntime/import';
|
libSourcePath := '/usr/include/dmd/druntime/import';
|
||||||
|
|
@ -310,7 +373,8 @@ begin
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
if (fCol.Count = 0) and not (getCoeditDocPath + libFname).fileExists then
|
updateItemsByAlias;
|
||||||
|
if (fCollection.Count = 0) and not (getCoeditDocPath + libFname).fileExists then
|
||||||
begin
|
begin
|
||||||
dlgOkInfo(
|
dlgOkInfo(
|
||||||
'Coedit failed to add "druntime" and "phobos" to the library manager.'
|
'Coedit failed to add "druntime" and "phobos" to the library manager.'
|
||||||
|
|
@ -319,10 +383,10 @@ begin
|
||||||
end;
|
end;
|
||||||
updateDCD;
|
updateDCD;
|
||||||
//
|
//
|
||||||
for i := 0 to fCol.Count-1 do
|
for i := 0 to fCollection.Count-1 do
|
||||||
begin
|
begin
|
||||||
if (items[i].libAlias <> 'phobos') and (items[i].libAlias <> 'druntime') then
|
if (libraryByIndex[i].libAlias <> 'phobos') and (libraryByIndex[i].libAlias <> 'druntime') then
|
||||||
items[i].updateModulesInfo;
|
libraryByIndex[i].updateModulesInfo;
|
||||||
end;
|
end;
|
||||||
updateCrossDependencies;
|
updateCrossDependencies;
|
||||||
end;
|
end;
|
||||||
|
|
@ -331,18 +395,53 @@ destructor TLibraryManager.destroy;
|
||||||
begin
|
begin
|
||||||
ForceDirectoriesUTF8(getCoeditDocPath);
|
ForceDirectoriesUTF8(getCoeditDocPath);
|
||||||
LibMan.saveToFile(getCoeditDocPath + libFname);
|
LibMan.saveToFile(getCoeditDocPath + libFname);
|
||||||
fCol.Free;
|
fItemsByAlias.Free;
|
||||||
|
fCollection.Free;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLibraryManager.setCol(value: TCollection);
|
procedure TLibraryManager.updateItemsByAlias;
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
begin
|
begin
|
||||||
fCol.assign(value);
|
fItemsByAlias.Free;
|
||||||
|
fItemsByAlias := TItemsByAlias.create;
|
||||||
|
for i:= 0 to fCollection.Count-1 do
|
||||||
|
fItemsByAlias.insert(libraryByIndex[i].libAlias, libraryByIndex[i]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLibraryManager.getItems(index: integer): TLibraryItem;
|
procedure TLibraryManager.setCollection(value: TCollection);
|
||||||
begin
|
begin
|
||||||
exit(TLibraryItem(fCol.Items[index]));
|
fCollection.assign(value);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLibraryManager.getLibraryByIndex(index: integer): TLibraryItem;
|
||||||
|
begin
|
||||||
|
exit(TLibraryItem(fCollection.Items[index]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLibraryManager.getLibraryByAlias(const value: string): TLibraryItem;
|
||||||
|
begin
|
||||||
|
exit(fItemsByAlias.GetData(value));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLibraryManager.getLibraryByImport(const value: string): TLibraryItem;
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
s: TLibraryItem;
|
||||||
|
begin
|
||||||
|
result := nil;
|
||||||
|
for i := 0 to librariesCount-1 do
|
||||||
|
begin
|
||||||
|
s := libraryByIndex[i];
|
||||||
|
if s.hasModule(value) then
|
||||||
|
exit(s);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TLibraryManager.getLibrariesCount: integer;
|
||||||
|
begin
|
||||||
|
exit(fCollection.Count);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLibraryManager.updateDCD;
|
procedure TLibraryManager.updateDCD;
|
||||||
|
|
@ -352,12 +451,12 @@ var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
if not DcdWrapper.available then exit;
|
if not DcdWrapper.available then exit;
|
||||||
// note: new items are directly handled but removed ones still in cache until server restarts.
|
// note: new libraryByIndex are directly handled but removed ones still in cache until server restarts.
|
||||||
str := TStringList.Create;
|
str := TStringList.Create;
|
||||||
try
|
try
|
||||||
for i := 0 to fCol.Count-1 do
|
for i := 0 to fCollection.Count-1 do
|
||||||
begin
|
begin
|
||||||
itm := TLibraryItem(fCol.Items[i]);
|
itm := TLibraryItem(fCollection.Items[i]);
|
||||||
if itm.enabled then
|
if itm.enabled then
|
||||||
str.Add(itm.libSourcePath);
|
str.Add(itm.libSourcePath);
|
||||||
end;
|
end;
|
||||||
|
|
@ -368,32 +467,20 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLibraryManager.getLibFiles(aliases, list: TStrings);
|
procedure TLibraryManager.getLibFiles(aliases, list: TStrings);
|
||||||
var
|
procedure add(lib: TLibraryItem);
|
||||||
itm: TLibraryItem;
|
var
|
||||||
lst: TStringList;
|
j: integer;
|
||||||
i,j: Integer;
|
dir: string;
|
||||||
dir: string;
|
lst: TstringList;
|
||||||
begin
|
|
||||||
for i := 0 to fCol.Count-1 do
|
|
||||||
begin
|
begin
|
||||||
itm := TLibraryItem(fCol.Items[i]);
|
// as a trick a folder can be set as source, this allows to pass
|
||||||
if (not itm.enabled) or
|
// multiple sources in an automated way.
|
||||||
(aliases.isNotNil and (aliases.IndexOf(itm.libAlias) = -1)) then
|
if lib.libFile.dirExists then
|
||||||
continue;
|
|
||||||
// single items files
|
|
||||||
if fileExists(itm.libFile) then
|
|
||||||
begin
|
|
||||||
if list.IndexOf(itm.libFile) <> -1 then
|
|
||||||
continue;
|
|
||||||
list.Add(itm.libFile);
|
|
||||||
end
|
|
||||||
// folder of items file
|
|
||||||
else if itm.libFile.dirExists then
|
|
||||||
begin
|
begin
|
||||||
lst := TStringList.Create;
|
lst := TStringList.Create;
|
||||||
try
|
try
|
||||||
dir := itm.libFile;
|
dir := lib.libFile;
|
||||||
if itm.libFile[dir.length] = DirectorySeparator then
|
if lib.libFile[dir.length] = DirectorySeparator then
|
||||||
dir := dir[1..dir.length-1];
|
dir := dir[1..dir.length-1];
|
||||||
listFiles(lst, dir);
|
listFiles(lst, dir);
|
||||||
for j:= 0 to lst.Count-1 do
|
for j:= 0 to lst.Count-1 do
|
||||||
|
|
@ -405,27 +492,57 @@ begin
|
||||||
finally
|
finally
|
||||||
lst.Free;
|
lst.Free;
|
||||||
end;
|
end;
|
||||||
|
end
|
||||||
|
else if lib.hasValidLibFile then
|
||||||
|
list.Add(lib.libFile);
|
||||||
|
end;
|
||||||
|
var
|
||||||
|
lib: TLibraryItem;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
// no selector = all libs
|
||||||
|
if aliases.isNil then
|
||||||
|
begin
|
||||||
|
for i:= 0 to librariesCount-1 do
|
||||||
|
begin
|
||||||
|
lib := libraryByIndex[i];
|
||||||
|
if lib.enabled then
|
||||||
|
add(lib);
|
||||||
end;
|
end;
|
||||||
|
end
|
||||||
|
// else get selected libs
|
||||||
|
else for i := 0 to aliases.Count-1 do
|
||||||
|
begin
|
||||||
|
lib := libraryByAlias[aliases[i]];
|
||||||
|
if lib.isNotNil and lib.enabled then
|
||||||
|
add(lib);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLibraryManager.getLibSources(aliases, list: TStrings);
|
procedure TLibraryManager.getLibSourcePath(aliases, list: TStrings);
|
||||||
var
|
var
|
||||||
itm: TLibraryItem;
|
lib: TLibraryItem;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
for i := 0 to fCol.Count-1 do
|
// no selector = all libs
|
||||||
|
if aliases.isNil then
|
||||||
begin
|
begin
|
||||||
itm := TLibraryItem(fCol.Items[i]);
|
for i:= 0 to librariesCount-1 do
|
||||||
if (not itm.enabled) or
|
begin
|
||||||
(aliases.isNotNil and (aliases.IndexOf(itm.libAlias) = -1)) then
|
lib := libraryByIndex[i];
|
||||||
continue;
|
if lib.enabled and lib.hasValidLibSourcePath then
|
||||||
//
|
list.Add('-I' + lib.libSourcePath);
|
||||||
if list.IndexOf(itm.libSourcePath) <> -1 then
|
end;
|
||||||
continue;
|
end
|
||||||
if not itm.libSourcePath.dirExists then
|
// else get selected libs
|
||||||
continue;
|
else
|
||||||
list.Add('-I' + itm.libSourcePath);
|
begin
|
||||||
|
for i := 0 to aliases.Count-1 do
|
||||||
|
begin
|
||||||
|
lib := libraryByAlias[aliases[i]];
|
||||||
|
if lib.isNotNil and lib.enabled and lib.hasValidLibSourcePath then
|
||||||
|
list.Add('-I' + lib.libSourcePath);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -435,30 +552,45 @@ var
|
||||||
imp: TStringList;
|
imp: TStringList;
|
||||||
i,j: integer;
|
i,j: integer;
|
||||||
itm: TLibraryItem;
|
itm: TLibraryItem;
|
||||||
|
dep: TLibraryItem;
|
||||||
|
sel: TLibraryList;
|
||||||
begin
|
begin
|
||||||
tks := TLexTokenList.Create;
|
tks := TLexTokenList.Create;
|
||||||
imp := TStringList.Create;
|
imp := TStringList.Create;
|
||||||
|
sel := TLibraryList.Create;
|
||||||
try
|
try
|
||||||
lex(source.Text, tks, nil, [lxoNoComments]);
|
lex(source.Text, tks, nil, [lxoNoComments]);
|
||||||
getImports(tks, imp);
|
getImports(tks, imp);
|
||||||
for i := 0 to fCol.Count-1 do
|
for i:= 0 to imp.Count-1 do
|
||||||
begin
|
begin
|
||||||
itm := items[i];
|
// get library for import I
|
||||||
for j := imp.Count-1 downto 0 do if itm.hasModule(imp[j]) then
|
itm := libraryByImport[imp[i]];
|
||||||
|
if itm.isNotNil then
|
||||||
begin
|
begin
|
||||||
imp.Delete(j);
|
sel.insert(itm);
|
||||||
if (libs.IndexOf(itm.libFile) <> -1) then
|
// get libraries for import I dependencies
|
||||||
continue;
|
for j:= 0 to itm.dependencies.Count-1 do
|
||||||
libs.Add(itm.libFile);
|
|
||||||
paths.Add('-I'+itm.libSourcePath);
|
|
||||||
if itm.dependencies.Count > 0 then
|
|
||||||
begin
|
begin
|
||||||
getLibFiles(itm.dependencies, libs);
|
dep := libraryByAlias[itm.dependencies[j]];
|
||||||
getLibSources(itm.dependencies, paths);
|
if dep.isNotNil then
|
||||||
|
sel.insert(dep);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
// add the library files and the import paths for the selection
|
||||||
|
if not sel.IsEmpty then with sel.Iterator do
|
||||||
|
begin
|
||||||
|
while true do if data.hasValidLibFile then
|
||||||
|
begin
|
||||||
|
libs.Add(Data.libFile);
|
||||||
|
paths.Add('-I' + Data.libSourcePath);
|
||||||
|
if not Next then
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
free;
|
||||||
|
end;
|
||||||
finally
|
finally
|
||||||
|
sel.Free;
|
||||||
tks.Free;
|
tks.Free;
|
||||||
imp.Free;
|
imp.Free;
|
||||||
end;
|
end;
|
||||||
|
|
@ -466,28 +598,33 @@ end;
|
||||||
|
|
||||||
procedure TLibraryManager.updateCrossDependencies;
|
procedure TLibraryManager.updateCrossDependencies;
|
||||||
var
|
var
|
||||||
i, j, k, m: integer;
|
i, j, m: integer;
|
||||||
|
lib: TLibraryItem;
|
||||||
|
dep: TLibraryItem;
|
||||||
|
imp: string;
|
||||||
begin
|
begin
|
||||||
for i := 0 to fCol.Count-1 do
|
for i := 0 to fCollection.Count-1 do
|
||||||
begin
|
begin
|
||||||
if (items[i].libAlias = 'phobos') or (items[i].libAlias = 'druntime') then
|
lib := libraryByIndex[i];
|
||||||
|
if (lib.libAlias = 'phobos') or (lib.libAlias = 'druntime') then
|
||||||
continue;
|
continue;
|
||||||
items[i].dependencies.Clear;
|
lib.dependencies.Clear;
|
||||||
for j := 0 to items[i].modules.Count-1 do
|
for j := 0 to lib.modules.Count-1 do
|
||||||
for m := 0 to items[i].moduleInfos[j].imports.Count-1 do
|
for m := 0 to lib.moduleByIndex[j].imports.Count-1 do
|
||||||
begin
|
begin
|
||||||
for k := 0 to fCol.Count-1 do
|
imp := lib.moduleByIndex[j].imports[m];
|
||||||
begin
|
// module of the same package so...
|
||||||
if k = i then
|
if lib.hasModule(imp) then
|
||||||
continue;
|
continue;
|
||||||
if (items[k].libAlias = 'phobos') or (items[k].libAlias = 'druntime') then
|
dep := libraryByImport[imp];
|
||||||
continue;
|
// ... this should not happen
|
||||||
if items[k].hasModule(items[i].moduleInfos[j].imports[m]) then
|
if dep = lib then
|
||||||
begin
|
continue;
|
||||||
items[i].dependencies.Add(items[k].libAlias);
|
// core or std are always handled by sc.ini
|
||||||
break;
|
if dep.isNil or (dep.libAlias = 'phobos') or (dep.libAlias = 'druntime') then
|
||||||
end;
|
continue;
|
||||||
end;
|
// add deps
|
||||||
|
libraryByIndex[i].dependencies.Add(dep.libAlias);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
|
||||||
|
|
@ -2288,7 +2288,7 @@ begin
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
LibMan.getLibFiles(nil, dmdproc.Parameters);
|
LibMan.getLibFiles(nil, dmdproc.Parameters);
|
||||||
LibMan.getLibSources(nil, dmdproc.Parameters);
|
LibMan.getLibSourcePath(nil, dmdproc.Parameters);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
deleteDups(dmdproc.Parameters);
|
deleteDups(dmdproc.Parameters);
|
||||||
|
|
|
||||||
|
|
@ -341,27 +341,13 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCENativeProject.doChanged;
|
procedure TCENativeProject.doChanged;
|
||||||
{$IFDEF DEBUG}
|
|
||||||
var
|
|
||||||
lst: TStringList;
|
|
||||||
{$ENDIF}
|
|
||||||
begin
|
begin
|
||||||
fModified := true;
|
fModified := true;
|
||||||
updateOutFilename;
|
updateOutFilename;
|
||||||
getBaseConfig;
|
getBaseConfig;
|
||||||
subjProjChanged(fProjectSubject, self);
|
subjProjChanged(fProjectSubject, self);
|
||||||
if assigned(fOnChange) then fOnChange(Self);
|
if assigned(fOnChange) then
|
||||||
{$IFDEF DEBUG}
|
fOnChange(Self);
|
||||||
//lst := TStringList.Create;
|
|
||||||
//try
|
|
||||||
// lst.Add('---------begin----------');
|
|
||||||
// getOpts(lst);
|
|
||||||
// lst.Add('---------end-----------');
|
|
||||||
// DebugLn(lst.Text);
|
|
||||||
//finally
|
|
||||||
// lst.Free;
|
|
||||||
//end;
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCENativeProject.getConfig(const ix: integer): TCompilerConfiguration;
|
function TCENativeProject.getConfig(const ix: integer): TCompilerConfiguration;
|
||||||
|
|
@ -468,7 +454,7 @@ begin
|
||||||
LibMan.getLibFiles(libAliasesPtr, aList);
|
LibMan.getLibFiles(libAliasesPtr, aList);
|
||||||
|
|
||||||
// but always adds -I<path>
|
// but always adds -I<path>
|
||||||
LibMan.getLibSources(libAliasesPtr, aList);
|
LibMan.getLibSourcePath(libAliasesPtr, aList);
|
||||||
// config
|
// config
|
||||||
if currentConfiguration.isOverriddenConfiguration then
|
if currentConfiguration.isOverriddenConfiguration then
|
||||||
currentConfiguration.getOpts(aList, fBaseConfig)
|
currentConfiguration.getOpts(aList, fBaseConfig)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue