1 module reggae.dub; 2 3 import reggae.build; 4 import reggae.rules; 5 import reggae.types; 6 import reggae.config: dflags, perModule; 7 import reggae.sorting; 8 9 public import std.typecons: Yes, No; 10 import std.typecons: Flag; 11 import std.algorithm: map, filter; 12 import std.array: array, join; 13 import std.path: buildPath; 14 import std.traits: isCallable; 15 16 17 struct DubPackage { 18 string name; 19 string path; 20 string mainSourceFile; 21 string targetFileName; 22 string[] flags; 23 string[] importPaths; 24 string[] stringImportPaths; 25 string[] files; 26 string targetType; 27 string[] versions; 28 string[] dependencies; 29 string[] libs; 30 } 31 32 33 struct DubInfo { 34 DubPackage[] packages; 35 36 Target[] toTargets(Flag!"main" includeMain = Yes.main) @safe const { 37 Target[] targets; 38 39 foreach(const i, const dubPackage; packages) { 40 const importPaths = dubPackage.allOf!(a => a.packagePaths(a.importPaths))(packages); 41 const stringImportPaths = dubPackage.allOf!(a => a.packagePaths(a.stringImportPaths))(packages); 42 const versions = dubPackage.allOf!(a => a.versions)(packages); 43 //the path must be explicit for the other packages, implicit for the "main" 44 //package 45 const projDir = i == 0 ? "" : dubPackage.path; 46 47 immutable flags = dubPackage.flags.join(" ") ~ dflags ~ " " ~ 48 versions.map!(a => "-version=" ~ a).join(" "); 49 50 auto files = dubPackage. 51 files. 52 filter!(a => includeMain || a != dubPackage.mainSourceFile). 53 map!(a => buildPath(dubPackage.path, a)); 54 55 targets ~= dCompileGrouped(files.array, flags, importPaths, stringImportPaths, projDir); 56 } 57 58 return targets; 59 } 60 61 //@trusted: array 62 Target mainTarget(string flagsStr = "") @trusted const { 63 string[] libs; 64 foreach(p; packages) { 65 libs ~= p.libs; 66 } 67 68 const pack = packages[0]; 69 auto flags = flagsStr.splitter(" ").array; 70 flags ~= pack.targetType == "library" ? ["-lib"] : []; 71 //hacky hack for dub describe on vibe.d projects 72 flags ~= libs.filter!(a => a != "ev").map!(a => "-L-l" ~ a).array; 73 return dLink(packages[0].targetFileName, toTargets(), flags.join(",")); 74 } 75 76 string[] targetImportPaths() @trusted nothrow const { 77 return packages[0].allOf!(a => a.packagePaths(a.importPaths))(packages); 78 } 79 80 string[][] fetchCommands() @safe pure nothrow const { 81 return packages[0].dependencies.map!(a => ["dub", "fetch", a]).array; 82 } 83 } 84 85 86 private auto packagePaths(in DubPackage pack, in string[] paths) @trusted nothrow { 87 return paths.map!(a => buildPath(pack.path, a)).array; 88 } 89 90 //@trusted because of map.array 91 private string[] allOf(alias F)(in DubPackage pack, in DubPackage[] packages) @trusted nothrow { 92 string[] paths; 93 //foreach(d; [pack.name] ~ pack.dependencies) doesn't compile with CTFE 94 //it seems to have to do with constness, replace string[] with const(string)[] 95 //and it won't compile 96 string[] dependencies = [pack.name]; 97 dependencies ~= pack.dependencies; 98 foreach(dependency; dependencies) { 99 import std.range; 100 const depPack = packages.find!(a => a.name == dependency).front; 101 paths ~= F(depPack).array; 102 } 103 return paths; 104 } 105 106 107 Target dubMainTarget(string flags)() { 108 import reggae.config; 109 return dubInfo.mainTarget(flags); 110 } 111 112 113 Target dExeWithDubObjs(ExeName exeName, 114 Configuration config = Configuration("default"), 115 alias objsFunction = () { Target[] t; return t; }, 116 Flag!"main" includeMain = Yes.main, 117 Flags flags = Flags())() 118 if(isCallable!objsFunction) { 119 120 import reggae.config; 121 return dLink(exeName.name, 122 objsFunction() ~ configToDubInfo[config.config].toTargets(includeMain), 123 flags.flags); 124 }