1 /** 2 Build settings definitions. 3 4 Copyright: © 2013-2014 rejectedsoftware e.K. 5 License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 6 Authors: Sönke Ludwig 7 */ 8 module dub.compilers.buildsettings; 9 10 import dub.internal.vibecompat.inet.path; 11 12 import std.array : array; 13 import std.algorithm : filter; 14 import std.path : globMatch; 15 16 17 /// BuildPlatform specific settings, like needed libraries or additional 18 /// include paths. 19 struct BuildSettings { 20 TargetType targetType; 21 string targetPath; 22 string targetName; 23 string workingDirectory; 24 string mainSourceFile; 25 string[] dflags; 26 string[] lflags; 27 string[] libs; 28 string[] sourceFiles; 29 string[] copyFiles; 30 string[] versions; 31 string[] debugVersions; 32 string[] importPaths; 33 string[] stringImportPaths; 34 string[] importFiles; 35 string[] stringImportFiles; 36 string[] preGenerateCommands; 37 string[] postGenerateCommands; 38 string[] preBuildCommands; 39 string[] postBuildCommands; 40 BuildRequirements requirements; 41 BuildOptions options; 42 43 BuildSettings dup() 44 const { 45 BuildSettings ret; 46 foreach (m; __traits(allMembers, BuildSettings)) { 47 static if (is(typeof(__traits(getMember, ret, m) = __traits(getMember, this, m).dup))) 48 __traits(getMember, ret, m) = __traits(getMember, this, m).dup; 49 else static if (is(typeof(__traits(getMember, ret, m) = __traits(getMember, this, m)))) 50 __traits(getMember, ret, m) = __traits(getMember, this, m); 51 } 52 assert(ret.targetType == targetType); 53 assert(ret.targetName == targetName); 54 assert(ret.importPaths == importPaths); 55 return ret; 56 } 57 58 void add(in BuildSettings bs) 59 { 60 addDFlags(bs.dflags); 61 addLFlags(bs.lflags); 62 addLibs(bs.libs); 63 addSourceFiles(bs.sourceFiles); 64 addCopyFiles(bs.copyFiles); 65 addVersions(bs.versions); 66 addDebugVersions(bs.debugVersions); 67 addImportPaths(bs.importPaths); 68 addStringImportPaths(bs.stringImportPaths); 69 addImportFiles(bs.importFiles); 70 addStringImportFiles(bs.stringImportFiles); 71 addPreGenerateCommands(bs.preGenerateCommands); 72 addPostGenerateCommands(bs.postGenerateCommands); 73 addPreBuildCommands(bs.preBuildCommands); 74 addPostBuildCommands(bs.postBuildCommands); 75 } 76 77 void addDFlags(in string[] value...) { dflags ~= value; } 78 void removeDFlags(in string[] value...) { remove(dflags, value); } 79 void addLFlags(in string[] value...) { lflags ~= value; } 80 void addLibs(in string[] value...) { add(libs, value); } 81 void addSourceFiles(in string[] value...) { add(sourceFiles, value); } 82 void prependSourceFiles(in string[] value...) { prepend(sourceFiles, value); } 83 void removeSourceFiles(in string[] value...) { removePaths(sourceFiles, value); } 84 void addCopyFiles(in string[] value...) { add(copyFiles, value); } 85 void addVersions(in string[] value...) { add(versions, value); } 86 void addDebugVersions(in string[] value...) { add(debugVersions, value); } 87 void addImportPaths(in string[] value...) { add(importPaths, value); } 88 void addStringImportPaths(in string[] value...) { add(stringImportPaths, value); } 89 void prependStringImportPaths(in string[] value...) { prepend(stringImportPaths, value); } 90 void addImportFiles(in string[] value...) { add(importFiles, value); } 91 void removeImportFiles(in string[] value...) { removePaths(importFiles, value); } 92 void addStringImportFiles(in string[] value...) { addSI(stringImportFiles, value); } 93 void addPreGenerateCommands(in string[] value...) { add(preGenerateCommands, value, false); } 94 void addPostGenerateCommands(in string[] value...) { add(postGenerateCommands, value, false); } 95 void addPreBuildCommands(in string[] value...) { add(preBuildCommands, value, false); } 96 void addPostBuildCommands(in string[] value...) { add(postBuildCommands, value, false); } 97 void addRequirements(in BuildRequirements[] value...) { foreach (v; value) this.requirements |= v; } 98 void addOptions(in BuildOptions[] value...) { foreach (v; value) this.options |= v; } 99 void removeOptions(in BuildOptions[] value...) { foreach (v; value) this.options &= ~v; } 100 101 // Adds vals to arr without adding duplicates. 102 private void add(ref string[] arr, in string[] vals, bool no_duplicates = true) 103 { 104 if (!no_duplicates) { 105 arr ~= vals; 106 return; 107 } 108 109 foreach (v; vals) { 110 bool found = false; 111 foreach (i; 0 .. arr.length) 112 if (arr[i] == v) { 113 found = true; 114 break; 115 } 116 if (!found) arr ~= v; 117 } 118 } 119 120 private void prepend(ref string[] arr, in string[] vals, bool no_duplicates = true) 121 { 122 if (!no_duplicates) { 123 arr = vals ~ arr; 124 return; 125 } 126 127 foreach_reverse (v; vals) { 128 bool found = false; 129 foreach (i; 0 .. arr.length) 130 if (arr[i] == v) { 131 found = true; 132 break; 133 } 134 if (!found) arr = v ~ arr; 135 } 136 } 137 138 // add string import files (avoids file name duplicates in addition to path duplicates) 139 private void addSI(ref string[] arr, in string[] vals) 140 { 141 outer: 142 foreach (v; vals) { 143 auto vh = Path(v).head; 144 foreach (ve; arr) { 145 if (Path(ve).head == vh) 146 continue outer; 147 } 148 arr ~= v; 149 } 150 } 151 152 private void removePaths(ref string[] arr, in string[] vals) 153 { 154 bool matches(string s) 155 { 156 foreach (p; vals) 157 if (Path(s) == Path(p) || globMatch(s, p)) 158 return true; 159 return false; 160 } 161 arr = arr.filter!(s => !matches(s))().array(); 162 } 163 164 private void remove(ref string[] arr, in string[] vals) 165 { 166 bool matches(string s) 167 { 168 foreach (p; vals) 169 if (s == p) 170 return true; 171 return false; 172 } 173 arr = arr.filter!(s => !matches(s))().array(); 174 } 175 } 176 177 enum BuildSetting { 178 dflags = 1<<0, 179 lflags = 1<<1, 180 libs = 1<<2, 181 sourceFiles = 1<<3, 182 copyFiles = 1<<4, 183 versions = 1<<5, 184 debugVersions = 1<<6, 185 importPaths = 1<<7, 186 stringImportPaths = 1<<8, 187 options = 1<<9, 188 none = 0, 189 commandLine = dflags|copyFiles, 190 commandLineSeparate = commandLine|lflags, 191 all = dflags|lflags|libs|sourceFiles|copyFiles|versions|debugVersions|importPaths|stringImportPaths|options, 192 noOptions = all & ~options 193 } 194 195 enum TargetType { 196 autodetect, 197 none, 198 executable, 199 library, 200 sourceLibrary, 201 dynamicLibrary, 202 staticLibrary, 203 object 204 } 205 206 enum BuildRequirements { 207 none = 0, /// No special requirements 208 allowWarnings = 1<<0, /// Warnings do not abort compilation 209 silenceWarnings = 1<<1, /// Don't show warnings 210 disallowDeprecations = 1<<2, /// Using deprecated features aborts compilation 211 silenceDeprecations = 1<<3, /// Don't show deprecation warnings 212 disallowInlining = 1<<4, /// Avoid function inlining, even in release builds 213 disallowOptimization = 1<<5, /// Avoid optimizations, even in release builds 214 requireBoundsCheck = 1<<6, /// Always perform bounds checks 215 requireContracts = 1<<7, /// Leave assertions and contracts enabled in release builds 216 relaxProperties = 1<<8, /// DEPRECATED: Do not enforce strict property handling (-property) 217 noDefaultFlags = 1<<9, /// Do not issue any of the default build flags (e.g. -debug, -w, -property etc.) - use only for development purposes 218 } 219 220 enum BuildOptions { 221 none = 0, /// Use compiler defaults 222 debugMode = 1<<0, /// Compile in debug mode (enables contracts, -debug) 223 releaseMode = 1<<1, /// Compile in release mode (disables assertions and bounds checks, -release) 224 coverage = 1<<2, /// Enable code coverage analysis (-cov) 225 debugInfo = 1<<3, /// Enable symbolic debug information (-g) 226 debugInfoC = 1<<4, /// Enable symbolic debug information in C compatible form (-gc) 227 alwaysStackFrame = 1<<5, /// Always generate a stack frame (-gs) 228 stackStomping = 1<<6, /// Perform stack stomping (-gx) 229 inline = 1<<7, /// Perform function inlining (-inline) 230 noBoundsCheck = 1<<8, /// Disable all bounds checking (-noboundscheck) 231 optimize = 1<<9, /// Enable optimizations (-O) 232 profile = 1<<10, /// Emit profiling code (-profile) 233 unittests = 1<<11, /// Compile unit tests (-unittest) 234 verbose = 1<<12, /// Verbose compiler output (-v) 235 ignoreUnknownPragmas = 1<<13, /// Ignores unknown pragmas during compilation (-ignore) 236 syntaxOnly = 1<<14, /// Don't generate object files (-o-) 237 warnings = 1<<15, /// Enable warnings (-wi) 238 warningsAsErrors = 1<<16, /// Treat warnings as errors (-w) 239 ignoreDeprecations = 1<<17, /// Do not warn about using deprecated features (-d) 240 deprecationWarnings = 1<<18, /// Warn about using deprecated features (-dw) 241 deprecationErrors = 1<<19, /// Stop compilation upon usage of deprecated features (-de) 242 property = 1<<20, /// DEPRECATED: Enforce property syntax (-property) 243 }