blob: da3d14b6c2284ce985c32dbbf76ec51cda701bc4 [file] [log] [blame]
Diana Picusb03e5082018-02-05 12:36:49 +01001"""Command line interface tests for llvm.py build-and-test.
2
3Note that although this uses the unittest framework, it does *not* contain unit
4tests.
5
6"""
7import os
Diana Picusfec612c2018-02-19 19:14:00 +01008from tempfile import NamedTemporaryFile
Diana Picusb03e5082018-02-05 12:36:49 +01009
10from llvmtestcase import LLVMTestCase, require_command_arg, debug
11
12
13class Testllvmbuildandtest(LLVMTestCase):
14
15 @classmethod
16 def llvm_build_and_test(cls, *args, **kwargs):
17 return cls.command_with_defaults("build-and-test", *args, **kwargs)
18
Diana Picusfec612c2018-02-19 19:14:00 +010019 @classmethod
20 def get_temp_file_with_content(cls, content):
21 """Return a temporary file with the given content."""
22 theFile = NamedTemporaryFile(mode='wt')
23 print(content, file=theFile, flush=True)
24 return theFile
25
Diana Picusc1b4d342018-02-15 17:09:45 +010026 @require_command_arg("--repos")
27 def test_repos_dir_is_compulsory(self):
28 """Test that we get an error if we don't pass the path to the repos."""
29 self.run_with_output(
30 self.llvm_build_and_test("--source-dir=somewhere",
31 "--stage1-build-dir=elsewhere"))
32
33 @require_command_arg("--source-dir")
34 def test_source_dir_is_compulsory(self):
35 """Test that we get an error if we don't pass the path to the sources."""
36 self.run_with_output(
37 self.llvm_build_and_test("--repos-dir=somewhere",
38 "--stage1-build-dir=elsewhere"))
39
40 @require_command_arg("--stage1-build-dir")
41 def test_stage1_build_dir_is_compulsory(self):
42 """
43 Test that we get an error if we don't pass the path to the stage 1
44 build directory.
45 """
46 self.run_with_output(
47 self.llvm_build_and_test("--repos-dir=somewhere",
48 "--source-dir=elsewhere"))
49
Diana Picusb03e5082018-02-05 12:36:49 +010050 def test_default_stage1(self):
51 """
52 Test that we dump the correct commands for a single stage build of LLVM.
53 """
Diana Picusfcfc6282018-02-14 18:50:24 +010054 reposDir = "path-to-repos"
Diana Picusb03e5082018-02-05 12:36:49 +010055 sourceDir = "path-to-sources"
56 buildDir = "path-to-stage1"
57
58 output = self.run_with_output(
59 self.llvm_build_and_test(
60 "--dry-run",
Diana Picusfcfc6282018-02-14 18:50:24 +010061 "--repos-dir", reposDir,
Diana Picusb03e5082018-02-05 12:36:49 +010062 "--source-dir", sourceDir,
63 "--stage1-build-dir", buildDir))
64
65 commands = output.splitlines()
66
67 self.assertRegex(commands[0],
68 "{build}\$ cmake -G Ninja .* {sources}".format(
69 build=buildDir, sources=sourceDir))
70
71 self.assertRegex(commands[1],
72 "{build}\$ ninja".format(build=buildDir))
73
Diana Picus2c580832018-02-14 14:51:00 +010074 def test_custom_stage1(self):
75 """Test that we can customize the first stage of the build."""
76 reposDir = "path-to-repos"
77 sourceDir = "path-to-sources"
78 buildDir = "path-to-stage1"
79
80 output = self.run_with_output(
81 self.llvm_build_and_test(
82 "--dry-run",
83 "--repos-dir", reposDir,
84 "--source-dir", sourceDir,
85 "--stage1-build-dir", buildDir,
86 "--stage1-subproject", "clang",
87 "--stage1-subproject", "compiler-rt",
88 "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
89 "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True",
90 "--stage1-build-flag=-j8",
91 "--stage1-build-flag", "check-all"))
92
93 commands = output.splitlines()
94
95 self.assertRegex(commands[0],
96 "{build}\$ cmake -G Ninja .* {sources}".format(
97 build=buildDir, sources=sourceDir))
98
99 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
100 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
101 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
102 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
103
104 self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
105 self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
106
107 self.assertRegex(commands[1],
108 "{build}\$ ninja -j8 check-all".format(build=buildDir))
109
110
Diana Picus49ee93a2018-02-15 05:52:34 +0100111 def test_stage1_and_default_testsuite(self):
Diana Picusb03e5082018-02-05 12:36:49 +0100112 """
113 Test that we dump the correct commands for a single stage build of LLVM
114 and a run of the test-suite with the resulting compiler.
115 """
Diana Picusfcfc6282018-02-14 18:50:24 +0100116 reposDir = "path-to-repos"
Diana Picusb03e5082018-02-05 12:36:49 +0100117 sourceDir = "path-to-sources"
118 buildDir = "path-to-stage1"
Diana Picusb03e5082018-02-05 12:36:49 +0100119 sandboxDir = "path-to-sandbox"
Diana Picusfcfc6282018-02-14 18:50:24 +0100120
121 testSuiteDir = os.path.join(reposDir, "test-suite")
122 lntDir = os.path.join(reposDir, "lnt")
Diana Picusb03e5082018-02-05 12:36:49 +0100123
124 output = self.run_with_output(
125 self.llvm_build_and_test(
126 "--dry-run",
Diana Picusfcfc6282018-02-14 18:50:24 +0100127 "--repos-dir", reposDir,
Diana Picusb03e5082018-02-05 12:36:49 +0100128 "--source-dir", sourceDir,
129 "--stage1-build-dir", buildDir,
Diana Picusfcfc6282018-02-14 18:50:24 +0100130 "--enable-test-suite",
131 "--sandbox", sandboxDir))
Diana Picusb03e5082018-02-05 12:36:49 +0100132
133 commands = output.splitlines()
134
135 self.assertRegex(commands[0],
136 "{build}\$ cmake -G Ninja .* {sources}".format(
137 build=buildDir, sources=sourceDir))
138
139 self.assertRegex(commands[1],
140 "{build}\$ ninja".format(build=buildDir))
141
142 self.assertRegex(
143 commands[2], ".*\$ virtualenv {sandbox}".format(sandbox=sandboxDir))
144
145 self.assertRegex(
146 commands[3],
147 ".*\$ {sandbox}/bin/python {lnt}/setup.py develop".format(
148 sandbox=sandboxDir,
149 lnt=lntDir))
150
151 self.assertRegex(
152 commands[4],
153 ".*\$ {sandbox}/bin/python {sandbox}/bin/lnt runtest test-suite "
154 "--sandbox={sandbox} --test-suite={testsuite} "
155 "--use-lit={build}/bin/llvm-lit --cc={build}/bin/clang".format(
156 sandbox=sandboxDir, testsuite=testSuiteDir, build=buildDir))
157
Diana Picus49ee93a2018-02-15 05:52:34 +0100158 def test_stage1_and_custom_testsuite(self):
159 """Test that we can add custom flags to our test-suite run."""
160 reposDir = "path-to-repos"
161 sourceDir = "path-to-sources"
162 buildDir = "path-to-stage1"
163 sandboxDir = "path-to-sandbox"
164
165 testSuiteDir = os.path.join(reposDir, "test-suite")
166 lntDir = os.path.join(reposDir, "lnt")
167
168 output = self.run_with_output(
169 self.llvm_build_and_test(
170 "--dry-run",
171 "--repos-dir", reposDir,
172 "--source-dir", sourceDir,
173 "--stage1-build-dir", buildDir,
174 "--enable-test-suite",
175 "--sandbox", sandboxDir,
176 "--lnt-flag=--threads=4",
177 "--lnt-flag=--cppflags",
178 "--lnt-flag", "'-mcpu=cortex-a15 -marm'"))
179
180 commands = output.splitlines()
181
182 self.assertRegex(commands[0],
183 "{build}\$ cmake -G Ninja .* {sources}".format(
184 build=buildDir, sources=sourceDir))
185
186 self.assertRegex(commands[1],
187 "{build}\$ ninja".format(build=buildDir))
188
189 self.assertRegex(
190 commands[2], ".*\$ virtualenv {sandbox}".format(sandbox=sandboxDir))
191
192 self.assertRegex(
193 commands[3],
194 ".*\$ {sandbox}/bin/python {lnt}/setup.py develop".format(
195 sandbox=sandboxDir,
196 lnt=lntDir))
197
198 self.assertRegex(
199 commands[4],
200 ".*\$ {sandbox}/bin/python {sandbox}/bin/lnt runtest test-suite "
201 "--sandbox={sandbox} --test-suite={testsuite} "
202 "--use-lit={build}/bin/llvm-lit --cc={build}/bin/clang "
203 "--threads=4 --cppflags '-mcpu=cortex-a15 -marm'".format(
204 sandbox=sandboxDir, testsuite=testSuiteDir, build=buildDir))
205
Diana Picusb03e5082018-02-05 12:36:49 +0100206 def test_default_stage2(self):
207 """
208 Test that we dump the correct commands for a 2-stage build of LLVM.
209 """
Diana Picusfcfc6282018-02-14 18:50:24 +0100210 reposDir = "path-to-repos"
Diana Picusb03e5082018-02-05 12:36:49 +0100211 sourceDir = "path-to-sources"
212 buildDir1 = "path-to-stage1"
213 buildDir2 = "path-to-stage2"
214
215 output = self.run_with_output(
216 self.llvm_build_and_test(
217 "--dry-run",
Diana Picusfcfc6282018-02-14 18:50:24 +0100218 "--repos-dir", reposDir,
Diana Picusb03e5082018-02-05 12:36:49 +0100219 "--source-dir", sourceDir,
220 "--stage1-build-dir", buildDir1,
221 "--stage2-build-dir", buildDir2))
222
223 commands = output.splitlines()
224
225 self.assertRegex(
226 commands[0],
227 "{stage1}\$ cmake -G Ninja .* {sources}".format(
228 stage1=buildDir1, sources=sourceDir))
229
230 self.assertRegex(
231 commands[1],
232 "{stage1}\$ ninja".format(stage1=buildDir1))
233
234 self.assertRegex(
235 commands[2], "{stage2}\$ cmake -G Ninja .* "
236 "-DCMAKE_C_COMPILER={stage1}/bin/clang "
237 "-DCMAKE_CXX_COMPILER={stage1}/bin/clang\+\+ {sources}".format(
238 stage1=buildDir1, stage2=buildDir2, sources=sourceDir))
239
240 self.assertRegex(
241 commands[3],
242 "{stage2}\$ ninja".format(stage2=buildDir2))
243
Diana Picus2c580832018-02-14 14:51:00 +0100244 def test_custom_stage1_default_stage2(self):
245 """
246 Test that we preserve the subprojects, but not the CMake or build flags.
247 """
248 reposDir = "path-to-repos"
249 sourceDir = "path-to-sources"
250 buildDir1 = "path-to-stage1"
251 buildDir2 = "path-to-stage2"
252
253 output = self.run_with_output(
254 self.llvm_build_and_test(
255 "--dry-run",
256 "--repos-dir", reposDir,
257 "--source-dir", sourceDir,
258 "--stage1-build-dir", buildDir1,
259 "--stage1-subproject", "clang",
260 "--stage1-subproject", "compiler-rt",
261 "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
262 "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True",
263 "--stage1-build-flag=-j8",
264 "--stage1-build-flag", "check-all",
265 "--stage2-build-dir", buildDir2))
266
267 commands = output.splitlines()
268
269 self.assertRegex(commands[0],
270 "{build}\$ cmake -G Ninja .* {sources}".format(
271 build=buildDir1, sources=sourceDir))
272
273 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
274 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
275 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
276 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
277
278 self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
279 self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
280
281 self.assertRegex(commands[1],
282 "{build}\$ ninja -j8 check-all".format(build=buildDir1))
283
284 self.assertRegex(
285 commands[2], "{stage2}\$ cmake -G Ninja .* "
286 "-DCMAKE_C_COMPILER={stage1}/bin/clang "
287 "-DCMAKE_CXX_COMPILER={stage1}/bin/clang\+\+ {sources}".format(
288 stage1=buildDir1, stage2=buildDir2, sources=sourceDir))
289
290 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[2])
291 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[2])
292 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[2])
293 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[2])
294
295 self.assertNotIn("-DCMAKE_CXX_FLAGS=-marm", commands[2])
296 self.assertNotIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[2])
297
298 self.assertRegex(
299 commands[3],
300 "{stage2}\$ ninja".format(stage2=buildDir2))
301
Diana Picus6cdb5162018-02-15 05:29:46 +0100302 def test_custom_both_stages(self):
303 """
304 Test that we get the correct commands when trying to customize both
305 stage 1 and stage 2.
306 """
307 reposDir = "path-to-repos"
308 sourceDir = "path-to-sources"
309 buildDir1 = "path-to-stage1"
310 buildDir2 = "path-to-stage2"
311
312 output = self.run_with_output(
313 self.llvm_build_and_test(
314 "--dry-run",
315 "--repos-dir", reposDir,
316 "--source-dir", sourceDir,
317 "--stage1-build-dir", buildDir1,
318 "--stage1-subproject", "clang",
319 "--stage1-subproject", "compiler-rt",
320 "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
321 "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True",
322 "--stage1-build-flag=-j8",
323 "--stage2-build-dir", buildDir2,
324 "--stage2-subproject", "clang",
325 "--stage2-subproject", "libcxx",
326 "--stage2-cmake-def", "CMAKE_BUILD_TYPE=MinSizeRel",
327 "--stage2-build-flag", "check-all"))
328
329 commands = output.splitlines()
330
331 self.assertRegex(commands[0],
332 "{build}\$ cmake -G Ninja .* {sources}".format(
333 build=buildDir1, sources=sourceDir))
334
335 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
336 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
337 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
338 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
339
340 self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
341 self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
342 self.assertNotIn("-DCMAKE_BUILD_TYPE=MinSizeRel", commands[0])
343
344 self.assertRegex(commands[1],
345 "{build}\$ ninja -j8".format(build=buildDir1))
346
347 self.assertRegex(
348 commands[2], "{stage2}\$ cmake -G Ninja .* "
349 "-DCMAKE_C_COMPILER={stage1}/bin/clang "
350 "-DCMAKE_CXX_COMPILER={stage1}/bin/clang\+\+ {sources}".format(
351 stage1=buildDir1, stage2=buildDir2, sources=sourceDir))
352
353 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[2])
354 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=OFF", commands[2])
355 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=ON", commands[2])
356 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[2])
357
358 self.assertNotIn("-DCMAKE_CXX_FLAGS=-marm", commands[2])
359 self.assertNotIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[2])
360 self.assertIn("-DCMAKE_BUILD_TYPE=MinSizeRel", commands[2])
361
362 self.assertRegex(
363 commands[3],
364 "{stage2}\$ ninja check-all".format(stage2=buildDir2))
Diana Picus2c580832018-02-14 14:51:00 +0100365
Diana Picusb03e5082018-02-05 12:36:49 +0100366 def test_stage2_and_testsuite(self):
367 """
368 Test that we dump the correct commands for a 2-stage build of LLVM and a
369 run of the test-suite with the resulting compiler.
370 """
Diana Picusfcfc6282018-02-14 18:50:24 +0100371 reposDir = "path-to-repos"
Diana Picusb03e5082018-02-05 12:36:49 +0100372 sourceDir = "path-to-sources"
373 buildDir1 = "path-to-stage1"
374 buildDir2 = "path-to-stage2"
Diana Picusb03e5082018-02-05 12:36:49 +0100375 sandboxDir = "path-to-sandbox"
Diana Picusfcfc6282018-02-14 18:50:24 +0100376
377 testSuiteDir = os.path.join(reposDir, "test-suite")
378 lntDir = os.path.join(reposDir, "lnt")
Diana Picusb03e5082018-02-05 12:36:49 +0100379
380 output = self.run_with_output(
381 self.llvm_build_and_test(
382 "--dry-run",
Diana Picusfcfc6282018-02-14 18:50:24 +0100383 "--repos-dir", reposDir,
Diana Picusb03e5082018-02-05 12:36:49 +0100384 "--source-dir", sourceDir,
385 "--stage1-build-dir", buildDir1,
386 "--stage2-build-dir", buildDir2,
Diana Picusfcfc6282018-02-14 18:50:24 +0100387 "--enable-test-suite",
388 "--sandbox", sandboxDir))
Diana Picusb03e5082018-02-05 12:36:49 +0100389
390 commands = output.splitlines()
391
392 self.assertRegex(
393 commands[0],
394 "{stage1}\$ cmake -G Ninja .* {sources}".format(
395 stage1=buildDir1,
396 sources=sourceDir))
397
398 self.assertRegex(
399 commands[1],
400 "{stage1}\$ ninja".format(stage1=buildDir1))
401
402 self.assertRegex(
403 commands[2], "{stage2}\$ cmake -G Ninja .* "
404 "-DCMAKE_C_COMPILER={stage1}/bin/clang "
405 "-DCMAKE_CXX_COMPILER={stage1}/bin/clang\+\+ {sources}".format(
406 stage1=buildDir1, stage2=buildDir2, sources=sourceDir))
407
408 self.assertRegex(
409 commands[3],
410 "{stage2}\$ ninja".format(stage2=buildDir2))
411
412 self.assertRegex(
413 commands[4],
414 ".*\$ virtualenv {sandbox}".format(sandbox=sandboxDir))
415
416 self.assertRegex(
417 commands[5],
418 ".*\$ {sandbox}/bin/python {lnt}/setup.py develop".format(
419 sandbox=sandboxDir,
420 lnt=lntDir))
421
422 self.assertRegex(
423 commands[6],
424 ".*\$ {sandbox}/bin/python {sandbox}/bin/lnt runtest test-suite "
425 "--sandbox={sandbox} --test-suite={testsuite} "
426 "--use-lit={build}/bin/llvm-lit --cc={build}/bin/clang".format(
427 sandbox=sandboxDir, testsuite=testSuiteDir, build=buildDir2))
Diana Picusfec612c2018-02-19 19:14:00 +0100428
429 def test_read_flags_from_file(self):
430 """Test that we can read our flags from a configuration file."""
431 reposDir = "path-to-repos"
432 sourceDir = "path-to-sources"
433 buildDir = "path-to-stage1"
434
435 flagsInFile = ("--dry-run\n"
436 "--repos-dir\n"
437 "{repos}\n"
438 "--source-dir\n"
439 "{sources}\n"
440 "--stage1-build-dir\n"
441 "{build}").format(
442 repos=reposDir, sources=sourceDir, build=buildDir)
443
444 with self.get_temp_file_with_content(flagsInFile) as configFile:
445 output = self.run_with_output(
446 self.llvm_build_and_test("@{}".format(configFile.name)))
447
448 commands = output.splitlines()
449
450 self.assertRegex(commands[0],
451 "{build}\$ cmake -G Ninja .* {sources}".format(
452 build=buildDir, sources=sourceDir))
453
454 self.assertRegex(commands[1],
455 "{build}\$ ninja".format(build=buildDir))
456
457 def test_override_flags_from_file(self):
458 """
459 Test that we can combine flags from a configuration file and command
460 line flags. The command line flags that come before the name of the
461 configuration file should be overriden by those from the file, whereas
462 command line flags that come after the name of the configuration file
463 should override the values found in the file. For arguments that can be
464 passed multiple times, all the values are collected (both from the
465 command line and from the config file). They should however appear in
466 the order that they were given.
467 """
468 reposDir = "path-to-repos"
469 sourceDir = "path-to-sources"
470 buildDir = "path-to-stage1"
471
472 overridenSourceDir = "overriden-sources"
473 overridenBuildDir = "overriden-build"
474
475 flagsInFile = (
476 "--dry-run\n"
477 "--repos-dir\n"
478 "{repos}\n"
479 "--source-dir\n"
480 "{sources}\n"
481 "--stage1-build-dir\n"
482 "{build}\n"
483 "--stage1-subproject\n"
484 "clang\n"
485 "--stage1-cmake-def\n"
486 "CMAKE_CXX_FLAGS=-mthumb").format(repos=reposDir, sources=sourceDir,
487 build=overridenBuildDir)
488
489 with self.get_temp_file_with_content(flagsInFile) as configFile:
490 output = self.run_with_output(
491 self.llvm_build_and_test(
492 # This should be overriden by the value in the config file.
493 "--source-dir", overridenSourceDir,
494 # This should be appended to the value in the config file.
495 "--stage1-subproject", "lld",
496 # The config file.
497 "@{}".format(configFile.name),
498 # This should override the value in the config file.
499 "--stage1-build-dir", buildDir,
500 # These should be appended to the values in the config file.
501 "--stage1-subproject", "compiler-rt",
502 "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
503 "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True"))
504
505 commands = output.splitlines()
506
507 self.assertRegex(commands[0],
508 "{build}\$ cmake -G Ninja .* {sources}".format(
509 build=buildDir, sources=sourceDir))
510
511 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
512 self.assertIn("-DLLVM_TOOL_LLD_BUILD=ON", commands[0])
513 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
514 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
515 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
516
517 self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
518 self.assertIn("-DCMAKE_CXX_FLAGS=-mthumb", commands[0])
519 self.assertLess(commands[0].find("-DCMAKE_CXX_FLAGS=-mthumb"),
520 commands[0].find("-DCMAKE_CXX_FLAGS=-marm"))
521 self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
522
523 self.assertRegex(commands[1],
524 "{build}\$ ninja".format(build=buildDir))