1 /** 2 A module for providing interop between reggae and dub 3 */ 4 5 module reggae.dub.interop; 6 7 import reggae.options; 8 import reggae.dub.info; 9 import reggae.dub.call; 10 import reggae.dub.json; 11 import std.stdio; 12 import std.exception; 13 import std.conv; 14 import std.process; 15 16 DubInfo[string] gDubInfos; 17 18 19 @safe: 20 21 void maybeCreateReggaefile(in Options options) { 22 if(options.isDubProject && !projectBuildFile(options).exists) { 23 createReggaefile(options); 24 } 25 } 26 27 void createReggaefile(in Options options) { 28 writeln("[Reggae] Creating reggaefile.d from dub information"); 29 auto file = File("reggaefile.d", "w"); 30 file.writeln("import reggae;"); 31 file.writeln("mixin build!dubDefaultTarget;"); 32 33 if(!options.noFetch) dubFetch(_getDubInfo(options)); 34 } 35 36 37 private DubInfo _getDubInfo(in Options options) { 38 39 if("default" !in gDubInfos) { 40 immutable dubBuildArgs = ["dub", "--annotate", "build", "--compiler=dmd", "--print-configs"]; 41 immutable dubBuildOutput = _callDub(options, dubBuildArgs); 42 immutable configs = getConfigurations(dubBuildOutput); 43 44 if(configs.configurations.empty) { 45 immutable descArgs = ["dub", "describe"]; 46 immutable descOutput = _callDub(options, descArgs); 47 gDubInfos["default"] = getDubInfo(descOutput); 48 } else { 49 foreach(config; configs.configurations) { 50 immutable descArgs = ["dub", "describe", "-c", config]; 51 immutable descOutput = _callDub(options, descArgs); 52 gDubInfos[config] = getDubInfo(descOutput); 53 } 54 gDubInfos["default"] = gDubInfos[configs.default_]; 55 } 56 } 57 58 return gDubInfos["default"]; 59 } 60 61 62 private string _callDub(in Options options, in string[] args) { 63 import std.process; 64 const string[string] env = null; 65 Config config = Config.none; 66 size_t maxOutput = size_t.max; 67 immutable workDir = options.projectPath; 68 69 immutable ret = execute(args, env, config, maxOutput, workDir); 70 enforce(ret.status == 0, text("Error calling ", args.join(" "), ":\n", 71 ret.output)); 72 return ret.output; 73 } 74 75 private void dubFetch(in DubInfo dubInfo) { 76 foreach(cmd; dubInfo.fetchCommands) { 77 immutable cmdStr = "'" ~ cmd.join(" ") ~ "'"; 78 writeln("Fetching package with cmd ", cmdStr); 79 immutable ret = execute(cmd); 80 if(ret.status) { 81 () @trusted { 82 stderr.writeln("Could not execute dub fetch with:\n", cmd.join(" "), "\n", 83 ret.output); 84 }(); 85 } 86 } 87 } 88 89 90 void writeDubConfig(in Options options, File file) { 91 file.writeln("import reggae.dub.info;"); 92 if(options.isDubProject) { 93 file.writeln("enum isDubProject = true;"); 94 auto dubInfo = _getDubInfo(options); 95 immutable targetType = dubInfo.packages[0].targetType; 96 enforce(targetType == "executable" || targetType == "library" || targetType == "staticLibrary", 97 text("Unsupported dub targetType '", targetType, "'")); 98 99 file.writeln(`const configToDubInfo = assocList([`); 100 101 const keys = () @trusted { return gDubInfos.keys; }(); 102 foreach(config; keys) { 103 file.writeln(` assocEntry("`, config, `", `, gDubInfos[config], `),`); 104 } 105 file.writeln(`]);`); 106 file.writeln; 107 } else { 108 file.writeln("enum isDubProject = false;"); 109 } 110 }