1 /**
2 	Generator for direct compiler builds.
3 
4 	Copyright: © 2013-2013 rejectedsoftware e.K.
5 	License: Subject to the terms of the MIT license.
6 	Authors: Sönke Ludwig, Jan Jurzitza
7 */
8 module workspaced.dub.lintgenerator;
9 
10 // TODO: this sucks, this is copy pasted from build.d in dub and only removed binary output here
11 
12 import dub.compilers.compiler;
13 import dub.compilers.utils;
14 import dub.generators.generator;
15 import dub.internal.utils;
16 import dub.internal.vibecompat.core.file;
17 import dub.internal.vibecompat.core.log;
18 import dub.internal.vibecompat.inet.path;
19 import dub.package_;
20 import dub.packagemanager;
21 import dub.project;
22 
23 import std.algorithm;
24 import std.array;
25 import std.conv;
26 import std.exception;
27 import std.file;
28 import std.process;
29 import std.string;
30 import std.encoding : sanitize;
31 
32 version (Windows)
33 	enum objSuffix = ".obj";
34 else
35 	enum objSuffix = ".o";
36 
37 class DubLintGenerator : ProjectGenerator
38 {
39 	this(Project project)
40 	{
41 		super(project);
42 	}
43 
44 	override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets)
45 	{
46 		auto dcl = settings.compiler;
47 
48 		auto root_ti = targets[m_project.rootPackage.name];
49 
50 		logInfo("Performing \"%s\" build using %s for %-(%s, %).", settings.buildType,
51 				settings.platform.compilerBinary, settings.platform.architecture);
52 
53 		buildTarget(settings, root_ti.buildSettings.dup, m_project.rootPackage, root_ti.config);
54 	}
55 
56 	private void buildTarget(GeneratorSettings settings,
57 			BuildSettings buildsettings, in Package pack, string config)
58 	{
59 		auto cwd = NativePath(getcwd());
60 
61 		// make all paths relative to shrink the command line
62 		string makeRelative(string path)
63 		{
64 			return shrinkPath(NativePath(path), cwd);
65 		}
66 
67 		foreach (ref f; buildsettings.sourceFiles)
68 			f = makeRelative(f);
69 		foreach (ref p; buildsettings.importPaths)
70 			p = makeRelative(p);
71 		foreach (ref p; buildsettings.stringImportPaths)
72 			p = makeRelative(p);
73 
74 		// perform the actual build
75 		performDirectBuild(settings, buildsettings, pack, config);
76 	}
77 
78 	private void performDirectBuild(GeneratorSettings settings,
79 			ref BuildSettings buildsettings, in Package pack, string config)
80 	{
81 		auto cwd = NativePath(getcwd());
82 
83 		// make file paths relative to shrink the command line
84 		foreach (ref f; buildsettings.sourceFiles)
85 		{
86 			auto fp = NativePath(f);
87 			if (fp.absolute)
88 				fp = fp.relativeTo(cwd);
89 			f = fp.toNativeString();
90 		}
91 
92 		logInfo("%s %s: building configuration \"%s\"...", pack.name, pack.version_, config);
93 
94 		// make all target/import paths relative
95 		string makeRelative(string path)
96 		{
97 			auto p = NativePath(path);
98 			// storing in a separate temprary to work around #601
99 			auto prel = p.absolute ? p.relativeTo(cwd) : p;
100 			return prel.toNativeString();
101 		}
102 
103 		buildsettings.targetPath = makeRelative(buildsettings.targetPath);
104 		foreach (ref p; buildsettings.importPaths)
105 			p = makeRelative(p);
106 		foreach (ref p; buildsettings.stringImportPaths)
107 			p = makeRelative(p);
108 
109 		buildWithCompiler(settings, buildsettings);
110 	}
111 
112 	private void buildWithCompiler(GeneratorSettings settings, BuildSettings buildsettings)
113 	{
114 		scope (failure)
115 		{
116 			logDiagnostic("FAIL %s %s %s", buildsettings.targetPath,
117 					buildsettings.targetName, buildsettings.targetType);
118 		}
119 
120 		buildsettings.libs = null;
121 		buildsettings.lflags = null;
122 		buildsettings.addOptions(BuildOption.syntaxOnly);
123 		buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !isLinkerFile(settings.platform, f)).array;
124 
125 		settings.compiler.prepareBuildSettings(buildsettings, settings.platform, BuildSetting.commandLine);
126 
127 		settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback);
128 	}
129 }
130 
131 private string shrinkPath(NativePath path, NativePath base)
132 {
133 	auto orig = path.toNativeString();
134 	if (!path.absolute)
135 		return orig;
136 	auto ret = path.relativeTo(base).toNativeString();
137 	return ret.length < orig.length ? ret : orig;
138 }