diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index 27478f7a..37d89fd3 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -244,7 +244,7 @@ - + @@ -522,6 +522,12 @@ + + + + + + diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr index a857383c..f6da8e51 100644 --- a/lazproj/coedit.lpr +++ b/lazproj/coedit.lpr @@ -8,11 +8,11 @@ uses {$ENDIF}{$ENDIF} Interfaces, Forms, lazcontrols, runtimetypeinfocontrols, anchordockpkg, ce_sharedres, ce_observer, ce_libman, ce_symstring, ce_tools, ce_dcd, ce_main, - ce_writableComponent, ce_staticmacro, ce_inspectors, ce_editoroptions, - ce_dockoptions, ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, + ce_writableComponent, ce_staticmacro, ce_inspectors, ce_editoroptions, ce_compilers, + ce_dockoptions, ce_shortcutseditor, ce_mru, ce_processes, ce_dialogs, ce_dubprojeditor, ce_controls, ce_dfmt, ce_lcldragdrop, ce_stringrange, ce_dlangmaps, ce_projgroup, ce_projutils, ce_d2synpresets, - ce_dastworx, ce_dbgitf, ce_ddemangle; + ce_dastworx, ce_dbgitf, ce_ddemangle, ce_dubproject; {$R *.res} diff --git a/src/ce_ceproject.pas b/src/ce_ceproject.pas index 88e5e619..b8122856 100644 --- a/src/ce_ceproject.pas +++ b/src/ce_ceproject.pas @@ -132,8 +132,8 @@ type // native project have no ext constraint, this function tells if filename is project function isValidNativeProject(const filename: string): boolean; - function getCEProjectCompiler: TCECompiler; - procedure setCEProjectCompiler(value: TCECompiler); + function getCEProjectCompiler: DCompiler; + procedure setCEProjectCompiler(value: DCompiler); implementation @@ -142,7 +142,7 @@ uses var CEProjectCompilerFilename: string = 'dmd'; - CEProjectCompiler: TCECompiler; + CEProjectCompiler: DCompiler; constructor TCENativeProject.create(aOwner: TComponent); begin @@ -788,7 +788,7 @@ begin fCompilProc.OnTerminate:= @compProcTerminated; getOpts(fCompilProc.Parameters); //getUpToDateObjects(fCompilProc.Parameters); - if CEProjectCompiler = TCECompiler.gdc then + if CEProjectCompiler = gdc then fCompilProc.Parameters.Add('-gdc=gdc'); fCompilProc.Execute; end; @@ -1074,28 +1074,23 @@ begin end; end; -function getCEProjectCompiler: TCECompiler; +function getCEProjectCompiler: DCompiler; begin exit(CEProjectCompiler); end; -procedure setCEProjectCompiler(value: TCECompiler); +procedure setCEProjectCompiler(value: DCompiler); +var + sel: ICECompilerSelector; begin - case value of - TCECompiler.dmd: CEProjectCompilerFilename := exeFullName('dmd' + exeExt); - TCECompiler.gdc: CEProjectCompilerFilename := exeFullName('gdmd' + exeExt); - TCECompiler.ldc: CEProjectCompilerFilename := exeFullName('ldmd2' + exeExt); - end; - if (not CEProjectCompilerFilename.fileExists) - or CEProjectCompilerFilename.isEmpty then - begin - value := TCECompiler.dmd; - CEProjectCompilerFilename:= 'dmd' + exeExt; - end; + sel := getCompilerSelector; CEProjectCompiler := value; + if not sel.isCompilerValid(CEProjectCompiler) then + CEProjectCompiler := dmd; + CEProjectCompilerFilename:=sel.getCompilerPath(CEProjectCompiler); end; initialization - setCEProjectCompiler(TCECompiler.dmd); + setCEProjectCompiler(dmd); RegisterClasses([TCENativeProject]); end. diff --git a/src/ce_common.pas b/src/ce_common.pas index 37af21cb..d3c569c7 100644 --- a/src/ce_common.pas +++ b/src/ce_common.pas @@ -29,8 +29,6 @@ type THasMain = (mainNo, mainYes, mainDefaultBehavior); - TCECompiler = (dmd, gdc, ldc); - // function used as string hasher in fcl-stl TStringHash = class class function hash(const key: string; maxBucketsPow2: longword): longword; diff --git a/src/ce_compilers.lfm b/src/ce_compilers.lfm new file mode 100644 index 00000000..221e34a2 --- /dev/null +++ b/src/ce_compilers.lfm @@ -0,0 +1,484 @@ +object Form1: TForm1 + Left = 749 + Height = 869 + Top = 128 + Width = 473 + Caption = 'Form1' + ClientHeight = 869 + ClientWidth = 473 + LCLVersion = '1.6.0.4' + object ScrollBox1: TScrollBox + Left = 0 + Height = 869 + Top = 0 + Width = 473 + HorzScrollBar.Page = 111 + VertScrollBar.Page = 864 + Align = alClient + ClientHeight = 865 + ClientWidth = 469 + TabOrder = 0 + object grpDMD: TGroupBox + Left = 0 + Height = 160 + Top = 64 + Width = 469 + Align = alTop + Caption = 'DMD' + ClientHeight = 130 + ClientWidth = 465 + TabOrder = 0 + object selDMDexe: TFileNameEdit + Left = 2 + Height = 20 + Hint = 'select the compiler' + Top = 19 + Width = 461 + FilterIndex = 0 + HideDirectories = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 0 + end + object selDMDrt: TDirectoryEdit + Left = 2 + Height = 20 + Hint = 'select the root of druntime sources' + Top = 60 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 1 + end + object selDMDstd: TDirectoryEdit + Left = 2 + Height = 20 + Hint = 'select the root of phobos sources' + Top = 101 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 2 + end + object StaticText1: TStaticText + Left = 0 + Height = 17 + Top = 0 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'compiler' + TabOrder = 3 + end + object StaticText2: TStaticText + Left = 0 + Height = 17 + Top = 41 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Runtime sources' + TabOrder = 4 + end + object StaticText3: TStaticText + Left = 0 + Height = 17 + Top = 82 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Phobos sources' + TabOrder = 5 + end + end + object grpGDC: TGroupBox + Left = 0 + Height = 160 + Top = 224 + Width = 469 + Align = alTop + Caption = 'GDC' + ClientHeight = 130 + ClientWidth = 465 + TabOrder = 1 + object selGDCexe: TFileNameEdit + Left = 2 + Height = 20 + Hint = 'select the compiler' + Top = 19 + Width = 461 + FilterIndex = 0 + HideDirectories = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 0 + end + object selGDCrt: TDirectoryEdit + Left = 2 + Height = 20 + Hint = 'select the root of LDC runtime & phobos sources (can be a common folder)' + Top = 60 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 1 + end + object selGDCstd: TDirectoryEdit + Left = 2 + Height = 20 + Hint = 'select the root of LDC runtime & phobos sources (can be a common folder)' + Top = 101 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 2 + end + object StaticText4: TStaticText + Left = 0 + Height = 17 + Top = 0 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'compiler' + TabOrder = 3 + end + object StaticText5: TStaticText + Left = 0 + Height = 17 + Top = 41 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Runtime sources' + TabOrder = 4 + end + object StaticText6: TStaticText + Left = 0 + Height = 17 + Top = 82 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Phobos sources' + TabOrder = 5 + end + end + object grpLDC: TGroupBox + Left = 0 + Height = 160 + Top = 384 + Width = 469 + Align = alTop + Caption = 'LDC' + ClientHeight = 130 + ClientWidth = 465 + TabOrder = 2 + object selLDCexe: TFileNameEdit + Left = 2 + Height = 20 + Hint = 'select the compiler' + Top = 19 + Width = 461 + FilterIndex = 0 + HideDirectories = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 0 + end + object selLDCrt: TDirectoryEdit + Left = 2 + Height = 20 + Hint = 'select the root of druntime sources' + Top = 60 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 1 + end + object selLDCstd: TDirectoryEdit + Left = 2 + Height = 20 + Hint = 'select the root of phobos sources' + Top = 101 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 2 + end + object StaticText7: TStaticText + Left = 0 + Height = 17 + Top = 0 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'compiler' + TabOrder = 3 + end + object StaticText8: TStaticText + Left = 0 + Height = 17 + Top = 41 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Runtime sources' + TabOrder = 4 + end + object StaticText9: TStaticText + Left = 0 + Height = 17 + Top = 82 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Phobos sources' + TabOrder = 5 + end + end + object grpUSER1: TGroupBox + Left = 0 + Height = 160 + Top = 544 + Width = 469 + Align = alTop + Caption = 'User 1' + ClientHeight = 130 + ClientWidth = 465 + TabOrder = 3 + object selUSER1exe: TFileNameEdit + Left = 2 + Height = 20 + Top = 19 + Width = 461 + FilterIndex = 0 + HideDirectories = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 0 + end + object selUSER1rt: TDirectoryEdit + Left = 2 + Height = 20 + Top = 60 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 1 + end + object selUSER1std: TDirectoryEdit + Left = 2 + Height = 20 + Top = 101 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 2 + end + object StaticText10: TStaticText + Left = 0 + Height = 17 + Top = 0 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'compiler' + TabOrder = 3 + end + object StaticText11: TStaticText + Left = 0 + Height = 17 + Top = 41 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Runtime sources' + TabOrder = 4 + end + object StaticText12: TStaticText + Left = 0 + Height = 17 + Top = 82 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Phobos sources' + TabOrder = 5 + end + end + object grpUSER2: TGroupBox + Left = 0 + Height = 160 + Top = 704 + Width = 469 + Align = alTop + Caption = 'User 2' + ClientHeight = 130 + ClientWidth = 465 + TabOrder = 4 + object selUSER2exe: TFileNameEdit + Left = 2 + Height = 20 + Top = 19 + Width = 461 + FilterIndex = 0 + HideDirectories = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 0 + end + object selUSER2rt: TDirectoryEdit + Left = 2 + Height = 20 + Top = 60 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 1 + end + object selUSER2std: TDirectoryEdit + Left = 2 + Height = 20 + Top = 101 + Width = 461 + ShowHidden = False + ButtonWidth = 23 + NumGlyphs = 1 + Flat = True + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 2 + end + object StaticText13: TStaticText + Left = 0 + Height = 17 + Top = 0 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'compiler' + TabOrder = 3 + end + object StaticText14: TStaticText + Left = 0 + Height = 17 + Top = 41 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Runtime sources' + TabOrder = 4 + end + object StaticText15: TStaticText + Left = 0 + Height = 17 + Top = 82 + Width = 465 + Align = alTop + Alignment = taCenter + Caption = 'Phobos sources' + TabOrder = 5 + end + end + object GroupBox6: TGroupBox + Left = 0 + Height = 64 + Top = 0 + Width = 469 + Align = alTop + Caption = 'Default compiler' + ClientHeight = 34 + ClientWidth = 465 + TabOrder = 5 + object selDefault: TComboBox + Left = 2 + Height = 30 + Top = 2 + Width = 461 + Align = alClient + BorderSpacing.Around = 2 + ItemHeight = 0 + ItemIndex = 0 + Items.Strings = ( + 'DMD' + 'GDC' + 'GDMD' + 'LDC' + 'LDMD' + 'USER 1' + 'USER 2' + ) + Style = csDropDownList + TabOrder = 0 + Text = 'DMD' + end + end + end +end diff --git a/src/ce_compilers.pas b/src/ce_compilers.pas new file mode 100644 index 00000000..e3295c57 --- /dev/null +++ b/src/ce_compilers.pas @@ -0,0 +1,446 @@ +unit ce_compilers; + +{$I ce_defines.inc} + +interface + +uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, EditBtn, + StdCtrls, + ce_dcd, ce_common, ce_interfaces, ce_observer, ce_writableComponent, + ce_dialogs; + +type + + //TODO-cCompilerPaths: add a way to relaunch DCD after compiler change + + TCompilersPaths = class(TWritableLfmTextComponent) + strict private + fDefaultCompiler: DCompiler; + fDmdExeName: string; + fDmdRuntimePath: string; + fDmdPhobosPath: string; + fGdcExeName: string; + fGdcRuntimePath: string; + fGdcPhobosPath: string; + fLdcExeName: string; + fLdcRuntimePath: string; + fLdcPhobosPath: string; + fUser1ExeName: string; + fUser1RuntimePath: string; + fUser1PhobosPath: string; + fUser2ExeName: string; + fUser2RuntimePath: string; + fUser2PhobosPath: string; + published + property defaultCompiler: DCompiler read fDefaultCompiler write fDefaultCompiler; + property DmdExeName: string read fDmdExeName write fDmdExeName; + property DmdRuntimePath: string read fDmdRuntimePath write fDmdRuntimePath; + property DmdPhobosPath: string read fDmdPhobosPath write fDmdPhobosPath; + property GdcExeName: string read fGdcExeName write fGdcExeName; + property GdcRuntimePath: string read fGdcRuntimePath write fGdcRuntimePath; + property GdcPhobosPath: string read fGdcPhobosPath write fGdcPhobosPath; + property LdcExeName: string read fLdcExeName write fLdcExeName; + property LdcRuntimePath: string read fLdcRuntimePath write fLdcRuntimePath; + property LdcPhobosPath: string read fLdcPhobosPath write fLdcPhobosPath; + property User1ExeName: string read fUser1ExeName write fUser1ExeName; + property User1RuntimePath: string read fUser1RuntimePath write fUser1RuntimePath; + property User1PhobosPath: string read fUser1PhobosPath write fUser1PhobosPath; + property User2ExeName: string read fUser2ExeName write fUser2ExeName; + property User2RuntimePath: string read fUser2RuntimePath write fUser2RuntimePath; + property User2PhobosPath: string read fUser2PhobosPath write fUser2PhobosPath; + public + procedure assign(source: TPersistent); override; + end; + + TForm1 = class(TForm, ICEEditableOptions, ICECompilerSelector) + selDefault: TComboBox; + selDMDrt: TDirectoryEdit; + selUSER2std: TDirectoryEdit; + selDMDstd: TDirectoryEdit; + selGDCrt: TDirectoryEdit; + selGDCstd: TDirectoryEdit; + selLDCrt: TDirectoryEdit; + selLDCstd: TDirectoryEdit; + selUSER1rt: TDirectoryEdit; + selUSER1std: TDirectoryEdit; + selUSER2rt: TDirectoryEdit; + selDMDexe: TFileNameEdit; + selGDCexe: TFileNameEdit; + selLDCexe: TFileNameEdit; + selUSER1exe: TFileNameEdit; + selUSER2exe: TFileNameEdit; + grpDMD: TGroupBox; + grpGDC: TGroupBox; + grpLDC: TGroupBox; + grpUSER1: TGroupBox; + grpUSER2: TGroupBox; + GroupBox6: TGroupBox; + ScrollBox1: TScrollBox; + StaticText1: TStaticText; + StaticText10: TStaticText; + StaticText11: TStaticText; + StaticText12: TStaticText; + StaticText13: TStaticText; + StaticText14: TStaticText; + StaticText15: TStaticText; + StaticText2: TStaticText; + StaticText3: TStaticText; + StaticText4: TStaticText; + StaticText5: TStaticText; + StaticText6: TStaticText; + StaticText7: TStaticText; + StaticText8: TStaticText; + StaticText9: TStaticText; + strict private + fPaths: TCompilersPaths; + fPathsBackup: TCompilersPaths; + procedure selectedExe(sender: TObject; var value: string); + procedure selectedRt(sender: TObject; var value: string); + procedure selectedStd(sender: TObject; var value: string); + procedure selectedDefault(sender: TObject); + procedure autoDetectDMD; + procedure autoDetectGDC; + procedure autoDetectLDC; + procedure dataToGui; + // + function optionedWantCategory(): string; + function optionedWantEditorKind: TOptionEditorKind; + function optionedWantContainer: TPersistent; + procedure optionedEvent(event: TOptionEditorEvent); + function optionedOptionsModified: boolean; + // + function singleServiceName: string; + function isCompilerValid(value: DCompiler): boolean; + function getCompilerPath(value: DCompiler): string; + procedure getCompilerImports(value: DCompiler; paths: TStrings); + public + constructor create(aOwner: TComponent); override; + destructor destroy; override; + end; + +implementation +{$R *.lfm} + +var + Form1: TForm1; + +const + optFname = 'compilerspaths.txt'; + +{$REGION Standard Object/COmponents things -------------------------------------} +constructor TForm1.create(aOwner: TComponent); +var + fname: string; + imprt: TStringList; +begin + inherited; + fPaths:= TCompilersPaths.Create(self); + fPathsBackup:= TCompilersPaths.Create(self); + + fname := getCoeditDocPath + optFname; + if fname.fileExists then + fPaths.loadFromFile(fname) + else + begin + autoDetectDMD; + autoDetectGDC; + autoDetectLDC; + end; + fPathsBackup.Assign(fPaths); + dataToGui; + + imprt := TStringList.Create; + try + getCompilerImports(fPaths.defaultCompiler, imprt); + DcdWrapper.addImportFolders(imprt); + finally + imprt.free; + end; + + selDMDexe.OnAcceptFileName:= @selectedExe; + selGDCexe.OnAcceptFileName:= @selectedExe; + selLDCexe.OnAcceptFileName:= @selectedExe; + selUSER1exe.OnAcceptFileName:= @selectedExe; + selUSER2exe.OnAcceptFileName:= @selectedExe; + + selDMDrt.OnAcceptDirectory:= @selectedRt; + selGDCrt.OnAcceptDirectory:= @selectedRt; + selLDCrt.OnAcceptDirectory:= @selectedRt; + selUSER1rt.OnAcceptDirectory:= @selectedRt; + selUSER2rt.OnAcceptDirectory:= @selectedRt; + + selDMDstd.OnAcceptDirectory:= @selectedStd; + selGDCstd.OnAcceptDirectory:= @selectedStd; + selLDCstd.OnAcceptDirectory:= @selectedStd; + selUSER1std.OnAcceptDirectory:= @selectedStd; + selUSER2std.OnAcceptDirectory:= @selectedStd; + + selDefault.OnSelect:= @selectedDefault; + + EntitiesConnector.addSingleService(self); + EntitiesConnector.addObserver(self); +end; + +destructor TForm1.destroy; +begin + fPaths.saveToFile(getCoeditDocPath + optFname); + EntitiesConnector.removeObserver(self); + inherited; +end; + +procedure TCompilersPaths.assign(source: TPersistent); +var + src: TCompilersPaths; +begin + if source is TCompilersPaths then + begin + src := TCompilersPaths(source); + fDefaultCompiler := src.fDefaultCompiler; + fDmdExeName := src.fDmdExeName; + fDmdRuntimePath := src.fDmdRuntimePath; + fDmdPhobosPath := src.fDmdPhobosPath; + fGdcExeName := src.fGdcExeName; + fGdcRuntimePath := src.fGdcRuntimePath; + fGdcPhobosPath := src.fGdcPhobosPath; + fLdcExeName := src.fLdcExeName; + fLdcRuntimePath := src.fLdcRuntimePath; + fLdcPhobosPath := src.fLdcPhobosPath; + fUser1ExeName := src.fUser1ExeName; + fUser1RuntimePath := src.fUser1RuntimePath; + fUser1PhobosPath := src.fUser1PhobosPath; + fUser2ExeName := src.fUser2ExeName; + fUser2RuntimePath := src.fUser2RuntimePath; + fUser2PhobosPath := src.fUser2PhobosPath; + end + else inherited; +end; +{$ENDREGION} + +{$REGION ICEEditableOptions ----------------------------------------------------} +function TForm1.optionedWantCategory(): string; +begin + exit('Compilers paths'); +end; + +function TForm1.optionedWantEditorKind: TOptionEditorKind; +begin + exit(oekForm); +end; + +function TForm1.optionedWantContainer: TPersistent; +begin + fPathsBackup.assign(fPaths); + exit(self); +end; + +procedure TForm1.optionedEvent(event: TOptionEditorEvent); +begin + case event of + oeeAccept: fPathsBackup.assign(fPaths); + oeeCancel: fPaths.assign(fPathsBackup); + end; +end; + +function TForm1.optionedOptionsModified: boolean; +begin + //TODO-cCompilerPaths: add setters to detect if a TCompilersPaths is modified + exit(false); +end; +{$ENDREGION} + +{$REGION ICECompilerSelector ---------------------------------------------------} +function TForm1.singleServiceName: string; +begin + exit('ICECompilerSelector'); +end; + +function TForm1.isCompilerValid(value: DCompiler): boolean; +begin + result := false; + with fPaths do case value of + DCompiler.dmd: exit(DmdExeName.fileExists); + DCompiler.gdc: exit(GdcExeName.fileExists); + DCompiler.gdmd: exit(exeFullName('gdmd' + exeExt).fileExists); + DCompiler.ldc: exit(LdcExeName.fileExists); + DCompiler.ldmd: exit(exeFullName('ldmd2' + exeExt).fileExists); + DCompiler.user1: exit(User1ExeName.fileExists); + DCompiler.user2: exit(User2ExeName.fileExists); + end; +end; + +function TForm1.getCompilerPath(value: DCompiler): string; +begin + result := ''; + with fPaths do case value of + DCompiler.dmd: exit(DmdExeName); + DCompiler.gdc: exit(GdcExeName); + DCompiler.gdmd: exit(exeFullName('gdmd' + exeExt)); + DCompiler.ldc: exit(LdcExeName); + DCompiler.ldmd: exit(exeFullName('ldmd2' + exeExt)); + DCompiler.user1: exit(User1ExeName); + DCompiler.user2: exit(User2ExeName); + end; +end; + +procedure TForm1.getCompilerImports(value: DCompiler; paths: TStrings); + procedure tryAdd(const pth: string); + begin + if pth.isNotEmpty then + paths.Add(pth); + end; +begin + with fPaths do case value of + DCompiler.dmd: begin tryAdd(DmdRuntimePath); tryAdd(DmdPhobosPath); end; + DCompiler.gdc, DCompiler.gdmd: + begin tryAdd(GdcRuntimePath); tryAdd(GdcPhobosPath); end; + DCompiler.ldc, DCompiler.ldmd: + begin tryAdd(LdcRuntimePath); tryAdd(LdcPhobosPath); end; + DCompiler.user1: + begin tryAdd(User1RuntimePath); tryAdd(User1PhobosPath); end; + DCompiler.user2: + begin tryAdd(User2RuntimePath); tryAdd(User2PhobosPath); end; + end; +end; +{$ENDREGION} + +{$REGION Compilers paths things ------------------------------------------------} +procedure TForm1.dataToGui; +begin + with fPaths do + begin + selDMDexe.FileName := DmdExeName; + selDMDrt.Directory := DmdRuntimePath; + selDMDstd.Directory := DmdPhobosPath; + + selGDCexe.FileName := GdcExeName; + selGDCrt.Directory := GdcRuntimePath; + selGDCstd.Directory := GdcPhobosPath; + + selLDCexe.FileName := LdcExeName; + selLDCrt.Directory := LdcRuntimePath; + selLDCstd.Directory := LdcPhobosPath; + + selUSER1exe.FileName := User1ExeName; + selUSER1rt.Directory := User1RuntimePath; + selUSER1std.Directory := User1PhobosPath; + + selUSER2exe.FileName := User2ExeName; + selUSER2rt.Directory := User2RuntimePath; + selUSER2std.Directory := User2PhobosPath; + + selDefault.ItemIndex := integer(defaultCompiler); + end; +end; + +procedure TForm1.selectedExe(sender: TObject; var value: string); +var + ctrl: TWinControl; +begin + ctrl := TWinControl(sender); + if ctrl.Parent = grpDMD then + fPaths.DmdExeName:=value + else if ctrl.Parent = grpGDC then + fPaths.GDCExeName:=value + else if ctrl.Parent = grpLDC then + fPaths.LdcExeName:=value + else if ctrl.Parent = grpUSER1 then + fPaths.User1ExeName:=value + else if ctrl.Parent = grpUSER2 then + fPaths.User2ExeName:=value; +end; + +procedure TForm1.selectedRt(sender: TObject; var value: string); +var + ctrl: TWinControl; +begin + ctrl := TWinControl(sender); + if ctrl.Parent = grpDMD then + fPaths.DmdRuntimePath:=value + else if ctrl.Parent = grpGDC then + fPaths.GDCRuntimePath:=value + else if ctrl.Parent = grpLDC then + fPaths.LdcRuntimePath:=value + else if ctrl.Parent = grpUSER1 then + fPaths.User1RuntimePath:=value + else if ctrl.Parent = grpUSER2 then + fPaths.User2RuntimePath:=value; +end; + +procedure TForm1.selectedStd(sender: TObject; var value: string); +var + ctrl: TWinControl; +begin + ctrl := TWinControl(sender); + if ctrl.Parent = grpDMD then + fPaths.DmdPhobosPath:=value + else if ctrl.Parent = grpGDC then + fPaths.GDCPhobosPath:=value + else if ctrl.Parent = grpLDC then + fPaths.LdcPhobosPath:=value + else if ctrl.Parent = grpUSER1 then + fPaths.User1PhobosPath:=value + else if ctrl.Parent = grpUSER2 then + fPaths.User2PhobosPath:=value; +end; + +procedure TForm1.selectedDefault(sender: TObject); +begin + fPaths.defaultCompiler:= DCompiler(selDefault.ItemIndex); + dlgOkInfo('A restart might be necessary so that DCD caches a different version' + + 'of the runtime and the standard library.'); +end; + +procedure TForm1.autoDetectDMD; +{$IFDEF WINDOWS} +var + path: string; +{$ENDIF} +begin + {$IFDEF WINDOWS} + path := exeFullName('dmd' + exeExt); + if path.dirExists then + begin + fPaths.DmdExeName:= path; + path := path.extractFileDir.extractFileDir.extractFileDir; + if (path + '\src\drunime\import').dirExists then + fPaths.DmdRuntimePath := path + '\src\drunime\import'; + if (path + '\src\phobos').dirExists then + fPaths.DmdRuntimePath := path + '\src\phobos'; + end; + {$ENDIF} + {$IFDEF LINUX} + if '/usr/bin/dmd'.fileExists then + fPaths.DmdExeName:='/usr/bin/dmd'; + if '/usr/include/dmd/phobos'.dirExists then + fPaths.DmdPhobosPath:='/usr/include/dmd/phobos'; + if '/usr/include/dmd/druntime/import'.dirExists then + fPaths.DmdRuntimePath:='/usr/include/dmd/druntime/import'; + {$ENDIF} + {$IFDEF DARWIN} + if '/usr/local/bin/dmd'.fileExists then + fPaths.DmdExeName:='/usr/local/bin/dmd'; + if '/Library/D/dmd/src/phobos'.dirExists then + fPaths.DmdPhobosPath:='/Library/D/dmd/src/phobos'; + if '/Library/D/dmd/src/druntime/import' then + fPaths.DmdRuntimePath:='/Library/D/dmd/src/druntime/import'; + {$ENDIF} +end; + +procedure TForm1.autoDetectGDC; +begin + //TODO-cCompilerPaths: detect GDC +end; + +procedure TForm1.autoDetectLDC; +begin + //TODO-cCompilerPaths: detect LDC +end; +{$ENDREGION} + +initialization + Form1 := TForm1.create(nil); +finalization + Form1.free; +end. + diff --git a/src/ce_dmdwrap.pas b/src/ce_dmdwrap.pas index b41fb0a3..8c16e5fe 100644 --- a/src/ce_dmdwrap.pas +++ b/src/ce_dmdwrap.pas @@ -258,7 +258,7 @@ type destructor destroy; override; procedure assign(source: TPersistent); override; procedure getOpts(list: TStrings; base: TOptsGroup = nil); override; - procedure getCompilerSpecificOpts(list: TStrings; base: TOptsGroup = nil; compiler: TCECompiler = TCECompiler.dmd); + procedure getCompilerSpecificOpts(list: TStrings; base: TOptsGroup = nil; compiler: DCompiler = dmd); end; (***************************************************************************** @@ -1209,7 +1209,7 @@ begin end; procedure TOtherOpts.getCompilerSpecificOpts(list: TStrings; base: - TOptsGroup = nil; compiler: TCECompiler = TCECompiler.dmd); + TOptsGroup = nil; compiler: DCompiler = dmd); var i: integer; str: string; @@ -1218,10 +1218,11 @@ var begin if base.isNil then begin + // TODO-cCompilers paths: add other options to CE proj format for the other comps case compiler of - TCECompiler.dmd: lst := fDmdOthers; - TCECompiler.ldc: lst := fLdcOthers; - TCECompiler.gdc: lst := fGdcOthers; + dmd: lst := fDmdOthers; + ldc: lst := fLdcOthers; + gdc: lst := fGdcOthers; end; for i := 0 to lst.Count-1 do begin @@ -1236,17 +1237,17 @@ begin begin baseopt := TOtherOpts(base); case compiler of - TCECompiler.dmd: + dmd: if fDmdOthers.Count = 0 then lst := baseopt.fDmdOthers else lst := fDmdOthers; - TCECompiler.ldc: + ldc: if fLdcOthers.Count = 0 then lst := baseopt.fLdcOthers else lst := fLdcOthers; - TCECompiler.gdc: + gdc: if fGdcOthers.Count = 0 then lst := baseopt.fGdcOthers else diff --git a/src/ce_dubproject.pas b/src/ce_dubproject.pas index bbb2021d..204b4728 100644 --- a/src/ce_dubproject.pas +++ b/src/ce_dubproject.pas @@ -8,7 +8,7 @@ uses Classes, SysUtils, xfpjson, xjsonparser, xjsonscanner, process, strutils, LazFileUtils, RegExpr, ce_common, ce_interfaces, ce_observer, ce_dialogs, ce_processes, - ce_writableComponent; + ce_writableComponent, ce_compilers; type @@ -27,12 +27,12 @@ type fCombined: boolean; fDepCheck: TDubDependencyCheck; fOther: string; - fCompiler: TCECompiler; + fCompiler: DCompiler; procedure setLinkMode(value: TDubLinkMode); - procedure setCompiler(value: TCECompiler); - function getCompiler: TCECompiler; + procedure setCompiler(value: DCompiler); + function getCompiler: DCompiler; published - property compiler: TCECOmpiler read getCompiler write setCompiler; + property compiler: DCompiler read getCompiler write setCompiler; property parallel: boolean read fParallel write fParallel; property forceRebuild: boolean read fForceRebuild write fForceRebuild; property linkMode: TDubLinkMode read fLinkMode write setLinkMode; @@ -153,11 +153,11 @@ type // converts a sdl description to json, returns the json function sdl2json(const filename: string): TJSONObject; - function getDubCompiler: TCECompiler; - procedure setDubCompiler(value: TCECompiler); + function getDubCompiler: DCompiler; + procedure setDubCompiler(value: DCompiler); var - DubCompiler: TCECompiler = TCECompiler.dmd; + DubCompiler: DCompiler = dmd; DubCompilerFilename: string = 'dmd'; const @@ -188,13 +188,13 @@ begin fLinkMode:=value; end; -procedure TCEDubBuildOptionsBase.setCompiler(value: TCECompiler); +procedure TCEDubBuildOptionsBase.setCompiler(value: DCompiler); begin fCompiler := value; setDubCompiler(fCompiler); end; -function TCEDubBuildOptionsBase.getCompiler: TCECompiler; +function TCEDubBuildOptionsBase.getCompiler: DCompiler; begin result := fCompiler; end; @@ -1211,29 +1211,25 @@ begin end; end; -function getDubCompiler: TCECompiler; +function getDubCompiler: DCompiler; begin exit(DubCompiler); end; -procedure setDubCompiler(value: TCECompiler); +procedure setDubCompiler(value: DCompiler); +var + sel: ICECompilerSelector; begin - case value of - TCECompiler.dmd: DubCompilerFilename := exeFullName('dmd' + exeExt); - TCECompiler.gdc: DubCompilerFilename := exeFullName('gdc' + exeExt); - TCECompiler.ldc: DubCompilerFilename := exeFullName('ldc2' + exeExt); - end; - if (not DubCompilerFilename.fileExists) or DubCompilerFilename.isEmpty then - begin - value := TCECompiler.dmd; - DubCompilerFilename:= 'dmd' + exeExt; - end; + sel := getCompilerSelector; DubCompiler := value; + if not sel.isCompilerValid(DubCompiler) then + DubCompiler := dmd; + DubCompilerFilename:=sel.getCompilerPath(DubCompiler); end; {$ENDREGION} initialization - setDubCompiler(TCECompiler.dmd); + setDubCompiler(dmd); dubBuildOptions:= TCEDubBuildOptions.create(nil); finalization dubBuildOptions.free; diff --git a/src/ce_libman.pas b/src/ce_libman.pas index d7b344c2..97601e91 100644 --- a/src/ce_libman.pas +++ b/src/ce_libman.pas @@ -7,7 +7,8 @@ interface uses Classes, SysUtils, FileUtil, ce_common, ce_writableComponent, LazFileUtils, ghashmap, ghashset, - ce_dcd, ce_dialogs, ce_projutils, ce_interfaces, ce_dlang, ce_dastworx; + ce_dcd, ce_dialogs, ce_projutils, ce_interfaces, ce_dlang, ce_dastworx, + ce_compilers; type @@ -314,98 +315,33 @@ end; constructor TLibraryManager.create(aOwner: TComponent); var - fName: string; - {$IFDEF WINDOWS} - fDmdPath: string; - {$ENDIF} + nme: string; + als: string; + lib: TLibraryItem; i: integer; begin inherited; fItemsByAlias := TItemsByAlias.create; fCollection := TCollection.Create(TLibraryItem); fCollection.FPOAttachObserver(self); - fname := getCoeditDocPath + libFname; - if fname.fileExists then - loadFromFile(fname); - if fCollection.Count = 0 then + nme := getCoeditDocPath + libFname; + if nme.fileExists then + loadFromFile(nme); + for i := fCollection.Count-1 downto 0 do begin - {$IFDEF WINDOWS} - fDmdPath := ExeSearch('dmd.exe'); - if fDmdPath.fileExists then + lib := libraryByIndex[i]; + als := lib.libAlias.upperCase; + // TODO-cmaintenace: from 3 upd 1 remove auto suprerssion of libman entry for phobos and rt. + if (als = 'PHOBOS') or (als = 'RUNTIME') or (als = 'DRUNTIME') then begin - // add phobos - fname := fDmdPath.ExtractFileDir; - fname := fname.ExtractFileDir; - with TLibraryItem(fCollection.Add) do begin - libAlias := 'phobos'; - libFile := fname + '\lib\phobos.lib'; - libSourcePath := fname.ExtractFileDir + '\src\phobos'; - end; - // add druntime (no lib - only for DCD) - fname := fDmdPath.ExtractFileDir; - fname := fname.ExtractFileDir; - with TLibraryItem(fCollection.Add) do begin - libAlias := 'druntime'; - libFile := ''; - libSourcePath := fname.ExtractFileDir + '\src\druntime\import'; - end; + fCollection.Delete(i); + continue; end; - {$ENDIF} - {$IFDEF LINUX} - // add phobos - if '/usr/include/dmd/phobos'.dirExists then - begin - with TLibraryItem(fCollection.Add) do begin - libAlias := 'phobos'; - libFile := ''; - libSourcePath := '/usr/include/dmd/phobos'; - end; - end; - // add druntime (no libraryByIndex - only for DCD) - if '/usr/include/dmd/druntime/import'.dirExists then - begin - with TLibraryItem(fCollection.Add) do begin - libAlias := 'druntime'; - libFile := ''; - libSourcePath := '/usr/include/dmd/druntime/import'; - end; - end; - {$ENDIF} - {$IFDEF DARWIN} - if '/Library/D/dmd/src/phobos'.dirExists then - begin - with TLibraryItem(fCol.Add) do begin - libAlias := 'phobos'; - libFile := ''; - libSourcePath := '/Library/D/dmd/src/phobos'; - end; - end; - // add druntime (no lib - only for DCD) - if '/Library/D/dmd/src/druntime/import'.dirExists then - begin - with TLibraryItem(fCol.Add) do begin - libAlias := 'druntime'; - libFile := ''; - libSourcePath := '/Library/D/dmd/src/druntime/import'; - end; - end; - {$ENDIF} + // + lib.updateModulesInfo; end; updateItemsByAlias; - if (fCollection.Count = 0) and not (getCoeditDocPath + libFname).fileExists then - begin - dlgOkInfo( - 'Coedit failed to add "druntime" and "phobos" to the library manager.' - + 'If they are not already specified in the DCD configuration then the ' - + 'completion will not work properly'); - end; updateDCD; - // - for i := 0 to fCollection.Count-1 do - begin - if (libraryByIndex[i].libAlias <> 'phobos') and (libraryByIndex[i].libAlias <> 'druntime') then - libraryByIndex[i].updateModulesInfo; - end; updateCrossDependencies; end; @@ -697,8 +633,6 @@ begin for i := 0 to fCollection.Count-1 do begin lib := libraryByIndex[i]; - if (lib.libAlias = 'phobos') or (lib.libAlias = 'druntime') then - continue; lib.dependencies.Clear; for j := 0 to lib.modules.Count-1 do for m := 0 to lib.moduleByIndex[j].imports.Count-1 do @@ -708,12 +642,12 @@ begin if lib.hasModule(imp) then continue; dep := libraryByImport[imp]; + // std / core / etc ... + if dep.isNil then + continue; // ... this should not happen if dep = lib then continue; - // core or std are always handled by sc.ini - if dep.isNil or (dep.libAlias = 'phobos') or (dep.libAlias = 'druntime') then - continue; // add deps if lib.dependencies.IndexOf(dep.libAlias) > -1 then continue; diff --git a/src/ce_main.pas b/src/ce_main.pas index fde5e290..0decb860 100644 --- a/src/ce_main.pas +++ b/src/ce_main.pas @@ -36,7 +36,7 @@ type TCERunnableOptions = class(TWritableLfmTextComponent) private - fCompiler: TCECompiler; + fCompiler: DCompiler; fDetectMain: boolean; fDetectLibraries: boolean; fOutputFolder: TCEPathname; @@ -44,12 +44,12 @@ type fStaticSwitches: TStringList; procedure setOutputFolder(const value: TCEPathname); procedure setStaticSwitches(value: TStringList); - procedure setCompiler(value: TCECompiler); + procedure setCompiler(value: DCompiler); protected procedure afterLoad; override; published property alwaysToFolder: boolean read fAlwaysToFolder write fAlwaysToFolder; - property compiler: TCECompiler read fCompiler write setCompiler; + property compiler: DCompiler read fCompiler write setCompiler; property detectMain: boolean read fDetectMain write fDetectMain; property detectLibraries: boolean read fDetectLibraries write fDetectLibraries; property outputFolder: TCEPathname read fOutputFolder write setOutputFolder; @@ -378,6 +378,7 @@ type fMainMenuSubj: TCEMainMenuSubject; fAppliOpts: TCEApplicationOptions; fProjActionsLock: boolean; + fCompilerSelector: ICECompilerSelector; procedure updateMainMenuProviders; procedure updateFloatingWidgetOnTop(onTop: boolean); procedure widgetDockingChanged(sender: TCEWidget; newState: TWidgetDockingState); @@ -544,8 +545,8 @@ type fShowBuildDuration: boolean; function getAdditionalPATH: string; procedure setAdditionalPATH(const value: string); - function getNativeProjecCompiler: TCECompiler; - procedure setNativeProjecCompiler(value: TCECompiler); + function getNativeProjecCompiler: DCompiler; + procedure setNativeProjecCompiler(value: DCompiler); procedure setSplitterScsrollSpeed(value: byte); published property additionalPATH: string read getAdditionalPATH write setAdditionalPath; @@ -556,7 +557,7 @@ type property maxRecentProjects: integer read fMaxRecentProjs write fMaxRecentProjs; property maxRecentDocuments: integer read fMaxRecentDocs write fMaxRecentDocs; property maxRecentProjectsGroups: integer read fMaxRecentGroups write fMaxRecentGroups; - property nativeProjectCompiler: TCECompiler read getNativeProjecCompiler write setNativeProjecCompiler; + property nativeProjectCompiler: DCompiler read getNativeProjecCompiler write setNativeProjecCompiler; property dscanUnittests: boolean read fDscanUnittests write fDscanUnittests default true; property autoSaveProjectFiles: boolean read fAutoSaveProjectFiles write fAutoSaveProjectFiles default false; property flatLook: boolean read fFlatLook write fFlatLook; @@ -690,14 +691,13 @@ begin fOutputFolder += DirectorySeparator; end; -procedure TCERunnableOptions.setCompiler(value: TCECompiler); +procedure TCERunnableOptions.setCompiler(value: DCompiler); begin - case value of - TCECompiler.ldc: if not exeInSysPath('ldmd2' + exeExt) then - value := TCECompiler.dmd; - TCECompiler.gdc: if not exeInSysPath('gdmd' + exeExt) then - value := TCECompiler.dmd; - end; + if fCompiler = value then + exit; + fCompiler := value; + if not getCompilerSelector.isCompilerValid(fCompiler) then + fCompiler := dmd; fCompiler :=value; end; @@ -764,12 +764,12 @@ begin fFlatLook:=true; end; -function TCEApplicationOptionsBase.getNativeProjecCompiler: TCECompiler; +function TCEApplicationOptionsBase.getNativeProjecCompiler: DCompiler; begin exit(ce_ceproject.getCEProjectCompiler); end; -procedure TCEApplicationOptionsBase.setNativeProjecCompiler(value: TCECompiler); +procedure TCEApplicationOptionsBase.setNativeProjecCompiler(value: DCompiler); begin ce_ceproject.setCEProjectCompiler(value); end; @@ -1138,6 +1138,7 @@ begin EntitiesConnector.forceUpdate; fSymStringExpander:= getSymStringExpander; fProjectGroup := getProjectGroup; + fCompilerSelector := getCompilerSelector; getCMdParams; fAppliOpts.assignTo(self); @@ -2604,9 +2605,11 @@ begin dmdproc.OnTerminate:= @asyncprocTerminate; dmdproc.Options := [poUsePipes, poStderrToOutPut]; case fRunnablesOptions.compiler of - TCECompiler.dmd: dmdProc.Executable :='dmd' + exeExt; - TCECompiler.ldc: dmdProc.Executable :='ldmd2' + exeExt; - TCECompiler.gdc: dmdProc.Executable :='gdmd' + exeExt; + dmd: dmdProc.Executable := fCompilerSelector.getCompilerPath(dmd); + gdc, gdmd: dmdProc.Executable := fCompilerSelector.getCompilerPath(gdmd); + ldc, ldmd: dmdProc.Executable := fCompilerSelector.getCompilerPath(ldmd); + user1: fCompilerSelector.getCompilerPath(user1); + user2: fCompilerSelector.getCompilerPath(user2); end; dmdproc.Parameters.Add(fDoc.fileName); if not asObj then @@ -2883,10 +2886,9 @@ begin fRunProc.Options := fRunProc.Options + [poNewConsole]; {$ENDIF} end; - case fRunnablesOptions.compiler of - TCECompiler.gdc: fRunProc.Parameters.add('--compiler=gdc'); - TCECompiler.ldc: fRunProc.Parameters.add('--compiler=ldc2'); - end; + if fRunnablesOptions.compiler <> dmd then + fRunProc.Parameters.add('--compiler=' + + fCompilerSelector.getCompilerPath(fRunnablesOptions.compiler)); fRunProc.execute; end;