blob: fe879a206a2070cda750a4e2c7924f273e3dea74 [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 Picusb03e5082018-02-05 12:36:49 +010026 def test_default_stage1(self):
27 """
28 Test that we dump the correct commands for a single stage build of LLVM.
29 """
Diana Picusfcfc6282018-02-14 18:50:24 +010030 reposDir = "path-to-repos"
Diana Picusb03e5082018-02-05 12:36:49 +010031 sourceDir = "path-to-sources"
32 buildDir = "path-to-stage1"
33
34 output = self.run_with_output(
35 self.llvm_build_and_test(
36 "--dry-run",
Diana Picusfcfc6282018-02-14 18:50:24 +010037 "--repos-dir", reposDir,
Diana Picusb03e5082018-02-05 12:36:49 +010038 "--source-dir", sourceDir,
39 "--stage1-build-dir", buildDir))
40
41 commands = output.splitlines()
42
43 self.assertRegex(commands[0],
44 "{build}\$ cmake -G Ninja .* {sources}".format(
45 build=buildDir, sources=sourceDir))
46
47 self.assertRegex(commands[1],
48 "{build}\$ ninja".format(build=buildDir))
49
Diana Picus2c580832018-02-14 14:51:00 +010050 def test_custom_stage1(self):
51 """Test that we can customize the first stage of the build."""
52 reposDir = "path-to-repos"
53 sourceDir = "path-to-sources"
54 buildDir = "path-to-stage1"
55
56 output = self.run_with_output(
57 self.llvm_build_and_test(
58 "--dry-run",
59 "--repos-dir", reposDir,
60 "--source-dir", sourceDir,
61 "--stage1-build-dir", buildDir,
62 "--stage1-subproject", "clang",
63 "--stage1-subproject", "compiler-rt",
64 "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
65 "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True",
66 "--stage1-build-flag=-j8",
67 "--stage1-build-flag", "check-all"))
68
69 commands = output.splitlines()
70
71 self.assertRegex(commands[0],
72 "{build}\$ cmake -G Ninja .* {sources}".format(
73 build=buildDir, sources=sourceDir))
74
75 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
76 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
77 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
78 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
79
80 self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
81 self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
82
83 self.assertRegex(commands[1],
84 "{build}\$ ninja -j8 check-all".format(build=buildDir))
85
86
Diana Picus49ee93a2018-02-15 05:52:34 +010087 def test_stage1_and_default_testsuite(self):
Diana Picusb03e5082018-02-05 12:36:49 +010088 """
89 Test that we dump the correct commands for a single stage build of LLVM
90 and a run of the test-suite with the resulting compiler.
91 """
Diana Picusfcfc6282018-02-14 18:50:24 +010092 reposDir = "path-to-repos"
Diana Picusb03e5082018-02-05 12:36:49 +010093 sourceDir = "path-to-sources"
94 buildDir = "path-to-stage1"
Diana Picusb03e5082018-02-05 12:36:49 +010095 sandboxDir = "path-to-sandbox"
Diana Picusfcfc6282018-02-14 18:50:24 +010096
97 testSuiteDir = os.path.join(reposDir, "test-suite")
98 lntDir = os.path.join(reposDir, "lnt")
Diana Picusb03e5082018-02-05 12:36:49 +010099
100 output = self.run_with_output(
101 self.llvm_build_and_test(
102 "--dry-run",
Diana Picusfcfc6282018-02-14 18:50:24 +0100103 "--repos-dir", reposDir,
Diana Picusb03e5082018-02-05 12:36:49 +0100104 "--source-dir", sourceDir,
105 "--stage1-build-dir", buildDir,
Diana Picusfcfc6282018-02-14 18:50:24 +0100106 "--enable-test-suite",
107 "--sandbox", sandboxDir))
Diana Picusb03e5082018-02-05 12:36:49 +0100108
109 commands = output.splitlines()
110
111 self.assertRegex(commands[0],
112 "{build}\$ cmake -G Ninja .* {sources}".format(
113 build=buildDir, sources=sourceDir))
114
115 self.assertRegex(commands[1],
116 "{build}\$ ninja".format(build=buildDir))
117
118 self.assertRegex(
119 commands[2], ".*\$ virtualenv {sandbox}".format(sandbox=sandboxDir))
120
121 self.assertRegex(
122 commands[3],
123 ".*\$ {sandbox}/bin/python {lnt}/setup.py develop".format(
124 sandbox=sandboxDir,
125 lnt=lntDir))
126
127 self.assertRegex(
128 commands[4],
129 ".*\$ {sandbox}/bin/python {sandbox}/bin/lnt runtest test-suite "
130 "--sandbox={sandbox} --test-suite={testsuite} "
131 "--use-lit={build}/bin/llvm-lit --cc={build}/bin/clang".format(
132 sandbox=sandboxDir, testsuite=testSuiteDir, build=buildDir))
133
Diana Picus49ee93a2018-02-15 05:52:34 +0100134 def test_stage1_and_custom_testsuite(self):
135 """Test that we can add custom flags to our test-suite run."""
136 reposDir = "path-to-repos"
137 sourceDir = "path-to-sources"
138 buildDir = "path-to-stage1"
139 sandboxDir = "path-to-sandbox"
140
141 testSuiteDir = os.path.join(reposDir, "test-suite")
142 lntDir = os.path.join(reposDir, "lnt")
143
144 output = self.run_with_output(
145 self.llvm_build_and_test(
146 "--dry-run",
147 "--repos-dir", reposDir,
148 "--source-dir", sourceDir,
149 "--stage1-build-dir", buildDir,
150 "--enable-test-suite",
151 "--sandbox", sandboxDir,
152 "--lnt-flag=--threads=4",
153 "--lnt-flag=--cppflags",
154 "--lnt-flag", "'-mcpu=cortex-a15 -marm'"))
155
156 commands = output.splitlines()
157
158 self.assertRegex(commands[0],
159 "{build}\$ cmake -G Ninja .* {sources}".format(
160 build=buildDir, sources=sourceDir))
161
162 self.assertRegex(commands[1],
163 "{build}\$ ninja".format(build=buildDir))
164
165 self.assertRegex(
166 commands[2], ".*\$ virtualenv {sandbox}".format(sandbox=sandboxDir))
167
168 self.assertRegex(
169 commands[3],
170 ".*\$ {sandbox}/bin/python {lnt}/setup.py develop".format(
171 sandbox=sandboxDir,
172 lnt=lntDir))
173
174 self.assertRegex(
175 commands[4],
176 ".*\$ {sandbox}/bin/python {sandbox}/bin/lnt runtest test-suite "
177 "--sandbox={sandbox} --test-suite={testsuite} "
178 "--use-lit={build}/bin/llvm-lit --cc={build}/bin/clang "
179 "--threads=4 --cppflags '-mcpu=cortex-a15 -marm'".format(
180 sandbox=sandboxDir, testsuite=testSuiteDir, build=buildDir))
181
Diana Picusb03e5082018-02-05 12:36:49 +0100182 def test_default_stage2(self):
183 """
184 Test that we dump the correct commands for a 2-stage build of LLVM.
185 """
Diana Picusfcfc6282018-02-14 18:50:24 +0100186 reposDir = "path-to-repos"
Diana Picusb03e5082018-02-05 12:36:49 +0100187 sourceDir = "path-to-sources"
188 buildDir1 = "path-to-stage1"
189 buildDir2 = "path-to-stage2"
190
191 output = self.run_with_output(
192 self.llvm_build_and_test(
193 "--dry-run",
Diana Picusfcfc6282018-02-14 18:50:24 +0100194 "--repos-dir", reposDir,
Diana Picusb03e5082018-02-05 12:36:49 +0100195 "--source-dir", sourceDir,
196 "--stage1-build-dir", buildDir1,
197 "--stage2-build-dir", buildDir2))
198
199 commands = output.splitlines()
200
201 self.assertRegex(
202 commands[0],
203 "{stage1}\$ cmake -G Ninja .* {sources}".format(
204 stage1=buildDir1, sources=sourceDir))
205
206 self.assertRegex(
207 commands[1],
208 "{stage1}\$ ninja".format(stage1=buildDir1))
209
210 self.assertRegex(
211 commands[2], "{stage2}\$ cmake -G Ninja .* "
212 "-DCMAKE_C_COMPILER={stage1}/bin/clang "
213 "-DCMAKE_CXX_COMPILER={stage1}/bin/clang\+\+ {sources}".format(
214 stage1=buildDir1, stage2=buildDir2, sources=sourceDir))
215
216 self.assertRegex(
217 commands[3],
218 "{stage2}\$ ninja".format(stage2=buildDir2))
219
Diana Picus2c580832018-02-14 14:51:00 +0100220 def test_custom_stage1_default_stage2(self):
221 """
222 Test that we preserve the subprojects, but not the CMake or build flags.
223 """
224 reposDir = "path-to-repos"
225 sourceDir = "path-to-sources"
226 buildDir1 = "path-to-stage1"
227 buildDir2 = "path-to-stage2"
228
229 output = self.run_with_output(
230 self.llvm_build_and_test(
231 "--dry-run",
232 "--repos-dir", reposDir,
233 "--source-dir", sourceDir,
234 "--stage1-build-dir", buildDir1,
235 "--stage1-subproject", "clang",
236 "--stage1-subproject", "compiler-rt",
237 "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
238 "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True",
239 "--stage1-build-flag=-j8",
240 "--stage1-build-flag", "check-all",
241 "--stage2-build-dir", buildDir2))
242
243 commands = output.splitlines()
244
245 self.assertRegex(commands[0],
246 "{build}\$ cmake -G Ninja .* {sources}".format(
247 build=buildDir1, sources=sourceDir))
248
249 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
250 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
251 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
252 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
253
254 self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
255 self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
256
257 self.assertRegex(commands[1],
258 "{build}\$ ninja -j8 check-all".format(build=buildDir1))
259
260 self.assertRegex(
261 commands[2], "{stage2}\$ cmake -G Ninja .* "
262 "-DCMAKE_C_COMPILER={stage1}/bin/clang "
263 "-DCMAKE_CXX_COMPILER={stage1}/bin/clang\+\+ {sources}".format(
264 stage1=buildDir1, stage2=buildDir2, sources=sourceDir))
265
266 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[2])
267 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[2])
268 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[2])
269 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[2])
270
271 self.assertNotIn("-DCMAKE_CXX_FLAGS=-marm", commands[2])
272 self.assertNotIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[2])
273
274 self.assertRegex(
275 commands[3],
276 "{stage2}\$ ninja".format(stage2=buildDir2))
277
Diana Picus6cdb5162018-02-15 05:29:46 +0100278 def test_custom_both_stages(self):
279 """
280 Test that we get the correct commands when trying to customize both
281 stage 1 and stage 2.
282 """
283 reposDir = "path-to-repos"
284 sourceDir = "path-to-sources"
285 buildDir1 = "path-to-stage1"
286 buildDir2 = "path-to-stage2"
287
288 output = self.run_with_output(
289 self.llvm_build_and_test(
290 "--dry-run",
291 "--repos-dir", reposDir,
292 "--source-dir", sourceDir,
293 "--stage1-build-dir", buildDir1,
294 "--stage1-subproject", "clang",
295 "--stage1-subproject", "compiler-rt",
296 "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
297 "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True",
298 "--stage1-build-flag=-j8",
299 "--stage2-build-dir", buildDir2,
300 "--stage2-subproject", "clang",
301 "--stage2-subproject", "libcxx",
302 "--stage2-cmake-def", "CMAKE_BUILD_TYPE=MinSizeRel",
303 "--stage2-build-flag", "check-all"))
304
305 commands = output.splitlines()
306
307 self.assertRegex(commands[0],
308 "{build}\$ cmake -G Ninja .* {sources}".format(
309 build=buildDir1, sources=sourceDir))
310
311 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
312 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
313 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
314 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
315
316 self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
317 self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
318 self.assertNotIn("-DCMAKE_BUILD_TYPE=MinSizeRel", commands[0])
319
320 self.assertRegex(commands[1],
321 "{build}\$ ninja -j8".format(build=buildDir1))
322
323 self.assertRegex(
324 commands[2], "{stage2}\$ cmake -G Ninja .* "
325 "-DCMAKE_C_COMPILER={stage1}/bin/clang "
326 "-DCMAKE_CXX_COMPILER={stage1}/bin/clang\+\+ {sources}".format(
327 stage1=buildDir1, stage2=buildDir2, sources=sourceDir))
328
329 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[2])
330 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=OFF", commands[2])
331 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=ON", commands[2])
332 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[2])
333
334 self.assertNotIn("-DCMAKE_CXX_FLAGS=-marm", commands[2])
335 self.assertNotIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[2])
336 self.assertIn("-DCMAKE_BUILD_TYPE=MinSizeRel", commands[2])
337
338 self.assertRegex(
339 commands[3],
340 "{stage2}\$ ninja check-all".format(stage2=buildDir2))
Diana Picus2c580832018-02-14 14:51:00 +0100341
Diana Picusb03e5082018-02-05 12:36:49 +0100342 def test_stage2_and_testsuite(self):
343 """
344 Test that we dump the correct commands for a 2-stage build of LLVM and a
345 run of the test-suite with the resulting compiler.
346 """
Diana Picusfcfc6282018-02-14 18:50:24 +0100347 reposDir = "path-to-repos"
Diana Picusb03e5082018-02-05 12:36:49 +0100348 sourceDir = "path-to-sources"
349 buildDir1 = "path-to-stage1"
350 buildDir2 = "path-to-stage2"
Diana Picusb03e5082018-02-05 12:36:49 +0100351 sandboxDir = "path-to-sandbox"
Diana Picusfcfc6282018-02-14 18:50:24 +0100352
353 testSuiteDir = os.path.join(reposDir, "test-suite")
354 lntDir = os.path.join(reposDir, "lnt")
Diana Picusb03e5082018-02-05 12:36:49 +0100355
356 output = self.run_with_output(
357 self.llvm_build_and_test(
358 "--dry-run",
Diana Picusfcfc6282018-02-14 18:50:24 +0100359 "--repos-dir", reposDir,
Diana Picusb03e5082018-02-05 12:36:49 +0100360 "--source-dir", sourceDir,
361 "--stage1-build-dir", buildDir1,
362 "--stage2-build-dir", buildDir2,
Diana Picusfcfc6282018-02-14 18:50:24 +0100363 "--enable-test-suite",
364 "--sandbox", sandboxDir))
Diana Picusb03e5082018-02-05 12:36:49 +0100365
366 commands = output.splitlines()
367
368 self.assertRegex(
369 commands[0],
370 "{stage1}\$ cmake -G Ninja .* {sources}".format(
371 stage1=buildDir1,
372 sources=sourceDir))
373
374 self.assertRegex(
375 commands[1],
376 "{stage1}\$ ninja".format(stage1=buildDir1))
377
378 self.assertRegex(
379 commands[2], "{stage2}\$ cmake -G Ninja .* "
380 "-DCMAKE_C_COMPILER={stage1}/bin/clang "
381 "-DCMAKE_CXX_COMPILER={stage1}/bin/clang\+\+ {sources}".format(
382 stage1=buildDir1, stage2=buildDir2, sources=sourceDir))
383
384 self.assertRegex(
385 commands[3],
386 "{stage2}\$ ninja".format(stage2=buildDir2))
387
388 self.assertRegex(
389 commands[4],
390 ".*\$ virtualenv {sandbox}".format(sandbox=sandboxDir))
391
392 self.assertRegex(
393 commands[5],
394 ".*\$ {sandbox}/bin/python {lnt}/setup.py develop".format(
395 sandbox=sandboxDir,
396 lnt=lntDir))
397
398 self.assertRegex(
399 commands[6],
400 ".*\$ {sandbox}/bin/python {sandbox}/bin/lnt runtest test-suite "
401 "--sandbox={sandbox} --test-suite={testsuite} "
402 "--use-lit={build}/bin/llvm-lit --cc={build}/bin/clang".format(
403 sandbox=sandboxDir, testsuite=testSuiteDir, build=buildDir2))
Diana Picusfec612c2018-02-19 19:14:00 +0100404
405 def test_read_flags_from_file(self):
406 """Test that we can read our flags from a configuration file."""
407 reposDir = "path-to-repos"
408 sourceDir = "path-to-sources"
409 buildDir = "path-to-stage1"
410
411 flagsInFile = ("--dry-run\n"
412 "--repos-dir\n"
413 "{repos}\n"
414 "--source-dir\n"
415 "{sources}\n"
416 "--stage1-build-dir\n"
417 "{build}").format(
418 repos=reposDir, sources=sourceDir, build=buildDir)
419
420 with self.get_temp_file_with_content(flagsInFile) as configFile:
421 output = self.run_with_output(
422 self.llvm_build_and_test("@{}".format(configFile.name)))
423
424 commands = output.splitlines()
425
426 self.assertRegex(commands[0],
427 "{build}\$ cmake -G Ninja .* {sources}".format(
428 build=buildDir, sources=sourceDir))
429
430 self.assertRegex(commands[1],
431 "{build}\$ ninja".format(build=buildDir))
432
433 def test_override_flags_from_file(self):
434 """
435 Test that we can combine flags from a configuration file and command
436 line flags. The command line flags that come before the name of the
437 configuration file should be overriden by those from the file, whereas
438 command line flags that come after the name of the configuration file
439 should override the values found in the file. For arguments that can be
440 passed multiple times, all the values are collected (both from the
441 command line and from the config file). They should however appear in
442 the order that they were given.
443 """
444 reposDir = "path-to-repos"
445 sourceDir = "path-to-sources"
446 buildDir = "path-to-stage1"
447
448 overridenSourceDir = "overriden-sources"
449 overridenBuildDir = "overriden-build"
450
451 flagsInFile = (
452 "--dry-run\n"
453 "--repos-dir\n"
454 "{repos}\n"
455 "--source-dir\n"
456 "{sources}\n"
457 "--stage1-build-dir\n"
458 "{build}\n"
459 "--stage1-subproject\n"
460 "clang\n"
461 "--stage1-cmake-def\n"
462 "CMAKE_CXX_FLAGS=-mthumb").format(repos=reposDir, sources=sourceDir,
463 build=overridenBuildDir)
464
465 with self.get_temp_file_with_content(flagsInFile) as configFile:
466 output = self.run_with_output(
467 self.llvm_build_and_test(
468 # This should be overriden by the value in the config file.
469 "--source-dir", overridenSourceDir,
470 # This should be appended to the value in the config file.
471 "--stage1-subproject", "lld",
472 # The config file.
473 "@{}".format(configFile.name),
474 # This should override the value in the config file.
475 "--stage1-build-dir", buildDir,
476 # These should be appended to the values in the config file.
477 "--stage1-subproject", "compiler-rt",
478 "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
479 "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True"))
480
481 commands = output.splitlines()
482
483 self.assertRegex(commands[0],
484 "{build}\$ cmake -G Ninja .* {sources}".format(
485 build=buildDir, sources=sourceDir))
486
487 self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
488 self.assertIn("-DLLVM_TOOL_LLD_BUILD=ON", commands[0])
489 self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
490 self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
491 self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
492
493 self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
494 self.assertIn("-DCMAKE_CXX_FLAGS=-mthumb", commands[0])
495 self.assertLess(commands[0].find("-DCMAKE_CXX_FLAGS=-mthumb"),
496 commands[0].find("-DCMAKE_CXX_FLAGS=-marm"))
497 self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
498
499 self.assertRegex(commands[1],
500 "{build}\$ ninja".format(build=buildDir))