1 module reggae.buildgen;
2 
3 import reggae.build;
4 import reggae.options;
5 import reggae.types;
6 import reggae.backend;
7 import reggae.reflect;
8 
9 import std.stdio;
10 
11 /**
12  Creates a build generator out of a module and a list of top-level targets.
13  This will define a function with the signature $(D Build buildFunc()) in
14  the calling module and a $(D main) entry point function for a command-line
15  executable.
16  */
17 mixin template buildGen(string buildModule, targets...) {
18     mixin buildImpl!targets;
19     mixin BuildGenMain!buildModule;
20 }
21 
22 mixin template BuildGenMain(string buildModule = "reggaefile") {
23     import std.stdio;
24 
25     int main(string[] args) {
26         try {
27             import reggae.config: options;
28             generateBuildFor!(buildModule)(options, args); //the user's build description
29         } catch(Exception ex) {
30             stderr.writeln(ex.msg);
31             return 1;
32         }
33 
34         return 0;
35     }
36 }
37 
38 void generateBuildFor(alias module_)(in Options options, string[] args) {
39     const buildFunc = getBuild!(module_); //get the function to call by CT reflection
40     const build = buildFunc(); //actually call the function to get the build description
41     generateBuild(build, options, args);
42 }
43 
44 void generateBuild(in Build build, in Options options, string[] args = []) {
45     final switch(options.backend) with(Backend) {
46 
47         case make:
48             handleMake(build, options);
49             break;
50 
51         case ninja:
52             handleNinja(build, options);
53             break;
54 
55         case tup:
56             handleTup(build, options);
57             break;
58 
59         case binary:
60             Binary(build, options).run(args);
61             break;
62 
63         case none:
64             throw new Exception("A backend must be specified with -b/--backend");
65         }
66 }
67 
68 private void handleNinja(in Build build, in Options options) {
69     version(minimal) {
70         throw new Exception("Ninja backend support not compiled in");
71     } else {
72 
73         const ninja = Ninja(build, options);
74 
75         auto buildNinja = File("build.ninja", "w");
76         buildNinja.writeln("include rules.ninja\n");
77         buildNinja.writeln(ninja.buildOutput);
78 
79         auto rulesNinja = File("rules.ninja", "w");
80         rulesNinja.writeln(ninja.rulesOutput);
81     }
82 }
83 
84 
85 private void handleMake(in Build build, in Options options) {
86     version(minimal) {
87         throw new Exception("Make backend support not compiled in");
88     } else {
89 
90         const makefile = Makefile(build, options);
91         auto file = File(makefile.fileName, "w");
92         file.write(makefile.output);
93     }
94 }
95 
96 private void handleTup(in Build build, in Options options) {
97     version(minimal) {
98         throw new Exception("Tup backend support not compiled in");
99     } else {
100         if(!".tup".exists) execute(["tup", "init"]);
101         const tup = Tup(build, options);
102         auto file = File(tup.fileName, "w");
103         file.write(tup.output);
104     }
105 }