1 /** 2 LDC compiler support. 3 4 Copyright: © 2013-2013 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.ldc; 9 10 import dub.compilers.compiler; 11 import dub.internal.utils; 12 import dub.internal.vibecompat.core.log; 13 import dub.internal.vibecompat.inet.path; 14 import dub.platform; 15 16 import std.algorithm; 17 import std.array; 18 import std.conv; 19 import std.exception; 20 import std.file; 21 import std.process; 22 import std.random; 23 import std.typecons; 24 25 26 class LdcCompiler : Compiler { 27 private static immutable s_options = [ 28 tuple(BuildOptions.debugMode, ["-d-debug"]), 29 tuple(BuildOptions.releaseMode, ["-release"]), 30 //tuple(BuildOptions.coverage, ["-?"]), 31 tuple(BuildOptions.debugInfo, ["-g"]), 32 tuple(BuildOptions.debugInfoC, ["-gc"]), 33 //tuple(BuildOptions.alwaysStackFrame, ["-?"]), 34 //tuple(BuildOptions.stackStomping, ["-?"]), 35 tuple(BuildOptions.inline, ["-enable-inlining"]), 36 tuple(BuildOptions.noBoundsCheck, ["-disable-boundscheck"]), 37 tuple(BuildOptions.optimize, ["-O"]), 38 //tuple(BuildOptions.profile, ["-?"]), 39 tuple(BuildOptions.unittests, ["-unittest"]), 40 tuple(BuildOptions.verbose, ["-v"]), 41 tuple(BuildOptions.ignoreUnknownPragmas, ["-ignore"]), 42 tuple(BuildOptions.syntaxOnly, ["-o-"]), 43 tuple(BuildOptions.warnings, ["-wi"]), 44 tuple(BuildOptions.warningsAsErrors, ["-w"]), 45 tuple(BuildOptions.ignoreDeprecations, ["-d"]), 46 tuple(BuildOptions.deprecationWarnings, ["-dw"]), 47 tuple(BuildOptions.deprecationErrors, ["-de"]), 48 tuple(BuildOptions.property, ["-property"]), 49 ]; 50 51 @property string name() const { return "ldc"; } 52 53 BuildPlatform determinePlatform(ref BuildSettings settings, string compiler_binary, string arch_override) 54 { 55 // TODO: determine platform by invoking the compiler instead 56 BuildPlatform build_platform; 57 build_platform.platform = .determinePlatform(); 58 build_platform.architecture = .determineArchitecture(); 59 build_platform.compiler = this.name; 60 build_platform.compilerBinary = compiler_binary; 61 62 switch (arch_override) { 63 default: throw new Exception("Unsupported architecture: "~arch_override); 64 case "": break; 65 case "x86": 66 build_platform.architecture = ["x86"]; 67 settings.addDFlags("-march=x86"); 68 break; 69 case "x86_64": 70 build_platform.architecture = ["x86_64"]; 71 settings.addDFlags("-march=x86_64"); 72 break; 73 } 74 75 return build_platform; 76 } 77 78 void prepareBuildSettings(ref BuildSettings settings, BuildSetting fields = BuildSetting.all) 79 { 80 enforceBuildRequirements(settings); 81 82 if (!(fields & BuildSetting.options)) { 83 foreach (t; s_options) 84 if (settings.options & t[0]) 85 settings.addDFlags(t[1]); 86 } 87 88 // since LDC always outputs multiple object files, avoid conflicts by default 89 settings.addDFlags("-oq", "-od=.dub/obj"); 90 91 if (!(fields & BuildSetting.libs)) { 92 resolveLibs(settings); 93 settings.addLFlags(settings.libs.map!(l => "-l"~l)().array()); 94 } 95 96 if (!(fields & BuildSetting.versions)) { 97 settings.addDFlags(settings.versions.map!(s => "-d-version="~s)().array()); 98 settings.versions = null; 99 } 100 101 if (!(fields & BuildSetting.debugVersions)) { 102 settings.addDFlags(settings.debugVersions.map!(s => "-d-debug="~s)().array()); 103 settings.debugVersions = null; 104 } 105 106 if (!(fields & BuildSetting.importPaths)) { 107 settings.addDFlags(settings.importPaths.map!(s => "-I"~s)().array()); 108 settings.importPaths = null; 109 } 110 111 if (!(fields & BuildSetting.stringImportPaths)) { 112 settings.addDFlags(settings.stringImportPaths.map!(s => "-J"~s)().array()); 113 settings.stringImportPaths = null; 114 } 115 116 if (!(fields & BuildSetting.sourceFiles)) { 117 settings.addDFlags(settings.sourceFiles); 118 settings.sourceFiles = null; 119 } 120 121 if (!(fields & BuildSetting.lflags)) { 122 settings.addDFlags(settings.lflags.map!(s => "-L="~s)().array()); 123 settings.lflags = null; 124 } 125 126 assert(fields & BuildSetting.dflags); 127 assert(fields & BuildSetting.copyFiles); 128 } 129 130 void extractBuildOptions(ref BuildSettings settings) 131 { 132 Appender!(string[]) newflags; 133 next_flag: foreach (f; settings.dflags) { 134 foreach (t; s_options) 135 if (t[1].canFind(f)) { 136 settings.options |= t[0]; 137 continue next_flag; 138 } 139 if (f.startsWith("-d-version=")) settings.addVersions(f[11 .. $]); 140 else if (f.startsWith("-d-debug=")) settings.addDebugVersions(f[9 .. $]); 141 else newflags ~= f; 142 } 143 settings.dflags = newflags.data; 144 } 145 146 void setTarget(ref BuildSettings settings, in BuildPlatform platform) 147 { 148 final switch (settings.targetType) { 149 case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); 150 case TargetType.none: assert(false, "Invalid target type: none"); 151 case TargetType.sourceLibrary: assert(false, "Invalid target type: sourceLibrary"); 152 case TargetType.executable: break; 153 case TargetType.library: 154 case TargetType.staticLibrary: 155 assert(false, "No LDC static libraries supported"); 156 case TargetType.dynamicLibrary: 157 assert(false, "No LDC dynamic libraries supported"); 158 } 159 160 auto tpath = Path(settings.targetPath) ~ getTargetFileName(settings, platform); 161 settings.addDFlags("-of"~tpath.toNativeString()); 162 } 163 164 void invoke(in BuildSettings settings, in BuildPlatform platform) 165 { 166 auto res_file = getTempDir() ~ ("dub-build-"~uniform(0, uint.max).to!string~"-.rsp"); 167 std.file.write(res_file.toNativeString(), join(cast(string[])settings.dflags, "\n")); 168 scope (exit) remove(res_file.toNativeString()); 169 170 logDiagnostic("%s %s", platform.compilerBinary, join(cast(string[])settings.dflags, " ")); 171 auto compiler_pid = spawnProcess([platform.compilerBinary, "@"~res_file.toNativeString()]); 172 auto result = compiler_pid.wait(); 173 enforce(result == 0, "LDC compile run failed with exit code "~to!string(result)); 174 } 175 176 void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects) 177 { 178 assert(false, "Separate linking not implemented for GDC"); 179 } 180 }