1 /**
2 	Generator for project files
3 	
4 	Copyright: © 2012-2013 Matthias Dondorff
5 	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
6 	Authors: Matthias Dondorff
7 */
8 module dub.generators.generator;
9 
10 import dub.compilers.compiler;
11 import dub.generators.build;
12 import dub.generators.monod;
13 import dub.generators.rdmd;
14 import dub.generators.visuald;
15 import dub.internal.vibecompat.core.file;
16 import dub.internal.vibecompat.core.log;
17 import dub.internal.vibecompat.inet.path;
18 import dub.package_;
19 import dub.packagemanager;
20 import dub.project;
21 
22 import std.exception;
23 import std.file;
24 import std.string;
25 
26 
27 /**
28 	Common interface for project generators/builders.
29 */
30 interface ProjectGenerator
31 {
32 	void generateProject(GeneratorSettings settings);
33 }
34 
35 
36 struct GeneratorSettings {
37 	BuildPlatform platform;
38 	string config;
39 	Compiler compiler;
40 	BuildSettings buildSettings;
41 
42 	// only used for generator "rdmd"
43 	bool run;
44 	string[] runArgs;
45 	string buildType;
46 }
47 
48 
49 /**
50 	Creates a project generator of the given type for the specified project.
51 */
52 ProjectGenerator createProjectGenerator(string generator_type, Project app, PackageManager mgr)
53 {
54 	assert(app !is null && mgr !is null, "Project and package manager needed to create a generator.");
55 
56 	generator_type = generator_type.toLower();
57 	switch(generator_type) {
58 		default:
59 			throw new Exception("Unknown project generator: "~generator_type);
60 		case "build":
61 			logDebug("Creating build generator.");
62 			return new BuildGenerator(app, mgr);
63 		case "rdmd":
64 			logDebug("Creating rdmd generator.");
65 			return new RdmdGenerator(app, mgr);
66 		case "mono-d":
67 			logDebug("Creating MonoD generator.");
68 			return new MonoDGenerator(app, mgr);
69 		case "visuald":
70 			logDebug("Creating VisualD generator.");
71 			return new VisualDGenerator(app, mgr, false);
72 		case "visuald-combined":
73 			logDebug("Creating VisualD generator (combined project).");
74 			return new VisualDGenerator(app, mgr, true);
75 	}
76 }
77 
78 
79 /**
80 	Runs pre-build commands and performs other required setup before project files are generated.
81 */
82 void prepareGeneration(BuildSettings buildsettings)
83 {
84 	if( buildsettings.preGenerateCommands.length ){
85 		logInfo("Running pre-generate commands...");
86 		runBuildCommands(buildsettings.preGenerateCommands, buildsettings);
87 	}
88 }
89 
90 /**
91 	Runs post-build commands and copies required files to the binary directory.
92 */
93 void finalizeGeneration(BuildSettings buildsettings, bool generate_binary)
94 {
95 	if (buildsettings.postGenerateCommands.length) {
96 		logInfo("Running post-generate commands...");
97 		runBuildCommands(buildsettings.postGenerateCommands, buildsettings);
98 	}
99 
100 	if (generate_binary) {
101 		if (!exists(buildsettings.targetPath))
102 			mkdirRecurse(buildsettings.targetPath);
103 		
104 		if (buildsettings.copyFiles.length) {
105 			logInfo("Copying files...");
106 			foreach (f; buildsettings.copyFiles) {
107 				auto src = Path(f);
108 				auto dst = Path(buildsettings.targetPath) ~ Path(f).head;
109 				logDiagnostic("  %s to %s", src.toNativeString(), dst.toNativeString());
110 				try {
111 					copyFile(src, dst, true);
112 				} catch logWarn("Failed to copy to %s", dst.toNativeString());
113 			}
114 		}
115 	}
116 }
117 
118 void runBuildCommands(string[] commands, in BuildSettings build_settings)
119 {
120 	import dub.internal.std.process;
121 	import dub.internal.utils;
122 
123 	string[string] env = environment.toAA();
124 	// TODO: do more elaborate things here
125 	// TODO: escape/quote individual items appropriately
126 	env["DFLAGS"] = join(cast(string[])build_settings.dflags, " ");
127 	env["LFLAGS"] = join(cast(string[])build_settings.lflags," ");
128 	env["VERSIONS"] = join(cast(string[])build_settings.versions," ");
129 	env["LIBS"] = join(cast(string[])build_settings.libs," ");
130 	env["IMPORT_PATHS"] = join(cast(string[])build_settings.importPaths," ");
131 	env["STRING_IMPORT_PATHS"] = join(cast(string[])build_settings.stringImportPaths," ");
132 	runCommands(commands, env);
133 }