blob: 173235e4ca2f66588a176e2dfb1bb4a1d2fda905 [file] [log] [blame]
Galina Kistanova1e2edfc2016-08-08 22:08:21 +00001from buildbot.steps.shell import ShellCommand
Galina Kistanova1e2edfc2016-08-08 22:08:21 +00002from buildbot.steps.slave import RemoveDirectory
Galina Kistanovab1668332017-07-07 02:00:28 +00003from buildbot.status.results import FAILURE
Galina Kistanovab3ff2752016-08-15 19:35:56 +00004from buildbot.process.properties import WithProperties
Galina Kistanova1e2edfc2016-08-08 22:08:21 +00005
6from zorg.buildbot.commands.CmakeCommand import CmakeCommand
7from zorg.buildbot.commands.NinjaCommand import NinjaCommand
8from zorg.buildbot.conditions.FileConditions import FileDoesNotExist
9from zorg.buildbot.process.factory import LLVMBuildFactory
10
11def _addSteps4SystemCompiler(
12 f,
13 stage_idx = 0,
14 clean = True,
15 jobs = None,
16 extra_configure_args = None,
17 env = None):
18
19 # Index is zero-based, so we want to use a human friendly number instead.
20 stage_num = stage_idx + 1
21
22 # Directories to use on this stage.
23 obj_dir = f.stage_objdirs[stage_idx]
24 src_dir = LLVMBuildFactory.pathRelativeToBuild(f.llvm_srcdir, obj_dir)
25 install_dir = LLVMBuildFactory.pathRelativeToBuild(f.stage_installdirs[stage_idx], obj_dir)
26
27 # This stage could use incremental build.
28 # Clean stage1, only if requested.
29 f.addStep(RemoveDirectory(name='clean-%s-dir' % obj_dir,
30 dir=obj_dir,
31 haltOnFailure=False,
32 flunkOnFailure=False,
33 doStepIf=clean
34 ))
35 f.addStep(RemoveDirectory(name='clean-%s-dir' % f.stage_installdirs[stage_idx],
36 dir=f.stage_installdirs[stage_idx],
37 haltOnFailure=False,
38 flunkOnFailure=False,
39 doStepIf=clean
40 ))
41
42 # Reconcile the cmake options for this stage.
43
44 # Make a local copy of the configure args, as we are going to modify that.
45 if extra_configure_args:
46 cmake_args = extra_configure_args[:]
47 else:
48 cmake_args = list()
49
50 # Set proper defaults.
51 CmakeCommand.applyDefaultOptions(cmake_args, [
52 ('-DCMAKE_BUILD_TYPE=', 'Release'),
53 ('-DCLANG_BUILD_EXAMPLES=', 'OFF'),
54 ('-DLLVM_BUILD_TESTS=', 'ON'),
55 ('-DLLVM_ENABLE_ASSERTIONS=', 'OFF'),
56 ('-DLLVM_OPTIMIZED_TABLEGEN=', 'ON'),
57 # Do not expect warning free build by the system toolchain.
58 ('-DLLVM_ENABLE_WERROR=', 'OFF'),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000059 ])
60
61 # Some options are required for this stage no matter what.
62 CmakeCommand.applyRequiredOptions(cmake_args, [
Galina Kistanova122a6f42017-09-21 19:19:28 +000063 ('-G', 'Ninja'),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000064 ('-DCMAKE_INSTALL_PREFIX=', install_dir),
65 ])
66
67 # Note: On this stage we do not care of warnings, as we build with
68 # a system toolchain and cannot control the environment.
69 # Warnings are likely, and we ignore them.
70
71 # Create configuration files with cmake
72 f.addStep(CmakeCommand(name="cmake-configure-stage%s" % stage_num,
73 description=["stage%s cmake configure" % stage_num],
74 haltOnFailure=True,
75 flunkOnWarnings=False,
76 options=cmake_args,
77 path=src_dir,
78 env=env,
79 workdir=obj_dir,
Galina Kistanova122a6f42017-09-21 19:19:28 +000080 doStepIf=FileDoesNotExist("CMakeCache.txt")
81 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000082
83 # Build clang by the system compiler
Galina Kistanova122a6f42017-09-21 19:19:28 +000084 f.addStep(NinjaCommand(name="build-stage%s-compiler" % stage_num,
85 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000086 haltOnFailure=True,
87 flunkOnWarnings=False,
88 description=["build stage%s compiler" % stage_num],
89 env=env,
Galina Kistanova122a6f42017-09-21 19:19:28 +000090 workdir=obj_dir,
91 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000092
93 # Test stage1 compiler
Galina Kistanova122a6f42017-09-21 19:19:28 +000094 f.addStep(NinjaCommand(name="test-stage%s-compiler"% stage_num,
95 targets=["check-all"], # or "check-llvm", "check-clang"
96 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000097 haltOnFailure=True,
98 flunkOnWarnings=False,
99 description=["test stage%s compiler" % stage_num],
100 env=env,
Galina Kistanova122a6f42017-09-21 19:19:28 +0000101 workdir=obj_dir,
102 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000103
104 # Install stage1 compiler
Galina Kistanova122a6f42017-09-21 19:19:28 +0000105 f.addStep(NinjaCommand(name="install-stage%s-compiler"% stage_num,
106 targets=["install"],
107 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000108 haltOnFailure=True,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000109 description=["install stage%s compiler" % stage_num],
110 env=env,
Galina Kistanova122a6f42017-09-21 19:19:28 +0000111 workdir=obj_dir,
112 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000113
114
115def _addSteps4StagedCompiler(
116 f,
117 stage_idx = 1,
118 use_stage_idx = -1,
119 withLTOSupport = False,
120 jobs = None,
121 extra_configure_args = None,
122 env = None):
123
124 if use_stage_idx < 0:
125 use_stage_idx = stage_idx - 1
126
127 # Index is zero-based, so we want to use a human friendly number instead.
128 stage_num = stage_idx + 1
129
130 # Directories to use on this stage.
131 obj_dir = f.stage_objdirs[stage_idx]
132 src_dir = LLVMBuildFactory.pathRelativeToBuild(f.llvm_srcdir, obj_dir)
133 install_dir = LLVMBuildFactory.pathRelativeToBuild(f.stage_installdirs[stage_idx], obj_dir)
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000134 staged_install = f.stage_installdirs[use_stage_idx]
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000135
136 # Always do a clean build for the staged compiler.
137 f.addStep(RemoveDirectory(name='clean-%s-dir' % obj_dir,
138 dir=obj_dir,
139 haltOnFailure=False,
140 flunkOnFailure=False,
141 ))
142
143 f.addStep(RemoveDirectory(name='clean-%s-dir' % f.stage_installdirs[stage_idx],
144 dir=f.stage_installdirs[stage_idx],
145 haltOnFailure=False,
146 flunkOnFailure=False,
147 ))
148
149 # Reconcile the cmake options for this stage.
150
151 # Make a local copy of the configure args, as we are going to modify that.
152 if extra_configure_args:
153 cmake_args = extra_configure_args[:]
154 else:
155 cmake_args = list()
156
157 # Set proper defaults.
158 CmakeCommand.applyDefaultOptions(cmake_args, [
159 ('-DCMAKE_BUILD_TYPE=', 'Release'),
160 ('-DCLANG_BUILD_EXAMPLES=', 'OFF'),
161 ('-DLLVM_BUILD_TESTS=', 'ON'),
162 ('-DLLVM_ENABLE_ASSERTIONS=', 'ON'),
163 ('-DLLVM_OPTIMIZED_TABLEGEN=', 'ON'),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000164 ])
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000165 if withLTOSupport:
166 CmakeCommand.applyDefaultOptions(cmake_args, [
167 # LTO Plugin dependency:
168 ('-DLLVM_BINUTILS_INCDIR=', '/opt/binutils/include'),
169 ])
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000170
171 # Some options are required for this stage no matter what.
172 CmakeCommand.applyRequiredOptions(cmake_args, [
173 ('-G', 'Ninja'),
174 ('-DCMAKE_INSTALL_PREFIX=', install_dir),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000175 ])
176
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000177 cmake_args.append(
178 WithProperties(
179 "-DCMAKE_CXX_COMPILER=%(workdir)s/" + staged_install + "/bin/clang++"
180 ))
181 cmake_args.append(
182 WithProperties(
183 "-DCMAKE_C_COMPILER=%(workdir)s/" + staged_install + "/bin/clang"
184 ))
185
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000186 # Create configuration files with cmake
187 f.addStep(CmakeCommand(name="cmake-configure-stage%s" % stage_num,
188 description=["stage%s cmake configure" % stage_num],
189 haltOnFailure=True,
190 options=cmake_args,
191 path=src_dir,
192 env=env,
193 workdir=obj_dir,
194 doStepIf=FileDoesNotExist("CMakeCache.txt")
195 ))
196 if withLTOSupport:
197 # Build LTO plugin if requested.
198 f.addStep(NinjaCommand(name="build-stage%s-LLVMgold.so" % stage_num,
199 targets=['lib/LLVMgold.so'],
Galina Kistanovae490af82016-12-21 00:47:26 +0000200 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000201 haltOnFailure=True,
202 description=["stage%s build LLVMgold.so" % stage_num],
203 env=env,
204 workdir=obj_dir,
205 ))
206
207 # Build clang by the staged compiler
208 f.addStep(NinjaCommand(name="build-stage%s-compiler" % stage_num,
Galina Kistanovae490af82016-12-21 00:47:26 +0000209 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000210 haltOnFailure=True,
211 description=["build stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000212 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000213 env=env,
214 workdir=obj_dir,
215 ))
216
217 # Test just built compiler
218 f.addStep(NinjaCommand(name="test-stage%s-compiler"% stage_num,
219 targets=["check-all"],
Galina Kistanovae490af82016-12-21 00:47:26 +0000220 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000221 haltOnFailure=True,
222 description=["test stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000223 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000224 env=env,
225 workdir=obj_dir,
226 ))
227
228 # Install just built compiler
229 f.addStep(NinjaCommand(name="install-stage%s-compiler"% stage_num,
230 targets=["install"],
Galina Kistanovae490af82016-12-21 00:47:26 +0000231 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000232 haltOnFailure=True,
233 description=["install stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000234 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000235 env=env,
236 workdir=obj_dir,
237 ))
238
239
240def getClangWithLTOBuildFactory(
Galina Kistanova9a7a1b62016-10-16 05:02:20 +0000241 depends_on_projects = None,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000242 clean = False,
243 jobs = None,
244 extra_configure_args = None,
245 compare_last_2_stages = True,
Galina Kistanova83d12a92016-10-13 19:32:23 +0000246 lto = None, # The string gets passed to -flto flag as is. Like -flto=thin.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000247 env = None):
248
249 # Set defaults
Galina Kistanova9a7a1b62016-10-16 05:02:20 +0000250 if depends_on_projects:
251 depends_on_projects = list(depends_on_projects)
252 else:
253 # By default we link with LLD.
254 depends_on_projects = ['llvm', 'clang', 'lld']
255
Galina Kistanova78490c72016-10-20 19:54:33 +0000256 if lto is None:
257 lto = 'ON'
258
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000259 if jobs is None:
260 jobs = "%(jobs)s"
261
262 if extra_configure_args is None:
263 extra_configure_args = []
Galina Kistanova17d62422016-10-20 18:41:02 +0000264 else:
265 extra_configure_args = list(extra_configure_args)
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000266
267 # Make sure CMAKE_INSTALL_PREFIX and -G are not specified
268 # in the extra_configure_args. We set them internally as needed.
269 # TODO: assert extra_configure_args.
270 install_prefix_specified = any(a.startswith('-DCMAKE_INSTALL_PREFIX=') for a in extra_configure_args)
Galina Kistanova06635582017-06-17 01:21:35 +0000271 assert not install_prefix_specified, "Please do not explicitly specify the install prefix for multi-stage build."
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000272
273 # Prepare environmental variables. Set here all env we want everywhere.
274 merged_env = {
275 'TERM' : 'dumb' # Be cautious and disable color output from all tools.
276 }
277 if env is not None:
278 # Overwrite pre-set items with the given ones, so user can set anything.
279 merged_env.update(env)
280
281 f = LLVMBuildFactory(
Galina Kistanova9a7a1b62016-10-16 05:02:20 +0000282 depends_on_projects=depends_on_projects,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000283 llvm_srcdir="llvm.src",
284 stage_objdirs=[
285 "build/stage1",
286 "build/stage2",
287 "build/stage3",
288 "build/stage4",
289 ],
290 stage_installdirs=[
291 "install/stage1",
292 "install/stage2",
293 "install/stage3",
294 "install/stage4",
295 ],
296 staged_compiler_idx = 1)
297
298 cleanBuildRequested = lambda step: step.build.getProperty("clean") or clean
299
300 # Do a clean checkout if requested.
301 f.addStep(RemoveDirectory(name='clean-src-dir',
302 dir=f.llvm_srcdir,
303 haltOnFailure=False,
304 flunkOnFailure=False,
305 doStepIf=cleanBuildRequested,
306 ))
307
308 # Get the source code.
309 f.addSVNSteps()
310
311 # Build with the system compiler first
312 _addSteps4SystemCompiler(f,
313 stage_idx=0,
314 clean=cleanBuildRequested,
315 jobs=jobs,
316 extra_configure_args=extra_configure_args,
317 env=merged_env)
318
319 # Then build the compiler we would use for the bootstrap.
320 _addSteps4StagedCompiler(f,
321 stage_idx=1,
322 withLTOSupport=True,
323 jobs=jobs,
324 extra_configure_args=extra_configure_args,
325 env=merged_env)
326
327 # Build all the remaining stages with exactly the same configuration.
328
Galina Kistanova17d62422016-10-20 18:41:02 +0000329 CmakeCommand.applyRequiredOptions(extra_configure_args, [
Galina Kistanova78490c72016-10-20 19:54:33 +0000330 ('-DLLVM_ENABLE_LTO=', lto),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000331 ])
332
Galina Kistanova17d62422016-10-20 18:41:02 +0000333 # If we build LLD, we would link with LLD.
334 # Otherwise we link with the system linker.
335 if 'lld' in depends_on_projects:
336 CmakeCommand.applyRequiredOptions(extra_configure_args, [
337 ('-DLLVM_ENABLE_LLD=', 'ON'),
338 ])
339
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000340 # The rest are test stages, which depend on the staged compiler we are ultimately after.
Galina Kistanovab1668332017-07-07 02:00:28 +0000341 s = f.staged_compiler_idx + 1
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000342 staged_install = f.stage_installdirs[f.staged_compiler_idx]
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000343 for i in range(s, len(f.stage_objdirs[s:]) + s):
344 configure_args = extra_configure_args[:]
345
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000346 configure_args.append(
347 WithProperties(
348 "-DCMAKE_AR=%(workdir)s/" + staged_install + "/bin/llvm-ar"
349 ))
350 configure_args.append(
351 WithProperties(
352 "-DCMAKE_RANLIB=%(workdir)s/" + staged_install + "/bin/llvm-ranlib"
353 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000354
355 _addSteps4StagedCompiler(f,
356 stage_idx=i,
357 use_stage_idx=f.staged_compiler_idx,
358 jobs=jobs,
359 extra_configure_args=configure_args,
360 env=merged_env)
361
362 if compare_last_2_stages:
363 # Compare the compilers built on the last 2 stages if requested.
364 diff_command = [
365 "diff",
366 "-q",
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000367 f.stage_installdirs[-2] + "/bin/clang",
368 f.stage_installdirs[-1] + "/bin/clang",
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000369 ]
370 f.addStep(
371 ShellCommand(
372 name="compare-compilers",
373 description=[
374 "compare",
375 "stage%d" % (len(f.stage_installdirs)-1),
376 "and",
377 "stage%d" % len(f.stage_installdirs),
378 "compilers",
379 ],
Galina Kistanovab1668332017-07-07 02:00:28 +0000380 haltOnFailure=False,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000381 command=WithProperties(" ".join(diff_command)),
382 workdir=".",
383 env=merged_env
384 )
385 )
386
Galina Kistanovab1668332017-07-07 02:00:28 +0000387 # Only if the compare-compilers step has failed.
388 def _prevStepFailed(step):
389 steps = step.build.getStatus().getSteps()
390 prev_step = steps[-2]
391 (result, _) = prev_step.getResults()
392 return (result == FAILURE)
393
394 dir1 = f.stage_objdirs[-2]
395 dir2 = f.stage_objdirs[-1]
396 inc_pattern = "-type f -not -name *.inc -printf '%f\n'"
397 find_cmd = "find %s %s" % (dir1, dir2)
398 diff_cmd = "diff -ru %s %s -x '*.tmp*' -X -" % (dir1, dir2)
399
400 # Note: Use a string here as we want the command executed by a shell.
401 diff_tablegen_inc_files_command = "%s %s | %s" % (find_cmd, inc_pattern, diff_cmd)
402
403 f.addStep(
404 ShellCommand(
405 name="compare-tablegen-inc-files",
406 description=[
407 "compare",
408 "stage%d" % (len(f.stage_installdirs)-1),
409 "and",
410 "stage%d" % len(f.stage_installdirs),
411 "Tablegen inc files",
412 ],
413 command=diff_tablegen_inc_files_command,
414 workdir=".",
415 env=merged_env,
416 doStepIf=_prevStepFailed,
417 )
418 )
419
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000420 return f