libman, use hashset and hash map to speed up the selection of the items, close #77

This commit is contained in:
Basile Burg 2016-07-04 03:12:12 +02:00
parent 94eddd0ca8
commit e1846a9466
4 changed files with 304 additions and 140 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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)