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