1 /**
2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved.
3 License: MPL-2
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 
6 This Source Code Form is subject to the terms of the Mozilla Public License,
7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain
8 one at http://mozilla.org/MPL/2.0/.
9 */
10 module dextool_test.compiler;
11 
12 import scriptlike;
13 
14 import dextool_test.utils : escapePath, TestEnv, runAndLog, makeCommand;
15 import dextool_test.builders;
16 
17 immutable defaultBinary = "./binary";
18 
19 /** Construct an execution of a compiler.
20  */
21 auto makeCompile(const ref TestEnv testEnv, string compiler) {
22     // dfmt off
23     return BuildCommandRun(compiler, testEnv.outdir.escapePath)
24         .commandInOutdir(false)
25         .addArg("-g")
26         .addInclude(testEnv.outdir.escapePath);
27     // dfmt on
28 }
29 
30 /// Use in conjunction with makeCompile to setup the default binary destination.
31 auto outputToDefaultBinary(BuildCommandRun br) {
32     return br.addArg(["-o", (br.workdir ~ defaultBinary).escapePath]);
33 }
34 
35 /** Add recursively all files in outdir with extension ext (including dot)
36  *
37  * Params:
38  *  br = builder param to extend
39  *  ext = extension to filter on
40  *  exclude = files to exclude
41  */
42 auto addFilesFromOutdirWithExtension(BuildCommandRun br, string ext, string[] exclude) {
43     import dextool_test.utils : recursiveFilesWithExtension;
44 
45     foreach (a; recursiveFilesWithExtension(br.workdir, ext).filter!(a => !canFind(exclude,
46             a.baseName.toString))) {
47         br.addArg(a);
48     }
49 
50     return br;
51 }
52 
53 /// Add parameters to link and use gmock/gtest.
54 auto addGtestArgs(BuildCommandRun br) {
55     // dfmt off
56     return br
57         .addInclude("fused_gmock")
58         .addArg("-L.")
59         .addArg("-lgmock_gtest")
60         .addArg("-lpthread");
61     // dfmt on
62 }
63 
64 /// Add the parameter as an include (-I).
65 auto addInclude(BuildCommandRun br, Path p) {
66     return br.addArg(["-I", p.toString]);
67 }
68 
69 auto addInclude(BuildCommandRun br, string p) {
70     return br.addArg(["-I", p]);
71 }
72 
73 /// Add the parameter as a define (-D).
74 auto addDefine(BuildCommandRun br, string v) {
75     return br.addArg(["-D", v]);
76 }
77 
78 string[] compilerFlags() {
79     auto default_flags = ["-std=c++98"];
80 
81     auto r = BuildCommandRun("g++").addArg("-dumpversion").yapOutput(false)
82         .throwOnExitStatus(false).run;
83 
84     if (!r.success)
85         return default_flags;
86 
87     if (r.stdout.length == 0 || r.stdout[0].length == 0) {
88         return default_flags;
89     } else if (r.stdout[0][0] == '5') {
90         return default_flags ~ ["-Wpedantic", "-Werror"];
91     } else {
92         return default_flags ~ ["-pedantic", "-Werror"];
93     }
94 }
95 
96 deprecated("legacy function, to be removed") void testWithGTest(const Path[] src,
97         const Path binary, const ref TestEnv testEnv, const string[] flags, const string[] incls) {
98     immutable bool[string] rm_flag = ["-Wpedantic" : true, "-Werror" : true, "-pedantic" : true];
99 
100     auto flags_ = flags.filter!(a => a !in rm_flag).array();
101 
102     Args args;
103     args ~= "g++";
104     args ~= flags_.dup;
105     args ~= "-g";
106     args ~= "-o" ~ binary.escapePath;
107     args ~= "-I" ~ testEnv.outdir.escapePath;
108     args ~= "-I" ~ "fused_gmock";
109     args ~= incls.dup;
110     args ~= src.dup;
111     args ~= "-l" ~ "gmock_gtest";
112     args ~= "-lpthread";
113     args ~= "-L.";
114 
115     runAndLog(args.data);
116 }
117 
118 deprecated("legacy function, to be removed") void compileResult(const Path input, const Path binary,
119         const Path main, const ref TestEnv testEnv, const string[] flags, const string[] incls) {
120     Args args;
121     args ~= "g++";
122     args ~= flags.dup;
123     args ~= "-g";
124     args ~= "-o" ~ binary.escapePath;
125     args ~= "-I" ~ testEnv.outdir.escapePath;
126     args ~= incls.dup;
127     args ~= main;
128 
129     if (exists(input)) {
130         args ~= input;
131     }
132 
133     runAndLog(args.data);
134 }