diff --git a/CHANGES b/CHANGES index ccbdeb62..76e627da 100644 --- a/CHANGES +++ b/CHANGES @@ -1439,8 +1439,8 @@ Version history 2025-07-03 version 1.4.1-beta4 * mago: - - added option to select what type of property functions that can now be implicitly called. - - fixed calling functions with slices or larger structs + - added option to select what type of property functions can be implicitly called. + - fixed calling functions with slices or larger structs as return types - improve shortened names in call stack - better propagate the raw option modifier (!) to expanded expressions - don't fail enumerating child expressions if one fails, show error for this item instead @@ -1448,3 +1448,13 @@ Version history 2025-07-15 version 1.4.1 * dmdserver: do not display invalid struct size and alignment in tool tip + +2025-09-03 version 1.4.2-beta1 + * dmdserver: fixed error "module specified twice on command line" for same module name in + different packages + * dmdserver: added support for importing C files + * added command "Reset Language Server" to extension menu + * issue #313: installer now checks whether VS and the C++ development workloads are installed + and provides some assistance in installing them + * dbuild: add file imported from C to the dependencies for rebuilding + * dbuild: add option to set C include search path and C #defines diff --git a/VERSION b/VERSION index 8ceece45..1a305319 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 4 -#define VERSION_REVISION 1 -#define VERSION_BETA -#define VERSION_BUILD 0 +#define VERSION_REVISION 2 +#define VERSION_BETA -beta +#define VERSION_BUILD 1 diff --git a/c2d/c2d.visualdproj b/c2d/c2d.visualdproj index b052df83..366242d6 100644 --- a/c2d/c2d.visualdproj +++ b/c2d/c2d.visualdproj @@ -1672,9 +1672,9 @@ 0 0 0 - 1 + 0 0 - 0 + 1 0 0 0 diff --git a/c2d/vsi2d.visualdproj b/c2d/vsi2d.visualdproj index 9485b53d..afda470b 100644 --- a/c2d/vsi2d.visualdproj +++ b/c2d/vsi2d.visualdproj @@ -1422,7 +1422,7 @@ 0 0 0 - 0 + 1 0 0 0 diff --git a/msbuild/dbuild/CompileD.cs b/msbuild/dbuild/CompileD.cs index df419ec7..a6c90dfd 100644 --- a/msbuild/dbuild/CompileD.cs +++ b/msbuild/dbuild/CompileD.cs @@ -37,11 +37,13 @@ public CompileD() public bool DoNotLink { get { return opts.DoNotLink; } set { opts.DoNotLink = value; } } public string CodeGeneration { get { return opts.CodeGeneration; } set { opts.CodeGeneration = value; } } - public string[] ImportPaths { get { return opts.ImportPaths; } set { opts.ImportPaths = value; } } - public string[] StringImportPaths { get { return opts.StringImportPaths; } set { opts.StringImportPaths = value; } } + public string[] ImportPaths { get { return opts.ImportPaths; } set { opts.ImportPaths = value; } } + public string[] ImportCPaths { get { return opts.ImportCPaths; } set { opts.ImportCPaths = value; } } + public string[] StringImportPaths { get { return opts.StringImportPaths; } set { opts.StringImportPaths = value; } } public string[] VersionIdentifiers { get { return opts.VersionIdentifiers; } set { opts.VersionIdentifiers = value; } } public string[] DebugIdentifiers { get { return opts.DebugIdentifiers; } set { opts.DebugIdentifiers = value; } } - public string ObjectFileName { get { return opts.ObjectFileName; } set { opts.ObjectFileName = value; } } + public string[] ImportCDefines { get { return opts.ImportCDefines; } set { opts.ImportCDefines = value; } } + public string ObjectFileName { get { return opts.ObjectFileName; } set { opts.ObjectFileName = value; } } public bool PreserveSourcePath { get { return opts.PreserveSourcePath; } set { opts.PreserveSourcePath = value; } } public string CRuntimeLibrary { get { return opts.CRuntimeLibrary; } set { opts.CRuntimeLibrary = value; } } public bool Profile { get { return opts.Profile; } set { opts.Profile = value; } } @@ -188,12 +190,22 @@ private string TLogPrefix protected override string[] ReadTLogNames { - get { return new string[1] { TLogPrefix + ".read.1.tlog" }; } + get { + return new string[2] { + TLogPrefix + ".read.1.tlog", + TLogPrefix + "-cl.read.1.tlog", + }; + } } protected override string[] WriteTLogNames { - get { return new string[1] { TLogPrefix + ".write.1.tlog" }; } + get { + return new string[2] { + TLogPrefix + ".write.1.tlog", + TLogPrefix + "-cl.write.1.tlog", + }; + } } protected override string CommandTLogName diff --git a/msbuild/dbuild/CompileDOpt.cs b/msbuild/dbuild/CompileDOpt.cs index dc4c6c53..c077cc40 100644 --- a/msbuild/dbuild/CompileDOpt.cs +++ b/msbuild/dbuild/CompileDOpt.cs @@ -9,148 +9,150 @@ namespace dbuild { - /// ////////////////////////////////////////////////////////////////// - /// happens to be identical to CPPTasks.ToolSwitchType - public enum DToolSwitchType - { - Boolean, - Integer, - String, - StringArray, - File, - Directory, - ITaskItem, - ITaskItemArray, - AlwaysAppend, - StringPathArray, - } - - public interface IToolSwitchProvider - { - void SetProperty(string name, string displayName, string description, string switchValue, - DToolSwitchType type, object value, - bool multipleValues = false, bool required = false, string separator = null); - object GetProperty(string name); - } - - [Flags] - public enum EscapeFormat - { - Default = 0, - EscapeTrailingSlash = 1 - } - public enum CommandLineFormat - { - ForBuildLog = 0, - ForTracking = 1 - } - - public class CompileDOptions - { - public ArrayList switchOrderList = new ArrayList(); - private IToolSwitchProvider provider; - private string _compiler = "dmd"; - - public CompileDOptions(IToolSwitchProvider provider) - { - this.provider = provider; - - this.switchOrderList.Add("DoNotLink"); - this.switchOrderList.Add("CodeGeneration"); - - this.switchOrderList.Add("ImportPaths"); - this.switchOrderList.Add("StringImportPaths"); - this.switchOrderList.Add("VersionIdentifiers"); - this.switchOrderList.Add("DebugIdentifiers"); - this.switchOrderList.Add("ObjectFileName"); - this.switchOrderList.Add("PreserveSourcePath"); - this.switchOrderList.Add("CRuntimeLibrary"); - - this.switchOrderList.Add("Profile"); - this.switchOrderList.Add("ProfileGC"); - this.switchOrderList.Add("Coverage"); - this.switchOrderList.Add("MinCoverage"); - this.switchOrderList.Add("Unittest"); - this.switchOrderList.Add("Optimizer"); - this.switchOrderList.Add("Inliner"); - this.switchOrderList.Add("StackFrame"); - this.switchOrderList.Add("StackStomp"); - this.switchOrderList.Add("AllInst"); - this.switchOrderList.Add("Main"); - this.switchOrderList.Add("LowMem"); - this.switchOrderList.Add("DebugCode"); - this.switchOrderList.Add("DebugInfo"); - this.switchOrderList.Add("DebugFull"); - this.switchOrderList.Add("DebugMixin"); - this.switchOrderList.Add("BoundsCheck"); - this.switchOrderList.Add("CPUArchitecture"); - this.switchOrderList.Add("PerformSyntaxCheckOnly"); - - this.switchOrderList.Add("BetterC"); - this.switchOrderList.Add("CppStandard"); - this.switchOrderList.Add("DIP25"); - this.switchOrderList.Add("DIP1000"); - this.switchOrderList.Add("DIP1008"); - this.switchOrderList.Add("DIP1021"); - this.switchOrderList.Add("RevertImport"); - this.switchOrderList.Add("PreviewDtorFields"); - this.switchOrderList.Add("PreviewIntPromote"); - this.switchOrderList.Add("PreviewFixAliasThis"); - this.switchOrderList.Add("PreviewRvalueRefParam"); - this.switchOrderList.Add("PreviewNoSharedAccess"); - this.switchOrderList.Add("PreviewMarkdown"); - this.switchOrderList.Add("PreviewIn"); - this.switchOrderList.Add("PreviewInclusiveInContracts"); - this.switchOrderList.Add("PreviewShortenedMethods"); - this.switchOrderList.Add("PreviewFixImmutableConv"); - this.switchOrderList.Add("PreviewSystemVariables"); - this.switchOrderList.Add("TransitionVMarkdown"); - this.switchOrderList.Add("TransitionField"); - this.switchOrderList.Add("TransitionCheckImports"); - this.switchOrderList.Add("TransitionComplex"); - - this.switchOrderList.Add("Warnings"); - this.switchOrderList.Add("Deprecations"); - this.switchOrderList.Add("Verbose"); - this.switchOrderList.Add("ShowTLS"); - this.switchOrderList.Add("ShowGC"); - this.switchOrderList.Add("IgnorePragma"); - this.switchOrderList.Add("ShowDependencies"); - - this.switchOrderList.Add("DocDir"); - this.switchOrderList.Add("DocFile"); - this.switchOrderList.Add("DepFile"); - this.switchOrderList.Add("HeaderDir"); - this.switchOrderList.Add("HeaderFile"); - this.switchOrderList.Add("CppHeaderFile"); - this.switchOrderList.Add("JSONFile"); - - this.switchOrderList.Add("AdditionalOptions"); - - this.switchOrderList.Add("Sources"); - } - - public string AdditionalOptions { get; set; } - - public ITaskItem[] Sources - { - get - { - return GetTaskItemsProperty("Sources"); - } - set - { - SetTaskItemsProperty("Sources", value); - } - } - - // Hidden - public bool DoNotLink + /// ////////////////////////////////////////////////////////////////// + /// happens to be identical to CPPTasks.ToolSwitchType + public enum DToolSwitchType + { + Boolean, + Integer, + String, + StringArray, + File, + Directory, + ITaskItem, + ITaskItemArray, + AlwaysAppend, + StringPathArray, + } + + public interface IToolSwitchProvider + { + void SetProperty(string name, string displayName, string description, string switchValue, + DToolSwitchType type, object value, + bool multipleValues = false, bool required = false, string separator = null); + object GetProperty(string name); + } + + [Flags] + public enum EscapeFormat + { + Default = 0, + EscapeTrailingSlash = 1 + } + public enum CommandLineFormat + { + ForBuildLog = 0, + ForTracking = 1 + } + + public class CompileDOptions + { + public ArrayList switchOrderList = new ArrayList(); + private IToolSwitchProvider provider; + private string _compiler = "dmd"; + + public CompileDOptions(IToolSwitchProvider provider) + { + this.provider = provider; + + this.switchOrderList.Add("DoNotLink"); + this.switchOrderList.Add("CodeGeneration"); + + this.switchOrderList.Add("ImportPaths"); + this.switchOrderList.Add("StringImportPaths"); + this.switchOrderList.Add("VersionIdentifiers"); + this.switchOrderList.Add("DebugIdentifiers"); + this.switchOrderList.Add("ImportCPaths"); + this.switchOrderList.Add("ImportCDefines"); + this.switchOrderList.Add("ObjectFileName"); + this.switchOrderList.Add("PreserveSourcePath"); + this.switchOrderList.Add("CRuntimeLibrary"); + + this.switchOrderList.Add("Profile"); + this.switchOrderList.Add("ProfileGC"); + this.switchOrderList.Add("Coverage"); + this.switchOrderList.Add("MinCoverage"); + this.switchOrderList.Add("Unittest"); + this.switchOrderList.Add("Optimizer"); + this.switchOrderList.Add("Inliner"); + this.switchOrderList.Add("StackFrame"); + this.switchOrderList.Add("StackStomp"); + this.switchOrderList.Add("AllInst"); + this.switchOrderList.Add("Main"); + this.switchOrderList.Add("LowMem"); + this.switchOrderList.Add("DebugCode"); + this.switchOrderList.Add("DebugInfo"); + this.switchOrderList.Add("DebugFull"); + this.switchOrderList.Add("DebugMixin"); + this.switchOrderList.Add("BoundsCheck"); + this.switchOrderList.Add("CPUArchitecture"); + this.switchOrderList.Add("PerformSyntaxCheckOnly"); + + this.switchOrderList.Add("BetterC"); + this.switchOrderList.Add("CppStandard"); + this.switchOrderList.Add("DIP25"); + this.switchOrderList.Add("DIP1000"); + this.switchOrderList.Add("DIP1008"); + this.switchOrderList.Add("DIP1021"); + this.switchOrderList.Add("RevertImport"); + this.switchOrderList.Add("PreviewDtorFields"); + this.switchOrderList.Add("PreviewIntPromote"); + this.switchOrderList.Add("PreviewFixAliasThis"); + this.switchOrderList.Add("PreviewRvalueRefParam"); + this.switchOrderList.Add("PreviewNoSharedAccess"); + this.switchOrderList.Add("PreviewMarkdown"); + this.switchOrderList.Add("PreviewIn"); + this.switchOrderList.Add("PreviewInclusiveInContracts"); + this.switchOrderList.Add("PreviewShortenedMethods"); + this.switchOrderList.Add("PreviewFixImmutableConv"); + this.switchOrderList.Add("PreviewSystemVariables"); + this.switchOrderList.Add("TransitionVMarkdown"); + this.switchOrderList.Add("TransitionField"); + this.switchOrderList.Add("TransitionCheckImports"); + this.switchOrderList.Add("TransitionComplex"); + + this.switchOrderList.Add("Warnings"); + this.switchOrderList.Add("Deprecations"); + this.switchOrderList.Add("Verbose"); + this.switchOrderList.Add("ShowTLS"); + this.switchOrderList.Add("ShowGC"); + this.switchOrderList.Add("IgnorePragma"); + this.switchOrderList.Add("ShowDependencies"); + + this.switchOrderList.Add("DocDir"); + this.switchOrderList.Add("DocFile"); + this.switchOrderList.Add("DepFile"); + this.switchOrderList.Add("HeaderDir"); + this.switchOrderList.Add("HeaderFile"); + this.switchOrderList.Add("CppHeaderFile"); + this.switchOrderList.Add("JSONFile"); + + this.switchOrderList.Add("AdditionalOptions"); + + this.switchOrderList.Add("Sources"); + } + + public string AdditionalOptions { get; set; } + + public ITaskItem[] Sources + { + get + { + return GetTaskItemsProperty("Sources"); + } + set + { + SetTaskItemsProperty("Sources", value); + } + } + + // Hidden + public bool DoNotLink { get { return GetBoolProperty("DoNotLink"); } set { - SetBoolProperty("DoNotLink", "Do Not Link", + SetBoolProperty("DoNotLink", "Do Not Link", "Compile only. Do not link (-c)", "-c", value); } @@ -169,7 +171,7 @@ public string CodeGeneration new string[2] { "ARM64", "-march=arm64" } }; - SetEnumProperty("CodeGeneration", "Code Generation", + SetEnumProperty("CodeGeneration", "Code Generation", "Generate 32 or 64 bit code.", switchMap, value); } @@ -181,7 +183,7 @@ public string[] ImportPaths get { return GetStringArray("ImportPaths"); } set { - SetStringArray("ImportPaths", true, "Import Paths", + SetStringArray("ImportPaths", true, "Import Paths", "Where to look for imports. (-I[path]).", "-I", value); } } @@ -191,17 +193,36 @@ public string[] StringImportPaths get { return GetStringArray("StringImportPaths"); } set { - SetStringArray("StringImportPaths", true, "String Import Paths", + SetStringArray("StringImportPaths", true, "String Import Paths", "Where to look for string imports. (-J[path]).", "-J", value); } } + public string[] ImportCPaths + { + get { return GetStringArray("ImportCPaths"); } + set + { + SetStringArray("ImportCPaths", true, "Import C Include Paths", + "Where to look for includes in imported C files. (-P-I[path]).", "-P-I", value); + } + } + + public string[] ImportCDefines + { + get { return GetStringArray("ImportCDefines"); } + set + { + SetStringArray("ImportCDefines", false, "Import C Preprocessor Defines", + "#defines for imported C files. (-P-D[ident[=val]]).", "-P-D", value); + } + } public string[] VersionIdentifiers { get { return GetStringArray("VersionIdentifiers"); } set { - SetStringArray("VersionIdentifiers", false, "Version Identifiers", + SetStringArray("VersionIdentifiers", false, "Version Identifiers", "Compile in version code identified by ident/>= level.", "-version=", value); } } @@ -211,7 +232,7 @@ public string[] DebugIdentifiers get { return GetStringArray("DebugIdentifiers"); } set { - SetStringArray("DebugIdentifiers", false, "Debug Identifiers", + SetStringArray("DebugIdentifiers", false, "Debug Identifiers", "Compile in debug code identified by ident/<= level.", "-debug=", value); } } @@ -221,7 +242,7 @@ public string ObjectFileName get { return GetStringProperty("ObjectFileName"); } set { - SetFileProperty("ObjectFileName", "Object File Name", + SetFileProperty("ObjectFileName", "Object File Name", "Specifies the name of the output object file. Leave empty to auto generate a name according to the compilation model. Use [PackageName] to add the folder name with special characters replaced.", "-of", value); } @@ -232,7 +253,7 @@ public bool PreserveSourcePath get { return GetBoolProperty("PreserveSourcePath"); } set { - SetBoolProperty("PreserveSourcePath", "Preserve source path", + SetBoolProperty("PreserveSourcePath", "Preserve source path", "Preserve source path for output files. (-op)", "-op", value); } @@ -252,7 +273,7 @@ public string CRuntimeLibrary new string[2] { "MultiThreadedDebugDll", "-mscrtlib=msvcrtd" } }; - SetEnumProperty("CRuntimeLibrary", "C Runtime Library", + SetEnumProperty("CRuntimeLibrary", "C Runtime Library", "Link against the static/dynamic debug/release C runtime library.", switchMap, value); } @@ -264,7 +285,7 @@ public bool Profile get { return GetBoolProperty("Profile"); } set { - SetBoolProperty("Profile", "Enable Profiling", + SetBoolProperty("Profile", "Enable Profiling", "Profile runtime performance of generated code. (-profile)", "-profile", value); } @@ -275,7 +296,7 @@ public bool ProfileGC get { return GetBoolProperty("ProfileGC"); } set { - SetBoolProperty("ProfileGC", "Enable GC Profiling", + SetBoolProperty("ProfileGC", "Enable GC Profiling", "Profile runtime allocations. (-profile=gc)", "-profile=gc", value); } @@ -286,7 +307,7 @@ public bool Coverage get { return GetBoolProperty("Coverage"); } set { - SetBoolProperty("Coverage", "Enable Code Coverage", + SetBoolProperty("Coverage", "Enable Code Coverage", "Do code coverage analysis. (-cov)", "-cov", value); } @@ -296,13 +317,13 @@ public int MinCoverage { get { - return GetIntProperty("MinCoverage"); + return GetIntProperty("MinCoverage"); } set { - SetIntProperty("MinCoverage", "Minimum Code Coverage", - "Require at least nnn% code coverage. (-cov=nnn)", - "-cov=", ValidateInteger(0, 100, value)); + SetIntProperty("MinCoverage", "Minimum Code Coverage", + "Require at least nnn% code coverage. (-cov=nnn)", + "-cov=", ValidateInteger(0, 100, value)); } } @@ -311,7 +332,7 @@ public bool Unittest get { return GetBoolProperty("Unittest"); } set { - SetBoolProperty("Unittest", "Enable Unittests", + SetBoolProperty("Unittest", "Enable Unittests", "Compile in unit tests (-unittest)", "-unittest", value); } @@ -322,7 +343,7 @@ public bool Optimizer get { return GetBoolProperty("Optimizer"); } set { - SetBoolProperty("Optimizer", "Optimizations", + SetBoolProperty("Optimizer", "Optimizations", "run optimizer (-O)", "-O", value); } @@ -333,7 +354,7 @@ public bool Inliner get { return GetBoolProperty("Inliner"); } set { - SetBoolProperty("Inliner", "Inlining", + SetBoolProperty("Inliner", "Inlining", "Do function inlining (-inline)", "-inline", value); } @@ -344,7 +365,7 @@ public bool StackFrame get { return GetBoolProperty("StackFrame"); } set { - SetBoolProperty("StackFrame", "Stack Frames", + SetBoolProperty("StackFrame", "Stack Frames", "Always emit stack frame (-gs)", "-gs", value); } @@ -355,7 +376,7 @@ public bool StackStomp get { return GetBoolProperty("StackStomp"); } set { - SetBoolProperty("StackStomp", "Stack Stomp", + SetBoolProperty("StackStomp", "Stack Stomp", "Add stack stomp code (-gx)", "-gx", value); } @@ -366,7 +387,7 @@ public bool AllInst get { return GetBoolProperty("AllInst"); } set { - SetBoolProperty("AllInst", "All Template Instantiations", + SetBoolProperty("AllInst", "All Template Instantiations", "Generate code for all template instantiations (-allinst)", "-allinst", value); } @@ -377,7 +398,7 @@ public bool BetterC get { return GetBoolProperty("BetterC"); } set { - SetBoolProperty("BetterC", "Better C", + SetBoolProperty("BetterC", "Better C", "Omit generating some runtime information and helper functions (-betterC)", "-betterC", value); } @@ -388,7 +409,7 @@ public bool Main get { return GetBoolProperty("Main"); } set { - SetBoolProperty("Main", "Add Main", + SetBoolProperty("Main", "Add Main", "Add default main() (e.g. for unittesting) (-main)", "-main", value); } @@ -399,7 +420,7 @@ public bool LowMem get { return GetBoolProperty("LowMem"); } set { - SetBoolProperty("LowMem", "Low Memory Usage", + SetBoolProperty("LowMem", "Low Memory Usage", "Use garbage collector to reduce memory needed by the compiler (-lowmem)", "-lowmem", value); } @@ -417,7 +438,7 @@ public string DebugCode new string[2] { "Release", "-release" } }; - SetEnumProperty("DebugCode", "Debug Code", + SetEnumProperty("DebugCode", "Debug Code", "Compile in debug code. (-debug, -release)", switchMap, value); } @@ -435,7 +456,7 @@ public string DebugInfo new string[2] { "Mago", "-g" } }; - SetEnumProperty("DebugInfo", "Debug Info", + SetEnumProperty("DebugInfo", "Debug Info", "Generate debug information. (-gc, -g)", switchMap, value); } @@ -446,7 +467,7 @@ public bool DebugFull get { return GetBoolProperty("DebugFull"); } set { - SetBoolProperty("DebugFull", "Full Debug Info", + SetBoolProperty("DebugFull", "Full Debug Info", "Emit debug info for all referenced types (-gf)", "-gf", value); } @@ -457,7 +478,7 @@ public string DebugMixin get { return GetStringProperty("DebugMixin"); } set { - SetFileProperty("DebugMixin", "Debug Mixin File", + SetFileProperty("DebugMixin", "Debug Mixin File", "Expand and save mixins to specified file. (-mixin=[file])", "-mixin=", value); } @@ -476,7 +497,7 @@ public string CPUArchitecture new string[2] { "native", "-mcpu=native" } }; - SetEnumProperty("CPUArchitecture", "CPU Architecture", + SetEnumProperty("CPUArchitecture", "CPU Architecture", "generate instructions for architecture. (-mcpu=)", switchMap, value); } @@ -494,7 +515,7 @@ public string BoundsCheck new string[2] { "On", "-boundscheck=on" } }; - SetEnumProperty("BoundsCheck", "Bounds Checking", + SetEnumProperty("BoundsCheck", "Bounds Checking", "Enable array bounds checking. (-boundscheck=off/safeonly/on)", switchMap, value); } @@ -505,7 +526,7 @@ public bool PerformSyntaxCheckOnly get { return GetBoolProperty("PerformSyntaxCheckOnly"); } set { - SetBoolProperty("PerformSyntaxCheckOnly", "Perform Syntax Check Only", + SetBoolProperty("PerformSyntaxCheckOnly", "Perform Syntax Check Only", "Performs a syntax check only (-o-)", "-o-", value); } @@ -517,7 +538,7 @@ public bool DIP25 get { return GetBoolProperty("DIP25"); } set { - SetBoolProperty("DIP25", "DIP25", + SetBoolProperty("DIP25", "DIP25", "implement DIP25: sealed pointers (-dip25)", "-dip25", value); } @@ -528,52 +549,52 @@ public bool DIP1000 get { return GetBoolProperty("DIP1000"); } set { - SetBoolProperty("DIP1000", "DIP1000", + SetBoolProperty("DIP1000", "DIP1000", "implement DIP1000: scoped pointers (-dip1000)", "-dip1000", value); } } - public bool DIP1008 - { - get { return GetBoolProperty("DIP1008"); } - set - { - SetBoolProperty("DIP1008", "DIP1008", - "implement DIP1008: reference counted exceptions (-dip1008)", - "-dip1008", value); - } - } + public bool DIP1008 + { + get { return GetBoolProperty("DIP1008"); } + set + { + SetBoolProperty("DIP1008", "DIP1008", + "implement DIP1008: reference counted exceptions (-dip1008)", + "-dip1008", value); + } + } - public bool DIP1021 - { - get { return GetBoolProperty("DIP1021"); } - set - { - SetBoolProperty("DIP1021", "DIP1021", - "implement DIP1021: mutable function arguments (-preview=dip1021)", - "-preview=dip1021", value); - } - } + public bool DIP1021 + { + get { return GetBoolProperty("DIP1021"); } + set + { + SetBoolProperty("DIP1021", "DIP1021", + "implement DIP1021: mutable function arguments (-preview=dip1021)", + "-preview=dip1021", value); + } + } - public bool RevertImport + public bool RevertImport { get { return GetBoolProperty("RevertImport"); } set { - SetBoolProperty("RevertImport", "Revert import", - "revert to single phase name lookup (-revert=import)", + SetBoolProperty("RevertImport", "Revert import", + "revert to single phase name lookup (-revert=import)", "-revert=import", value); } } public bool PreviewDtorFields - { + { get { return GetBoolProperty("PreviewDtorFields"); } set { - SetBoolProperty("PreviewDtorFields", "Preview dtorfields", - "destruct fields of partially constructed objects (-preview=dtorfields)", + SetBoolProperty("PreviewDtorFields", "Preview dtorfields", + "destruct fields of partially constructed objects (-preview=dtorfields)", "-preview=dtorfields", value); } } @@ -583,117 +604,117 @@ public bool PreviewIntPromote get { return GetBoolProperty("PreviewIntPromote"); } set { - SetBoolProperty("PreviewIntPromote", "Preview intpromote", - "fix integral promotions for unary + - ~ operators (-preview=intpromote)", - "-preview=intpromote", value); - } - } - - public bool PreviewFixAliasThis - { - get { return GetBoolProperty("PreviewFixAliasThis"); } - set - { - SetBoolProperty("PreviewFixAliasThis", "Preview fixAliasThis", - "when a symbol is resolved, check alias this scope before upper scopes (-preview=fixAliasThis)", - "-preview=fixAliasThis", value); - } - } - - public bool PreviewRvalueRefParam - { - get { return GetBoolProperty("PreviewRvalueRefParam"); } - set - { - SetBoolProperty("PreviewRvalueRefParam", "Preview rvaluerefparam", - "enable rvalue arguments to ref parameters (-preview=rvaluerefparam)", - "-preview=rvaluerefparam", value); - } - } - - public bool PreviewNoSharedAccess - { - get { return GetBoolProperty("PreviewNoSharedAccess"); } - set - { - SetBoolProperty("PreviewNoSharedAccess", "Preview nosharedaccess", - "disable access to shared memory objects (-preview=nosharedaccess)", - "-preview=nosharedaccess", value); - } - } - - public bool PreviewMarkdown - { + SetBoolProperty("PreviewIntPromote", "Preview intpromote", + "fix integral promotions for unary + - ~ operators (-preview=intpromote)", + "-preview=intpromote", value); + } + } + + public bool PreviewFixAliasThis + { + get { return GetBoolProperty("PreviewFixAliasThis"); } + set + { + SetBoolProperty("PreviewFixAliasThis", "Preview fixAliasThis", + "when a symbol is resolved, check alias this scope before upper scopes (-preview=fixAliasThis)", + "-preview=fixAliasThis", value); + } + } + + public bool PreviewRvalueRefParam + { + get { return GetBoolProperty("PreviewRvalueRefParam"); } + set + { + SetBoolProperty("PreviewRvalueRefParam", "Preview rvaluerefparam", + "enable rvalue arguments to ref parameters (-preview=rvaluerefparam)", + "-preview=rvaluerefparam", value); + } + } + + public bool PreviewNoSharedAccess + { + get { return GetBoolProperty("PreviewNoSharedAccess"); } + set + { + SetBoolProperty("PreviewNoSharedAccess", "Preview nosharedaccess", + "disable access to shared memory objects (-preview=nosharedaccess)", + "-preview=nosharedaccess", value); + } + } + + public bool PreviewMarkdown + { get { return GetBoolProperty("PreviewMarkdown"); } set { - SetBoolProperty("PreviewMarkdown", "Enable Markdown", - "Enable Markdown replacements in Ddoc (-preview=markdown)", - "-preview=markdown", value); - } - } - - public bool PreviewIn - { - get { return GetBoolProperty("PreviewIn"); } - set - { - SetBoolProperty("PreviewIn", "Preview in", - "'in' on parameters means `scope const [ref]` and accepts rvalues (-preview=in)", - "-preview=in", value); - } - } - - public bool PreviewInclusiveInContracts - { - get { return GetBoolProperty("PreviewInclusiveInContracts"); } - set - { - SetBoolProperty("PreviewInclusiveInContracts", "Preview inclusiveincontracts", - "'in' contracts of overridden methods must be a superset of parent contract (-preview=inclusiveincontracts)", - "-preview=inclusiveincontracts", value); - } - } - - public bool PreviewShortenedMethods - { - get { return GetBoolProperty("PreviewShortenedMethods"); } - set - { - SetBoolProperty("PreviewShortenedMethods", "Preview shortened methods", - "allow use of => for methods and top-level functions in addition to lambdas (-preview=shortenedMethods)", - "-preview=shortenedMethods", value); - } - } - - public bool PreviewFixImmutableConv - { - get { return GetBoolProperty("PreviewFixImmutableConv"); } - set - { - SetBoolProperty("PreviewFixImmutableConv", "Preview disallowing unsound immutable conversions", - "disallow unsound immutable conversions that were formerly incorrectly permitted (-preview=fixImmutableConv)", - "-preview=fixImmutableConv", value); - } - } - - public bool PreviewSystemVariables - { - get { return GetBoolProperty("PreviewSystemVariables"); } - set - { - SetBoolProperty("PreviewSystemVariables", "Preview system variables", - "disable access to variables marked '@system' from @safe code (-preview=systemVariables)", - "-preview=systemVariables", value); - } - } - - public bool TransitionVMarkdown + SetBoolProperty("PreviewMarkdown", "Enable Markdown", + "Enable Markdown replacements in Ddoc (-preview=markdown)", + "-preview=markdown", value); + } + } + + public bool PreviewIn + { + get { return GetBoolProperty("PreviewIn"); } + set + { + SetBoolProperty("PreviewIn", "Preview in", + "'in' on parameters means `scope const [ref]` and accepts rvalues (-preview=in)", + "-preview=in", value); + } + } + + public bool PreviewInclusiveInContracts + { + get { return GetBoolProperty("PreviewInclusiveInContracts"); } + set + { + SetBoolProperty("PreviewInclusiveInContracts", "Preview inclusiveincontracts", + "'in' contracts of overridden methods must be a superset of parent contract (-preview=inclusiveincontracts)", + "-preview=inclusiveincontracts", value); + } + } + + public bool PreviewShortenedMethods + { + get { return GetBoolProperty("PreviewShortenedMethods"); } + set + { + SetBoolProperty("PreviewShortenedMethods", "Preview shortened methods", + "allow use of => for methods and top-level functions in addition to lambdas (-preview=shortenedMethods)", + "-preview=shortenedMethods", value); + } + } + + public bool PreviewFixImmutableConv + { + get { return GetBoolProperty("PreviewFixImmutableConv"); } + set + { + SetBoolProperty("PreviewFixImmutableConv", "Preview disallowing unsound immutable conversions", + "disallow unsound immutable conversions that were formerly incorrectly permitted (-preview=fixImmutableConv)", + "-preview=fixImmutableConv", value); + } + } + + public bool PreviewSystemVariables + { + get { return GetBoolProperty("PreviewSystemVariables"); } + set + { + SetBoolProperty("PreviewSystemVariables", "Preview system variables", + "disable access to variables marked '@system' from @safe code (-preview=systemVariables)", + "-preview=systemVariables", value); + } + } + + public bool TransitionVMarkdown { get { return GetBoolProperty("TransitionVMarkdown"); } set { - SetBoolProperty("TransitionVMarkdown", "List Markdown Usage", + SetBoolProperty("TransitionVMarkdown", "List Markdown Usage", "List instances of Markdown replacements in Ddoc (-transition=vmarkdown)", "-transition=vmarkdown", value); } @@ -704,7 +725,7 @@ public bool TransitionField get { return GetBoolProperty("TransitionField"); } set { - SetBoolProperty("TransitionField", "List non-mutable fields", + SetBoolProperty("TransitionField", "List non-mutable fields", "List all non-mutable fields which occupy an object instance (-transition=field)", "-transition=field", value); } @@ -715,7 +736,7 @@ public bool TransitionCheckImports get { return GetBoolProperty("TransitionCheckImports"); } set { - SetBoolProperty("TransitionCheckImports", "Show import anomalies", + SetBoolProperty("TransitionCheckImports", "Show import anomalies", "Give deprecation messages about import anomalies (-transition=checkimports)", "-transition=checkimports", value); } @@ -726,7 +747,7 @@ public bool TransitionComplex get { return GetBoolProperty("TransitionComplex"); } set { - SetBoolProperty("TransitionComplex", "Show usage of complex types", + SetBoolProperty("TransitionComplex", "Show usage of complex types", "Give deprecation messages about all usages of complex or imaginary types (-transition=complex)", "-transition=complex", value); } @@ -746,7 +767,7 @@ public string CppStandard new string[2] { "cpp17", "-extern-std=c++17" } }; - SetEnumProperty("CppStandard", "C++ Language Standard", + SetEnumProperty("CppStandard", "C++ Language Standard", "set C++ name mangling compatibility (-extern-std=)", switchMap, value); } @@ -766,7 +787,7 @@ public string Warnings new string[2] { "Error", "-w" } }; - SetEnumProperty("Warnings", "Warnings", + SetEnumProperty("Warnings", "Warnings", "Enable display of warnings. (-w, -wi)", switchMap, value); } @@ -784,7 +805,7 @@ public string Deprecations new string[2] { "Allow", "-d" } }; - SetEnumProperty("Deprecations", "Enable deprecated features", + SetEnumProperty("Deprecations", "Enable deprecated features", "Enable display of deprecated features. (-dw, -de, -d)", switchMap, value); } @@ -795,7 +816,7 @@ public bool Verbose get { return GetBoolProperty("Verbose"); } set { - SetBoolProperty("Verbose", "Verbose", + SetBoolProperty("Verbose", "Verbose", "Print out what the compiler is currently doing (-v)", "-v", value); } @@ -806,7 +827,7 @@ public bool ShowTLS get { return GetBoolProperty("ShowTLS"); } set { - SetBoolProperty("ShowTLS", "Show TLS variables", + SetBoolProperty("ShowTLS", "Show TLS variables", "List all variables going into thread local storage (-vtls)", "-vtls", value); } @@ -817,7 +838,7 @@ public bool ShowGC get { return GetBoolProperty("ShowGC"); } set { - SetBoolProperty("ShowGC", "Show GC allocations", + SetBoolProperty("ShowGC", "Show GC allocations", "List all gc allocations including hidden ones. (-vgc)", "-vgc", value); } @@ -828,7 +849,7 @@ public bool IgnorePragma get { return GetBoolProperty("IgnorePragma"); } set { - SetBoolProperty("IgnorePragma", "Ignore unsupported pragmas", + SetBoolProperty("IgnorePragma", "Ignore unsupported pragmas", "Ignore unsupported pragmas. (-ignore)", "-ignore", value); } @@ -839,7 +860,7 @@ public bool ShowDependencies get { return GetBoolProperty("ShowDependencies"); } set { - SetBoolProperty("ShowDependencies", "Print module dependencies", + SetBoolProperty("ShowDependencies", "Print module dependencies", "Print module dependencies (imports/file/version/debug/lib). (-deps)", "-deps", value); } @@ -851,7 +872,7 @@ public string DocDir get { return GetStringProperty("DocDir"); } set { - SetFileProperty("DocDir", "Documentation Directory", + SetFileProperty("DocDir", "Documentation Directory", "Write documentation file(s) to this directory. (-Dd[dir])", "-Dd", value); } @@ -862,7 +883,7 @@ public string DocFile get { return GetStringProperty("DocFile"); } set { - SetFileProperty("DocFile", "Documentation File", + SetFileProperty("DocFile", "Documentation File", "Write documentation to this file. (-Df[file])", "-Df", value); } @@ -873,7 +894,7 @@ public string DepFile get { return GetStringProperty("DepFile"); } set { - SetFileProperty("DepFile", "Dependencies File", + SetFileProperty("DepFile", "Dependencies File", "Write module dependencies to filename (only imports). (-deps=[file])", "-deps=", value); } @@ -884,554 +905,554 @@ public string HeaderDir get { return GetStringProperty("HeaderDir"); } set { - SetFileProperty("HeaderDir", "Header Directory", + SetFileProperty("HeaderDir", "Header Directory", "Write 'header' file(s) to this directory. (-Hd[dir])", "-Hd", value); } } - public string HeaderFile - { - get { return GetStringProperty("HeaderFile"); } - set - { - SetFileProperty("HeaderFile", "Header File", - "Write 'header' to this file. (-Hf[file])", - "-Hf", value); - } - } + public string HeaderFile + { + get { return GetStringProperty("HeaderFile"); } + set + { + SetFileProperty("HeaderFile", "Header File", + "Write 'header' to this file. (-Hf[file])", + "-Hf", value); + } + } - public string CppHeaderFile - { - get { return GetStringProperty("CppHeaderFile"); } - set - { - SetFileProperty("CppHeaderFile", "C++ Header File", - "Write C++ 'header' to this file. (-HCf=[file])", - "-HCf=", value); - } - } + public string CppHeaderFile + { + get { return GetStringProperty("CppHeaderFile"); } + set + { + SetFileProperty("CppHeaderFile", "C++ Header File", + "Write C++ 'header' to this file. (-HCf=[file])", + "-HCf=", value); + } + } - public string JSONFile + public string JSONFile { get { return GetStringProperty("JSONFile"); } set { - SetFileProperty("JSONFile", "JSON Browse File", + SetFileProperty("JSONFile", "JSON Browse File", "Write browse information to this JSON file. (-Xf[file])", "-Xf", value); } } - // Other properties - public string Compiler - { - get { return _compiler; } - set { _compiler = value; } - } - - public string ToolName - { - get { return _compiler + ".exe"; } - } - - public string TrackerLogDirectory - { - get; - set; - } - - public bool ShowCommandLine - { - get; - set; - } - - public string PackageName - { - get; - set; - } - - ////////////////////////////////////////////////////////////////// - private int ValidateInteger(int min, int max, int value) - { - if (value < min) - value = min; - if (value > max) - value = max; - return value; - } - - protected string ReadSwitchMap(string propertyName, string[][] switchMap, string value) - { - if (switchMap != null) - { - for (int index = 0; index < switchMap.Length; ++index) - { - if (string.Equals(switchMap[index][0], value, StringComparison.CurrentCultureIgnoreCase)) - return switchMap[index][1]; - } - } - return string.Empty; - } - - protected static string EnsureTrailingSlash(string directoryName) - { - if (!string.IsNullOrEmpty(directoryName)) - { - char ch = directoryName[directoryName.Length - 1]; - if ((int)ch != (int)Path.DirectorySeparatorChar && (int)ch != (int)Path.AltDirectorySeparatorChar) - directoryName += Path.DirectorySeparatorChar.ToString(); - } - return directoryName; - } - - ////////////////////////////////////////////////////////////////// - public bool GetBoolProperty(string name) - { - object val = provider.GetProperty(name); - return val != null ? (bool)val : false; - } - - public void SetBoolProperty(string name, string displayName, string description, string switchValue, bool value) - { - provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.Boolean, value); - } - - public int GetIntProperty(string name) - { - object val = provider.GetProperty(name); - return val != null ? (int)val : 0; - } - - public void SetIntProperty(string name, string displayName, string description, - string switchValue, int value) - { - provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.Integer, value); - } - - public string GetStringProperty(string name) - { - object val = provider.GetProperty(name); - return val != null ? (string)val : null; - } - - public void SetFileProperty(string name, string displayName, string description, - string switchValue, string value) - { - provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.File, value); - } - - public void SetDirectoryProperty(string name, string displayName, string description, - string switchValue, string value) - { - provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.Directory, EnsureTrailingSlash(value)); - } - - public void SetEnumProperty(string name, string displayName, string description, - string[][] switchMap, string value) - { - string switchValue = ReadSwitchMap(name, switchMap, value); - provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.Directory, value, true); - } - - public string[] GetStringArray(string name) - { - object val = provider.GetProperty(name); - return val != null ? (string[])val : null; - } - - public void SetStringArray(string name, bool paths, string displayName, string description, - string switchValue, string[] value) - { - DToolSwitchType type = paths ? DToolSwitchType.StringPathArray : DToolSwitchType.StringArray; - provider.SetProperty(name, displayName, description, switchValue, type, value); - } - - public ITaskItem[] GetTaskItemsProperty(string name) - { - object val = provider.GetProperty(name); - return val != null ? (ITaskItem[])val : null; - } - - public void SetTaskItemsProperty(string name, ITaskItem[] value) - { - provider.SetProperty(name, string.Empty, string.Empty, string.Empty, DToolSwitchType.ITaskItemArray, value, false, true, " "); - } - - } - - public class DToolSwitch - { - public string Name; - public string FalseSuffix; - public string TrueSuffix; - public string Separator; - public bool BooleanValue = true; - public string Value; - public string SwitchValue; - public string ReverseSwitchValue; - public string Description; - public string DisplayName; - public DToolSwitchType Type; - public bool Required; - public int Number; - public string[] StringList; - public ITaskItem TaskItem; - public ITaskItem[] TaskItemArray; - public bool MultipleValues; - - public DToolSwitch() - { - } - public DToolSwitch(DToolSwitchType toolType) - { - Type = toolType; - } - - public void SetValue(object val) - { - switch (Type) - { - case DToolSwitchType.Boolean: BooleanValue = (bool)val; break; - case DToolSwitchType.Integer: Number = (int)val; break; - case DToolSwitchType.File: - case DToolSwitchType.Directory: - case DToolSwitchType.String: Value = (string)val; break; - case DToolSwitchType.StringPathArray: - case DToolSwitchType.StringArray: StringList = (string[])val; break; - case DToolSwitchType.ITaskItem: TaskItem = (ITaskItem)val; break; - case DToolSwitchType.ITaskItemArray: TaskItemArray = (ITaskItem[])val; break; - } - } - - public object GetValue() - { - switch (Type) - { - case DToolSwitchType.Boolean: return BooleanValue; - case DToolSwitchType.Integer: return Number; - case DToolSwitchType.File: - case DToolSwitchType.Directory: - case DToolSwitchType.String: return Value; - case DToolSwitchType.StringPathArray: - case DToolSwitchType.StringArray: return StringList; - case DToolSwitchType.ITaskItem: return TaskItem; - case DToolSwitchType.ITaskItemArray: return TaskItemArray; - } - return null; - } - } - - public class CompileDOpt : IToolSwitchProvider - { - private Dictionary activeToolSwitchesValues = new Dictionary(); - private Dictionary activeToolSwitches = new Dictionary((IEqualityComparer)StringComparer.OrdinalIgnoreCase); - CompileDOptions opts; - - public string Compiler { get { return opts.Compiler; } set { opts.Compiler = value; } } - public string ToolExe { get; set; } - public string AdditionalOptions { get { return opts.AdditionalOptions; } set { opts.AdditionalOptions = value; } } - public virtual ITaskItem[] Sources { get { return opts.Sources; } set { opts.Sources = value; } } - - public CompileDOpt() - { - opts = new CompileDOptions(this); - } - - ////////////////////////////////////////////////////////////////// - public void SetProperty(string name, string displayName, string description, string switchValue, - DToolSwitchType type, object value, - bool multipleValues = false, bool required = false, string separator = null) - { - activeToolSwitches.Remove(name); - DToolSwitch toolSwitch = new DToolSwitch(type); - toolSwitch.DisplayName = displayName; - toolSwitch.Description = description; - toolSwitch.SwitchValue = switchValue; - toolSwitch.Name = name; - toolSwitch.SetValue(value); - toolSwitch.MultipleValues = multipleValues; - toolSwitch.Required = required; - toolSwitch.Separator = separator; - activeToolSwitches.Add(name, toolSwitch); - AddActiveSwitchToolValue(toolSwitch); - } - - public object GetProperty(string name) - { - if (IsPropertySet(name)) - { - return activeToolSwitches[name].GetValue(); - } - return null; - } - - protected void AddActiveSwitchToolValue(DToolSwitch switchToAdd) - { - if (switchToAdd.Type != DToolSwitchType.Boolean || switchToAdd.BooleanValue) - { - if (string.IsNullOrEmpty(switchToAdd.SwitchValue)) - return; - activeToolSwitchesValues.Add(switchToAdd.SwitchValue, switchToAdd); - } - else - { - if (string.IsNullOrEmpty(switchToAdd.ReverseSwitchValue)) - return; - activeToolSwitchesValues.Add(switchToAdd.ReverseSwitchValue, switchToAdd); - } - } - - protected bool IsPropertySet(string propertyName) - { - if (!string.IsNullOrEmpty(propertyName)) - return this.activeToolSwitches.ContainsKey(propertyName); - return false; - } - - // emulate what's happening in VCToolTask - public string GenerateCommandLineCommands() - { - // must be outside of response file - string cmd = null; - if (opts.LowMem) - cmd = " -lowmem"; - return cmd; - } - - public string GenerateResponseFileCommands(CommandLineFormat format, EscapeFormat escapeFormat) - { - bool hadAdditionalOpts = false; - CommandLineBuilder commandLineBuilder = new CommandLineBuilder(true); - foreach (string switchOrder in opts.switchOrderList) - { - if (IsPropertySet(switchOrder)) - { - DToolSwitch activeToolSwitch = this.activeToolSwitches[switchOrder]; - // no dependencies between switches defined - this.GenerateCommandsAccordingToType(commandLineBuilder, activeToolSwitch, format, escapeFormat); - } - else if (string.Equals(switchOrder, "additionaloptions", StringComparison.OrdinalIgnoreCase)) - { - if (!string.IsNullOrEmpty(this.AdditionalOptions)) - commandLineBuilder.AppendSwitch(Environment.ExpandEnvironmentVariables(this.AdditionalOptions)); - hadAdditionalOpts = true; - } - } - if (!hadAdditionalOpts && !string.IsNullOrEmpty(this.AdditionalOptions)) - commandLineBuilder.AppendSwitch(Environment.ExpandEnvironmentVariables(this.AdditionalOptions)); - return commandLineBuilder.ToString(); - } - - protected void GenerateCommandsAccordingToType(CommandLineBuilder builder, DToolSwitch toolSwitch, - CommandLineFormat format, EscapeFormat escapeFormat) - { - switch (toolSwitch.Type) - { - case DToolSwitchType.Boolean: - this.EmitBooleanSwitch(builder, toolSwitch); - break; - case DToolSwitchType.Integer: - this.EmitIntegerSwitch(builder, toolSwitch); - break; - case DToolSwitchType.String: - this.EmitStringSwitch(builder, toolSwitch); - break; - case DToolSwitchType.StringArray: - EmitStringArraySwitch(builder, toolSwitch, CommandLineFormat.ForBuildLog, EscapeFormat.Default); - break; - case DToolSwitchType.File: - EmitFileSwitch(builder, toolSwitch, format); - break; - case DToolSwitchType.Directory: - EmitDirectorySwitch(builder, toolSwitch, format); - break; - case DToolSwitchType.ITaskItem: - EmitTaskItemSwitch(builder, toolSwitch); - break; - case DToolSwitchType.ITaskItemArray: - EmitTaskItemArraySwitch(builder, toolSwitch, format); - break; - case DToolSwitchType.StringPathArray: - EmitStringArraySwitch(builder, toolSwitch, format, escapeFormat); - break; - default: - // ErrorUtilities.VerifyThrow(false, "InternalError"); - break; - } - } - - private static void EmitTaskItemArraySwitch(CommandLineBuilder builder, DToolSwitch toolSwitch, CommandLineFormat format) - { - if (string.IsNullOrEmpty(toolSwitch.Separator)) - { - foreach (ITaskItem taskItem in toolSwitch.TaskItemArray) - builder.AppendSwitchIfNotNull(toolSwitch.SwitchValue, Environment.ExpandEnvironmentVariables(taskItem.ItemSpec)); - } - else - { - ITaskItem[] parameters = new ITaskItem[toolSwitch.TaskItemArray.Length]; - for (int index = 0; index < toolSwitch.TaskItemArray.Length; ++index) - { - parameters[index] = (ITaskItem)new TaskItem(Environment.ExpandEnvironmentVariables(toolSwitch.TaskItemArray[index].ItemSpec)); - if (format == CommandLineFormat.ForTracking) - parameters[index].ItemSpec = parameters[index].ItemSpec.ToUpperInvariant(); - } - builder.AppendSwitchIfNotNull(toolSwitch.SwitchValue, parameters, toolSwitch.Separator); - } - } - - private static void EmitTaskItemSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) - { - if (string.IsNullOrEmpty(toolSwitch.TaskItem.ItemSpec)) - return; - builder.AppendFileNameIfNotNull(Environment.ExpandEnvironmentVariables(toolSwitch.TaskItem.ItemSpec + toolSwitch.Separator)); - } - - private static void EmitDirectorySwitch(CommandLineBuilder builder, DToolSwitch toolSwitch, CommandLineFormat format) - { - if (string.IsNullOrEmpty(toolSwitch.SwitchValue)) - return; - if (format == CommandLineFormat.ForBuildLog) - builder.AppendSwitch(toolSwitch.SwitchValue + toolSwitch.Separator); - else - builder.AppendSwitch(toolSwitch.SwitchValue.ToUpperInvariant() + toolSwitch.Separator); - } - - private static void EmitFileSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch, CommandLineFormat format) - { - if (string.IsNullOrEmpty(toolSwitch.Value)) - return; - string parameter = Environment.ExpandEnvironmentVariables(toolSwitch.Value).Trim(); - if (format == CommandLineFormat.ForTracking) - parameter = parameter.ToUpperInvariant(); - if (!parameter.StartsWith("\"", StringComparison.Ordinal)) - { - string str = "\"" + parameter; - parameter = !str.EndsWith("\\", StringComparison.Ordinal) || str.EndsWith("\\\\", StringComparison.Ordinal) ? str + "\"" : str + "\\\""; - } - builder.AppendSwitchUnquotedIfNotNull(toolSwitch.SwitchValue + toolSwitch.Separator, parameter); - } - - private void EmitIntegerSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) - { - string num = toolSwitch.Number.ToString((IFormatProvider)CultureInfo.InvariantCulture) + GetEffectiveArgumentsValues(toolSwitch); - if (!string.IsNullOrEmpty(toolSwitch.Separator)) - builder.AppendSwitch(toolSwitch.SwitchValue + toolSwitch.Separator + num); - else - builder.AppendSwitch(toolSwitch.SwitchValue + num); - } - - private static void EmitStringArraySwitch(CommandLineBuilder builder, DToolSwitch toolSwitch, - CommandLineFormat format, EscapeFormat escapeFormat) - { - string[] parameters = new string[toolSwitch.StringList.Length]; - char[] anyOf = new char[11] { ' ', '|', '<', '>', ',', ';', '-', '\r', '\n', '\t', '\f' }; - for (int index = 0; index < toolSwitch.StringList.Length; ++index) - { - string str = !toolSwitch.StringList[index].StartsWith("\"", StringComparison.Ordinal) || !toolSwitch.StringList[index].EndsWith("\"", StringComparison.Ordinal) ? Environment.ExpandEnvironmentVariables(toolSwitch.StringList[index]) : Environment.ExpandEnvironmentVariables(toolSwitch.StringList[index].Substring(1, toolSwitch.StringList[index].Length - 2)); - if (!string.IsNullOrEmpty(str)) - { - if (format == CommandLineFormat.ForTracking) - str = str.ToUpperInvariant(); - if (escapeFormat.HasFlag((Enum)EscapeFormat.EscapeTrailingSlash) && - str.IndexOfAny(anyOf) == -1 && - (str.EndsWith("\\", StringComparison.Ordinal) && !str.EndsWith("\\\\", StringComparison.Ordinal))) - str += "\\"; - parameters[index] = str; - } - } - if (string.IsNullOrEmpty(toolSwitch.Separator)) - { - foreach (string parameter in parameters) - builder.AppendSwitchIfNotNull(toolSwitch.SwitchValue, parameter); - } - else - builder.AppendSwitchIfNotNull(toolSwitch.SwitchValue, parameters, toolSwitch.Separator); - } - - private void EmitStringSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) - { - string switchName = string.Empty + toolSwitch.SwitchValue + toolSwitch.Separator; - StringBuilder stringBuilder = new StringBuilder(GetEffectiveArgumentsValues(toolSwitch)); - string str1 = toolSwitch.Value; - if (!toolSwitch.MultipleValues) - { - string str2 = str1.Trim(); - if (!str2.StartsWith("\"", StringComparison.Ordinal)) - { - string str3 = "\"" + str2; - str2 = !str3.EndsWith("\\", StringComparison.Ordinal) || str3.EndsWith("\\\\", StringComparison.Ordinal) ? str3 + "\"" : str3 + "\\\""; - } - stringBuilder.Insert(0, str2); - } - if (switchName.Length == 0 && stringBuilder.ToString().Length == 0) - return; - builder.AppendSwitchUnquotedIfNotNull(switchName, stringBuilder.ToString()); - } - - private void EmitBooleanSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) - { - if (toolSwitch.BooleanValue) - { - if (string.IsNullOrEmpty(toolSwitch.SwitchValue)) - return; - StringBuilder stringBuilder = new StringBuilder(GetEffectiveArgumentsValues(toolSwitch)); - stringBuilder.Insert(0, toolSwitch.Separator); - stringBuilder.Insert(0, toolSwitch.TrueSuffix); - stringBuilder.Insert(0, toolSwitch.SwitchValue); - builder.AppendSwitch(stringBuilder.ToString()); - } - else - this.EmitReversibleBooleanSwitch(builder, toolSwitch); - } - - private void EmitReversibleBooleanSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) - { - if (string.IsNullOrEmpty(toolSwitch.ReverseSwitchValue)) - return; - string str = toolSwitch.BooleanValue ? toolSwitch.TrueSuffix : toolSwitch.FalseSuffix; - StringBuilder stringBuilder = new StringBuilder(GetEffectiveArgumentsValues(toolSwitch)); - stringBuilder.Insert(0, str); - stringBuilder.Insert(0, toolSwitch.Separator); - stringBuilder.Insert(0, toolSwitch.TrueSuffix); - stringBuilder.Insert(0, toolSwitch.ReverseSwitchValue); - builder.AppendSwitch(stringBuilder.ToString()); - } - - protected string GetEffectiveArgumentsValues(DToolSwitch property) - { - StringBuilder stringBuilder = new StringBuilder(); - CommandLineBuilder commandLineBuilder = new CommandLineBuilder(); - commandLineBuilder.AppendSwitchUnquotedIfNotNull("", stringBuilder.ToString()); - return commandLineBuilder.ToString(); - } - - public void applyParameters(Dictionary parameterValues) - { - var myType = typeof(CompileDOptions); - foreach (string s in opts.switchOrderList) - { - var prop = myType.GetProperty(s); - object val; - if (prop != null && parameterValues.TryGetValue(s, out val)) - { - prop.SetValue(opts, val, null); - } - } - } - - public string GenCmdLine(Dictionary parameters) - { - applyParameters(parameters); - - string commandLineCommands = GenerateCommandLineCommands(); - string responseFileCommands = GenerateResponseFileCommands(CommandLineFormat.ForBuildLog, EscapeFormat.Default); - if (!string.IsNullOrEmpty(commandLineCommands)) - return commandLineCommands + " " + responseFileCommands; - return responseFileCommands; - } - } + // Other properties + public string Compiler + { + get { return _compiler; } + set { _compiler = value; } + } + + public string ToolName + { + get { return _compiler + ".exe"; } + } + + public string TrackerLogDirectory + { + get; + set; + } + + public bool ShowCommandLine + { + get; + set; + } + + public string PackageName + { + get; + set; + } + + ////////////////////////////////////////////////////////////////// + private int ValidateInteger(int min, int max, int value) + { + if (value < min) + value = min; + if (value > max) + value = max; + return value; + } + + protected string ReadSwitchMap(string propertyName, string[][] switchMap, string value) + { + if (switchMap != null) + { + for (int index = 0; index < switchMap.Length; ++index) + { + if (string.Equals(switchMap[index][0], value, StringComparison.CurrentCultureIgnoreCase)) + return switchMap[index][1]; + } + } + return string.Empty; + } + + protected static string EnsureTrailingSlash(string directoryName) + { + if (!string.IsNullOrEmpty(directoryName)) + { + char ch = directoryName[directoryName.Length - 1]; + if ((int)ch != (int)Path.DirectorySeparatorChar && (int)ch != (int)Path.AltDirectorySeparatorChar) + directoryName += Path.DirectorySeparatorChar.ToString(); + } + return directoryName; + } + + ////////////////////////////////////////////////////////////////// + public bool GetBoolProperty(string name) + { + object val = provider.GetProperty(name); + return val != null ? (bool)val : false; + } + + public void SetBoolProperty(string name, string displayName, string description, string switchValue, bool value) + { + provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.Boolean, value); + } + + public int GetIntProperty(string name) + { + object val = provider.GetProperty(name); + return val != null ? (int)val : 0; + } + + public void SetIntProperty(string name, string displayName, string description, + string switchValue, int value) + { + provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.Integer, value); + } + + public string GetStringProperty(string name) + { + object val = provider.GetProperty(name); + return val != null ? (string)val : null; + } + + public void SetFileProperty(string name, string displayName, string description, + string switchValue, string value) + { + provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.File, value); + } + + public void SetDirectoryProperty(string name, string displayName, string description, + string switchValue, string value) + { + provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.Directory, EnsureTrailingSlash(value)); + } + + public void SetEnumProperty(string name, string displayName, string description, + string[][] switchMap, string value) + { + string switchValue = ReadSwitchMap(name, switchMap, value); + provider.SetProperty(name, displayName, description, switchValue, DToolSwitchType.Directory, value, true); + } + + public string[] GetStringArray(string name) + { + object val = provider.GetProperty(name); + return val != null ? (string[])val : null; + } + + public void SetStringArray(string name, bool paths, string displayName, string description, + string switchValue, string[] value) + { + DToolSwitchType type = paths ? DToolSwitchType.StringPathArray : DToolSwitchType.StringArray; + provider.SetProperty(name, displayName, description, switchValue, type, value); + } + + public ITaskItem[] GetTaskItemsProperty(string name) + { + object val = provider.GetProperty(name); + return val != null ? (ITaskItem[])val : null; + } + + public void SetTaskItemsProperty(string name, ITaskItem[] value) + { + provider.SetProperty(name, string.Empty, string.Empty, string.Empty, DToolSwitchType.ITaskItemArray, value, false, true, " "); + } + + } + + public class DToolSwitch + { + public string Name; + public string FalseSuffix; + public string TrueSuffix; + public string Separator; + public bool BooleanValue = true; + public string Value; + public string SwitchValue; + public string ReverseSwitchValue; + public string Description; + public string DisplayName; + public DToolSwitchType Type; + public bool Required; + public int Number; + public string[] StringList; + public ITaskItem TaskItem; + public ITaskItem[] TaskItemArray; + public bool MultipleValues; + + public DToolSwitch() + { + } + public DToolSwitch(DToolSwitchType toolType) + { + Type = toolType; + } + + public void SetValue(object val) + { + switch (Type) + { + case DToolSwitchType.Boolean: BooleanValue = (bool)val; break; + case DToolSwitchType.Integer: Number = (int)val; break; + case DToolSwitchType.File: + case DToolSwitchType.Directory: + case DToolSwitchType.String: Value = (string)val; break; + case DToolSwitchType.StringPathArray: + case DToolSwitchType.StringArray: StringList = (string[])val; break; + case DToolSwitchType.ITaskItem: TaskItem = (ITaskItem)val; break; + case DToolSwitchType.ITaskItemArray: TaskItemArray = (ITaskItem[])val; break; + } + } + + public object GetValue() + { + switch (Type) + { + case DToolSwitchType.Boolean: return BooleanValue; + case DToolSwitchType.Integer: return Number; + case DToolSwitchType.File: + case DToolSwitchType.Directory: + case DToolSwitchType.String: return Value; + case DToolSwitchType.StringPathArray: + case DToolSwitchType.StringArray: return StringList; + case DToolSwitchType.ITaskItem: return TaskItem; + case DToolSwitchType.ITaskItemArray: return TaskItemArray; + } + return null; + } + } + + public class CompileDOpt : IToolSwitchProvider + { + private Dictionary activeToolSwitchesValues = new Dictionary(); + private Dictionary activeToolSwitches = new Dictionary((IEqualityComparer)StringComparer.OrdinalIgnoreCase); + CompileDOptions opts; + + public string Compiler { get { return opts.Compiler; } set { opts.Compiler = value; } } + public string ToolExe { get; set; } + public string AdditionalOptions { get { return opts.AdditionalOptions; } set { opts.AdditionalOptions = value; } } + public virtual ITaskItem[] Sources { get { return opts.Sources; } set { opts.Sources = value; } } + + public CompileDOpt() + { + opts = new CompileDOptions(this); + } + + ////////////////////////////////////////////////////////////////// + public void SetProperty(string name, string displayName, string description, string switchValue, + DToolSwitchType type, object value, + bool multipleValues = false, bool required = false, string separator = null) + { + activeToolSwitches.Remove(name); + DToolSwitch toolSwitch = new DToolSwitch(type); + toolSwitch.DisplayName = displayName; + toolSwitch.Description = description; + toolSwitch.SwitchValue = switchValue; + toolSwitch.Name = name; + toolSwitch.SetValue(value); + toolSwitch.MultipleValues = multipleValues; + toolSwitch.Required = required; + toolSwitch.Separator = separator; + activeToolSwitches.Add(name, toolSwitch); + AddActiveSwitchToolValue(toolSwitch); + } + + public object GetProperty(string name) + { + if (IsPropertySet(name)) + { + return activeToolSwitches[name].GetValue(); + } + return null; + } + + protected void AddActiveSwitchToolValue(DToolSwitch switchToAdd) + { + if (switchToAdd.Type != DToolSwitchType.Boolean || switchToAdd.BooleanValue) + { + if (string.IsNullOrEmpty(switchToAdd.SwitchValue)) + return; + activeToolSwitchesValues.Add(switchToAdd.SwitchValue, switchToAdd); + } + else + { + if (string.IsNullOrEmpty(switchToAdd.ReverseSwitchValue)) + return; + activeToolSwitchesValues.Add(switchToAdd.ReverseSwitchValue, switchToAdd); + } + } + + protected bool IsPropertySet(string propertyName) + { + if (!string.IsNullOrEmpty(propertyName)) + return this.activeToolSwitches.ContainsKey(propertyName); + return false; + } + + // emulate what's happening in VCToolTask + public string GenerateCommandLineCommands() + { + // must be outside of response file + string cmd = null; + if (opts.LowMem) + cmd = " -lowmem"; + return cmd; + } + + public string GenerateResponseFileCommands(CommandLineFormat format, EscapeFormat escapeFormat) + { + bool hadAdditionalOpts = false; + CommandLineBuilder commandLineBuilder = new CommandLineBuilder(true); + foreach (string switchOrder in opts.switchOrderList) + { + if (IsPropertySet(switchOrder)) + { + DToolSwitch activeToolSwitch = this.activeToolSwitches[switchOrder]; + // no dependencies between switches defined + this.GenerateCommandsAccordingToType(commandLineBuilder, activeToolSwitch, format, escapeFormat); + } + else if (string.Equals(switchOrder, "additionaloptions", StringComparison.OrdinalIgnoreCase)) + { + if (!string.IsNullOrEmpty(this.AdditionalOptions)) + commandLineBuilder.AppendSwitch(Environment.ExpandEnvironmentVariables(this.AdditionalOptions)); + hadAdditionalOpts = true; + } + } + if (!hadAdditionalOpts && !string.IsNullOrEmpty(this.AdditionalOptions)) + commandLineBuilder.AppendSwitch(Environment.ExpandEnvironmentVariables(this.AdditionalOptions)); + return commandLineBuilder.ToString(); + } + + protected void GenerateCommandsAccordingToType(CommandLineBuilder builder, DToolSwitch toolSwitch, + CommandLineFormat format, EscapeFormat escapeFormat) + { + switch (toolSwitch.Type) + { + case DToolSwitchType.Boolean: + this.EmitBooleanSwitch(builder, toolSwitch); + break; + case DToolSwitchType.Integer: + this.EmitIntegerSwitch(builder, toolSwitch); + break; + case DToolSwitchType.String: + this.EmitStringSwitch(builder, toolSwitch); + break; + case DToolSwitchType.StringArray: + EmitStringArraySwitch(builder, toolSwitch, CommandLineFormat.ForBuildLog, EscapeFormat.Default); + break; + case DToolSwitchType.File: + EmitFileSwitch(builder, toolSwitch, format); + break; + case DToolSwitchType.Directory: + EmitDirectorySwitch(builder, toolSwitch, format); + break; + case DToolSwitchType.ITaskItem: + EmitTaskItemSwitch(builder, toolSwitch); + break; + case DToolSwitchType.ITaskItemArray: + EmitTaskItemArraySwitch(builder, toolSwitch, format); + break; + case DToolSwitchType.StringPathArray: + EmitStringArraySwitch(builder, toolSwitch, format, escapeFormat); + break; + default: + // ErrorUtilities.VerifyThrow(false, "InternalError"); + break; + } + } + + private static void EmitTaskItemArraySwitch(CommandLineBuilder builder, DToolSwitch toolSwitch, CommandLineFormat format) + { + if (string.IsNullOrEmpty(toolSwitch.Separator)) + { + foreach (ITaskItem taskItem in toolSwitch.TaskItemArray) + builder.AppendSwitchIfNotNull(toolSwitch.SwitchValue, Environment.ExpandEnvironmentVariables(taskItem.ItemSpec)); + } + else + { + ITaskItem[] parameters = new ITaskItem[toolSwitch.TaskItemArray.Length]; + for (int index = 0; index < toolSwitch.TaskItemArray.Length; ++index) + { + parameters[index] = (ITaskItem)new TaskItem(Environment.ExpandEnvironmentVariables(toolSwitch.TaskItemArray[index].ItemSpec)); + if (format == CommandLineFormat.ForTracking) + parameters[index].ItemSpec = parameters[index].ItemSpec.ToUpperInvariant(); + } + builder.AppendSwitchIfNotNull(toolSwitch.SwitchValue, parameters, toolSwitch.Separator); + } + } + + private static void EmitTaskItemSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) + { + if (string.IsNullOrEmpty(toolSwitch.TaskItem.ItemSpec)) + return; + builder.AppendFileNameIfNotNull(Environment.ExpandEnvironmentVariables(toolSwitch.TaskItem.ItemSpec + toolSwitch.Separator)); + } + + private static void EmitDirectorySwitch(CommandLineBuilder builder, DToolSwitch toolSwitch, CommandLineFormat format) + { + if (string.IsNullOrEmpty(toolSwitch.SwitchValue)) + return; + if (format == CommandLineFormat.ForBuildLog) + builder.AppendSwitch(toolSwitch.SwitchValue + toolSwitch.Separator); + else + builder.AppendSwitch(toolSwitch.SwitchValue.ToUpperInvariant() + toolSwitch.Separator); + } + + private static void EmitFileSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch, CommandLineFormat format) + { + if (string.IsNullOrEmpty(toolSwitch.Value)) + return; + string parameter = Environment.ExpandEnvironmentVariables(toolSwitch.Value).Trim(); + if (format == CommandLineFormat.ForTracking) + parameter = parameter.ToUpperInvariant(); + if (!parameter.StartsWith("\"", StringComparison.Ordinal)) + { + string str = "\"" + parameter; + parameter = !str.EndsWith("\\", StringComparison.Ordinal) || str.EndsWith("\\\\", StringComparison.Ordinal) ? str + "\"" : str + "\\\""; + } + builder.AppendSwitchUnquotedIfNotNull(toolSwitch.SwitchValue + toolSwitch.Separator, parameter); + } + + private void EmitIntegerSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) + { + string num = toolSwitch.Number.ToString((IFormatProvider)CultureInfo.InvariantCulture) + GetEffectiveArgumentsValues(toolSwitch); + if (!string.IsNullOrEmpty(toolSwitch.Separator)) + builder.AppendSwitch(toolSwitch.SwitchValue + toolSwitch.Separator + num); + else + builder.AppendSwitch(toolSwitch.SwitchValue + num); + } + + private static void EmitStringArraySwitch(CommandLineBuilder builder, DToolSwitch toolSwitch, + CommandLineFormat format, EscapeFormat escapeFormat) + { + string[] parameters = new string[toolSwitch.StringList.Length]; + char[] anyOf = new char[11] { ' ', '|', '<', '>', ',', ';', '-', '\r', '\n', '\t', '\f' }; + for (int index = 0; index < toolSwitch.StringList.Length; ++index) + { + string str = !toolSwitch.StringList[index].StartsWith("\"", StringComparison.Ordinal) || !toolSwitch.StringList[index].EndsWith("\"", StringComparison.Ordinal) ? Environment.ExpandEnvironmentVariables(toolSwitch.StringList[index]) : Environment.ExpandEnvironmentVariables(toolSwitch.StringList[index].Substring(1, toolSwitch.StringList[index].Length - 2)); + if (!string.IsNullOrEmpty(str)) + { + if (format == CommandLineFormat.ForTracking) + str = str.ToUpperInvariant(); + if (escapeFormat.HasFlag((Enum)EscapeFormat.EscapeTrailingSlash) && + str.IndexOfAny(anyOf) == -1 && + (str.EndsWith("\\", StringComparison.Ordinal) && !str.EndsWith("\\\\", StringComparison.Ordinal))) + str += "\\"; + parameters[index] = str; + } + } + if (string.IsNullOrEmpty(toolSwitch.Separator)) + { + foreach (string parameter in parameters) + builder.AppendSwitchIfNotNull(toolSwitch.SwitchValue, parameter); + } + else + builder.AppendSwitchIfNotNull(toolSwitch.SwitchValue, parameters, toolSwitch.Separator); + } + + private void EmitStringSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) + { + string switchName = string.Empty + toolSwitch.SwitchValue + toolSwitch.Separator; + StringBuilder stringBuilder = new StringBuilder(GetEffectiveArgumentsValues(toolSwitch)); + string str1 = toolSwitch.Value; + if (!toolSwitch.MultipleValues) + { + string str2 = str1.Trim(); + if (!str2.StartsWith("\"", StringComparison.Ordinal)) + { + string str3 = "\"" + str2; + str2 = !str3.EndsWith("\\", StringComparison.Ordinal) || str3.EndsWith("\\\\", StringComparison.Ordinal) ? str3 + "\"" : str3 + "\\\""; + } + stringBuilder.Insert(0, str2); + } + if (switchName.Length == 0 && stringBuilder.ToString().Length == 0) + return; + builder.AppendSwitchUnquotedIfNotNull(switchName, stringBuilder.ToString()); + } + + private void EmitBooleanSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) + { + if (toolSwitch.BooleanValue) + { + if (string.IsNullOrEmpty(toolSwitch.SwitchValue)) + return; + StringBuilder stringBuilder = new StringBuilder(GetEffectiveArgumentsValues(toolSwitch)); + stringBuilder.Insert(0, toolSwitch.Separator); + stringBuilder.Insert(0, toolSwitch.TrueSuffix); + stringBuilder.Insert(0, toolSwitch.SwitchValue); + builder.AppendSwitch(stringBuilder.ToString()); + } + else + this.EmitReversibleBooleanSwitch(builder, toolSwitch); + } + + private void EmitReversibleBooleanSwitch(CommandLineBuilder builder, DToolSwitch toolSwitch) + { + if (string.IsNullOrEmpty(toolSwitch.ReverseSwitchValue)) + return; + string str = toolSwitch.BooleanValue ? toolSwitch.TrueSuffix : toolSwitch.FalseSuffix; + StringBuilder stringBuilder = new StringBuilder(GetEffectiveArgumentsValues(toolSwitch)); + stringBuilder.Insert(0, str); + stringBuilder.Insert(0, toolSwitch.Separator); + stringBuilder.Insert(0, toolSwitch.TrueSuffix); + stringBuilder.Insert(0, toolSwitch.ReverseSwitchValue); + builder.AppendSwitch(stringBuilder.ToString()); + } + + protected string GetEffectiveArgumentsValues(DToolSwitch property) + { + StringBuilder stringBuilder = new StringBuilder(); + CommandLineBuilder commandLineBuilder = new CommandLineBuilder(); + commandLineBuilder.AppendSwitchUnquotedIfNotNull("", stringBuilder.ToString()); + return commandLineBuilder.ToString(); + } + + public void applyParameters(Dictionary parameterValues) + { + var myType = typeof(CompileDOptions); + foreach (string s in opts.switchOrderList) + { + var prop = myType.GetProperty(s); + object val; + if (prop != null && parameterValues.TryGetValue(s, out val)) + { + prop.SetValue(opts, val, null); + } + } + } + + public string GenCmdLine(Dictionary parameters) + { + applyParameters(parameters); + + string commandLineCommands = GenerateCommandLineCommands(); + string responseFileCommands = GenerateResponseFileCommands(CommandLineFormat.ForBuildLog, EscapeFormat.Default); + if (!string.IsNullOrEmpty(commandLineCommands)) + return commandLineCommands + " " + responseFileCommands; + return responseFileCommands; + } + } } diff --git a/msbuild/dcompile.targets b/msbuild/dcompile.targets index 50287a7a..b354fedd 100644 --- a/msbuild/dcompile.targets +++ b/msbuild/dcompile.targets @@ -165,7 +165,7 @@ <_CppStandard Condition="'$(_CppStandard)' == 'fromCpp'">default - + true false $(CL_MPCount) @@ -189,7 +189,6 @@ > - + + Project MultiThreaded diff --git a/msbuild/dmd.xml b/msbuild/dmd.xml index ebb2e5d6..07ff1937 100644 --- a/msbuild/dmd.xml +++ b/msbuild/dmd.xml @@ -48,6 +48,10 @@ Description="compile in version code identified by ident/>= level." Switch="-version=" /> + + diff --git a/msbuild/ldc.xml b/msbuild/ldc.xml index 81fb24d9..41b23197 100644 --- a/msbuild/ldc.xml +++ b/msbuild/ldc.xml @@ -48,6 +48,10 @@ Description="compile in version code identified by ident/>= level." Switch="-version=" /> + + @@ -74,7 +78,7 @@ - diff --git a/nsis/visuald.nsi b/nsis/visuald.nsi index de374fd4..95f10703 100644 --- a/nsis/visuald.nsi +++ b/nsis/visuald.nsi @@ -55,6 +55,7 @@ !include "MUI2.nsh" !include "Memento.nsh" !include "Sections.nsh" + !include "TextFunc.nsh" !include "InstallOptions.nsh" !include "uninstall_helper.nsh" @@ -180,6 +181,14 @@ !define MAGO_EE_KEY AD7Metrics\ExpressionEvaluator\${LANGUAGE_CLSID}\${VENDOR_CLSID} !endif + !define VS2019Filename "vs_community2019.exe" + !define VS2022Filename "vs_community2022.exe" + + !define VS2019Url "https://download.visualstudio.microsoft.com/download/pr/8ab6eab3-e151-4f4d-9ca5-07f8434e46bb/8cc1a4ebd138b5d0c2b97501a198f5eacdc434daa8a5c6564c8e23fdaaad3619/vs_Community.exe" + !define VS2022Url "https://c2rsetup.officeapps.live.com/c2r/downloadVS.aspx?sku=community&channel=Release&version=VS2022" + + !define VSINSTALLER "$PROGRAMFILES\Microsoft Visual Studio\Installer\vs_installer.exe" + ;Default installation folder InstallDir "$PROGRAMFILES\${APPNAME}" @@ -191,6 +200,9 @@ RequestExecutionLevel admin ReserveFile ${DMD_PAGE_INI} + ReserveFile /Plugin INetC.dll + ReserveFile "vsinstall.ini" + ReserveFile "vcinstall.ini" !ifdef DMD ; doesn't work in NSIS3 on appveyor ; ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll" !endif @@ -215,6 +227,9 @@ Var DMDInstallDir Var DInstallDir Var CompilerInstallDir + Var VSVersion + Var VCVersion + Var VCPath ;-------------------------------- ;Interface Settings @@ -227,6 +242,10 @@ !define MUI_TEXT_WELCOME_INFO_TITLE "Welcome to the ${LONG_APPNAME} ${VERSION} Setup Wizard" !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "license" + + Page custom VSInstallPage ValidateVSInstallPage + Page custom VCInstallPage ValidateVCInstallPage + !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY @@ -1575,6 +1594,106 @@ Function .onInit FunctionEnd +;-------------------------------- +!macro DownloadAndRun Filename Url AltUrl + inetc::get /CAPTION "Downloading ${Filename}..." /BANNER "" "${Url}" "$TEMP\${Filename}" + Pop $0 + StrCmp $0 "OK" run_${Filename} + !if `${AltUrl}` != "" + inetc::get /CAPTION "Downloading ${Filename}..." /BANNER "" "${AltUrl}" "$TEMP\${Filename}" + Pop $0 + StrCmp $0 "OK" run_${Filename} + !endif + + ; failed + MessageBox MB_OK|MB_ICONEXCLAMATION "Could not download ${Filename}$\r$\n$\r$\n${Url}" /SD IDOK + + Goto dandr_done_${Filename} + + run_${Filename}: + DetailPrint "Running ${Filename}" + ExecWait "$TEMP\${Filename}" + + Delete "$TEMP\${Filename}" + + dandr_done_${Filename}: +!macroend + +Function VSInstallPage + + Call DetectVC ; detects older versions of VS (but also build tools) + StrCmp $VCVersion "" test_vs + Abort + test_vs: + Call DetectVS + StrCmp $VSVersion "" ask_vs + Abort + ask_vs: + + !insertmacro MUI_HEADER_TEXT "Choose Visual Studio Installation" "Choose the Visual Studio version to install" + !insertmacro INSTALLOPTIONS_EXTRACT "vsinstall.ini" + !insertmacro INSTALLOPTIONS_DISPLAY "vsinstall.ini" + +FunctionEnd + +Function ValidateVSInstallPage + + !insertmacro INSTALLOPTIONS_READ $0 "vsinstall.ini" "Field 2" "State" + StrCmp $0 1 install_vs2022 + !insertmacro INSTALLOPTIONS_READ $0 "vsinstall.ini" "Field 3" "State" + StrCmp $0 1 install_vs2019 + goto done_vs + + install_vs2022: + !insertmacro DownloadAndRun ${VS2022Filename} ${VS2022Url} "" + goto check_vs + + install_vs2019: + !insertmacro DownloadAndRun ${VS2019Filename} ${VS2019Url} "" + goto check_vs + + check_vs: + Call DetectVS + StrCmp $VSVersion "" 0 done_vs + Abort + + done_vs: + +FunctionEnd + +Function VCInstallPage + + Call DetectVC + StrCmp $VCVersion "" ask_vs + Abort + ask_vs: + + !insertmacro MUI_HEADER_TEXT "Visual C++ Installation" "Install the C++ environment in Visual Studio" + !insertmacro INSTALLOPTIONS_EXTRACT "vcinstall.ini" + !insertmacro INSTALLOPTIONS_DISPLAY "vcinstall.ini" + +FunctionEnd + +Function ValidateVCInstallPage + + !insertmacro INSTALLOPTIONS_READ $0 "vcinstall.ini" "Field 2" "State" + StrCmp $0 1 run_vs_installer + goto done_vc + + run_vs_installer: + DetailPrint "Running ${VSINSTALLER}" + ExecWait "${VSINSTALLER}" + goto check_vc + + check_vc: + Call DetectVC + StrCmp $VVVersion "" 0 done_vc + Abort + + done_vc: + +FunctionEnd + ;-------------------------------- Function DMDInstallPage @@ -2128,3 +2247,103 @@ Function InstallForVS2022 FunctionEnd !endif ; VS2022 + +; ----------------------------------------- + +Function DetectVS + ClearErrors + + StrCpy $VSVersion "" + StrCpy $0 "$PROGRAMFILES\Microsoft Visual Studio\Installer\vswhere.exe" + IfFileExists "$0" 0 no_vswhere + nsExec::ExecToStack '"$0" -products * -prerelease -property installationPath' + Pop $1 ; stdout: path + Pop $0 ; result code + StrCmp $0 0 no_vswhere + StrCmp $1 "" no_vswhere + StrCpy $VSVersion "VS2017+" ; value not used, but only checked if empty + no_vswhere: + +FunctionEnd + +Function DetectVC + ClearErrors + + StrCpy $0 "$PROGRAMFILES\Microsoft Visual Studio\Installer\vswhere.exe" + IfFileExists "$0" 0 no_vswhere + nsExec::ExecToStack '"$0" -products * -prerelease -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath' + Pop $1 ; stdout: path + Pop $0 ; result code + StrCmp $0 0 no_vswhere + StrCmp $1 "" no_vswhere + StrCpy $VCVersion "VC2017+" ; value not used, but only checked if empty + StrCpy $VCPath $1 + Goto done + no_vswhere: + + Call DetectVS2019_InstallationFolder + StrCpy $1 "VC2019" + StrCmp $0 "" not_vc2019 vs2019 + vs2019: + ${LineRead} "$0\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" "1" $2 + IfErrors not_vc2019 + StrCpy $0 "$0\VC\Tools\MSVC\$2" + Goto done_vs + not_vc2019: + + Call DetectVS2019BuildTools_InstallationFolder + StrCpy $1 "VC2019BT" + StrCmp $0 "" not_vc2019BT vs2019BT + vs2019BT: + ${LineRead} "$0\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" "1" $2 + IfErrors not_vc2019BT + StrCpy $0 "$0\VC\Tools\MSVC\$2" + Goto done_vs + not_vc2019BT: + + ReadRegStr $0 HKLM "SOFTWARE\Microsoft\VisualStudio\SxS\VS7" "15.0" + StrCpy $1 "VC2017" + IfErrors not_vc2017 + ${LineRead} "$0\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" "1" $2 + IfErrors not_vc2017 + StrCpy $0 "$0\VC\Tools\MSVC\$2" + Goto done_vs + not_vc2017: + + Call DetectVS2017BuildTools_InstallationFolder + StrCpy $1 "VC2017BT" + StrCmp $0 "" not_vc2017BT vs2017BT + vs2017BT: + ${LineRead} "$0\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" "1" $2 + IfErrors not_vc2017BT + StrCpy $0 "$0\VC\Tools\MSVC\$2" + Goto done_vs + not_vc2017BT: + + ClearErrors + ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\14.0\Setup\VC" "ProductDir" + StrCpy $1 "VC2015" + IfErrors 0 done_vs + ClearErrors + ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\12.0\Setup\VC" "ProductDir" + StrCpy $1 "VC2013" + IfErrors 0 done_vs + ClearErrors + ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\11.0\Setup\VC" "ProductDir" + StrCpy $1 "VC2012" + IfErrors 0 done_vs + ClearErrors + ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\10.0\Setup\VC" "ProductDir" + StrCpy $1 "VC2010" + IfErrors 0 done_vs + ClearErrors + ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\9.0\Setup\VC" "ProductDir" + StrCpy $1 "VC2008" + IfErrors done done_vs + + done_vs: + StrCpy $VCPath $0 + StrCpy $VCVersion $1 + done: + +FunctionEnd diff --git a/stdext/stdext.visualdproj b/stdext/stdext.visualdproj index e579ba07..b81d3a3e 100644 --- a/stdext/stdext.visualdproj +++ b/stdext/stdext.visualdproj @@ -916,7 +916,7 @@ 0 0 0 - 0 + 1 0 1 0 diff --git a/stdext/string.d b/stdext/string.d index d37fdd49..7343b177 100644 --- a/stdext/string.d +++ b/stdext/string.d @@ -65,6 +65,72 @@ string[] tokenizeArgs(string text, bool semi_is_seperator = true, bool space_is_ return args; } +// Microsoft like quoting +string[] splitCmdLine(string cmdline, bool removeSlashes = true) +{ + string[] args; + for (size_t p = 0; p < cmdline.length; p++) + { + if (cmdline[p] == ' ' || cmdline[p] == '\t') + continue; + size_t q = p; + size_t quotes = 0; + while (q < cmdline.length) + { + auto c = cmdline[q]; + if ((quotes & 1) == 0 && (c == ' ' || c == '\t')) + break; + q++; + if (c == '\\') + { + size_t slash = q - 1; + while (q < cmdline.length && cmdline[q] == '\\') + q++; + if (q < cmdline.length && cmdline[q] == '"') + { + size_t slashes = q - slash; + if (removeSlashes) + { + // strip half the slashes, if odd, escape the '"' + size_t nq = slash + (slashes >> 1); + cmdline = cmdline[0..nq] ~ cmdline[q .. $]; + q = nq + 1; + } + if (slashes & 1) + q++; + else + quotes++; + } + } + else if (c == '"') + { + quotes++; + } + } + auto arg = cmdline[p..q]; + if (quotes == 2 && arg[0] == '"' && arg[$-1] == '"') + arg = arg[1..$-1]; + args ~= arg; + p = q; + } + return args; +} + +unittest +{ + string[] args = splitCmdLine("a b c"); + assert(args[0] == "a" && args[1] == "b" && args[2] == "c"); + + args = splitCmdLine(q"(a "b b" c)"); + assert(args[0] == "a" && args[1] == "b b" && args[2] == "c"); + + args = splitCmdLine(q"(a "b\ b\\" c)"); + assert(args[0] == "a" && args[1] == q"(b\ b\)" && args[2] == "c"); + + args = splitCmdLine(q"(a "b\" b\\" c)"); + assert(args[0] == "a" && args[1] == q"(b" b\)" && args[2] == "c"); +} + string unquoteArgument(string arg) { if(arg.length <= 0 || arg[0] != '\"') @@ -76,6 +142,14 @@ string unquoteArgument(string arg) return arg[1..$-1]; } +string quoteArgument(string arg) +{ + if(arg.indexOf(' ') < 0 && arg.indexOf('\t') < 0) + return arg; + + return "\"" ~ arg ~ "\""; +} + string replaceCrLfSemi(string s) { return replace(replace(s, "\n", ";"), "\r", ""); diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 09db2a83..f49c420e 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 09db2a83f0098572d59e7ffdbfc8bf16383a490f +Subproject commit f49c420e8197f61346d66ce0ecbd10088bd04625 diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index c22613ea..b34d44d7 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -13,6 +13,7 @@ import dmd.astenums; import dmd.builtin; import dmd.cond; import dmd.compiler; +import dmd.cpreprocess; import dmd.ctfeexpr; import dmd.dclass; import dmd.declaration; @@ -39,6 +40,8 @@ import dmd.common.outbuffer; import dmd.root.ctfloat; import std.string; +import stdext.path; +import stdext.string; import core.stdc.string; //////////////////////////////////////////////////////////////// @@ -114,6 +117,11 @@ enum string[2][] dmdStatics = ["_D3dmd7dmodule6Module18loadCoreStdcConfigFZ16core_stdc_configCQCiQChQCc", "Module"], // EscapeState.reset not accessible in package dmd ["_D3dmd6escape11EscapeState17scopeInferFailureHiCQBu10rootobject10RootObject", "EscapeInfer" ], + + // 2.10x + ["_D3dmd7typesem21getComplexLibraryTypeFSQBl8location3LocPSQCd6dscope5ScopeEQCu8astenums2TYZ13complex_floatCQEa5mtype4Type", "Type" ], + ["_D3dmd7typesem21getComplexLibraryTypeFSQBl8location3LocPSQCd6dscope5ScopeEQCu8astenums2TYZ14complex_doubleCQEb5mtype4Type", "Type" ], + ["_D3dmd7typesem21getComplexLibraryTypeFSQBl8location3LocPSQCd6dscope5ScopeEQCu8astenums2TYZ12complex_realCQDz5mtype4Type", "Type" ], ]; string cmangled(string s) @@ -288,6 +296,8 @@ void dmdSetupParams(const ref Options opts) global = global.init; global._init(); + global.preprocess = &preprocess; + target.os = Target.OS.Windows; global.params.v.errorLimit = 0; global.params.v.color = false; @@ -318,7 +328,11 @@ void dmdSetupParams(const ref Options opts) target.cpu = CPU.baseline; target.isLP64 = opts.x64; - string[] cli = opts.cmdline.split(' '); + string[] cli = splitCmdLine(opts.cmdline); + string workdir; + foreach(opt; cli) + if (opt.startsWith("-workdir=")) + workdir = unquoteArgument(opt[9..$]); foreach(opt; cli) { switch(opt) @@ -355,7 +369,20 @@ void dmdSetupParams(const ref Options opts) case "-preview=shortenedMethods": global.params.shortenedMethods = true; break; case "-preview=fixImmutableConv": global.params.fixImmutableConv = true; break; case "-preview=systemVariables": global.params.systemVariables = FeatureState.enabled; break; - default: break; + default: + if (opt.startsWith("-P")) + { + string cppopt = opt[2..$]; + if (cppopt.startsWith("-I")) + { + string dir = unquoteArgument(cppopt[2..$]); + string ndir = makeFilenameAbsolute(dir, workdir); + if (dir != ndir) + cppopt = "-I" ~ quoteArgument(ndir); + } + global.params.cppswitches.push(toStringz(cppopt)); + } + break; } } // global.params.versionlevel = opts.versionLevel; @@ -395,7 +422,11 @@ void dmdSetupParams(const ref Options opts) global.path.setDim(0); foreach(i; opts.importDirs) - global.path.push(ImportPathInfo(toStringz(i))); + { + auto path = toStringz(i); + global.importPaths.push(path); + global.path.push(ImportPathInfo(path)); + } global.filePath.setDim(0); foreach(i; opts.stringImportDirs) diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 80d308be..d98e2eb0 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -2291,6 +2291,7 @@ + @@ -2344,6 +2345,7 @@ + @@ -2405,7 +2407,7 @@ - + @@ -2451,6 +2453,7 @@ + diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 28ca54d2..61996022 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -95,7 +95,7 @@ class AnalysisContext if (md.packages.length != packages.length) continue L_nextMod; for (size_t p = 0; p < packages.length; p++) - if (cast(Identifier)md.packages[p] != md.packages[p]) + if (cast(Identifier)md.packages[p] != packages[p]) continue L_nextMod; } return mi.createSemanticModule(false); diff --git a/visuald/Resources/pkgcmd.vsct b/visuald/Resources/pkgcmd.vsct index 34ba99aa..d070fc68 100644 --- a/visuald/Resources/pkgcmd.vsct +++ b/visuald/Resources/pkgcmd.vsct @@ -34,13 +34,16 @@ - + - + - + + + + @@ -132,7 +135,7 @@ + +