blob: 15858ff5cfdc44dc7066994e29195e448ad7a082 [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
Galina Kistanova51129ad2019-10-20 03:53:16 +000010from zorg.buildbot.builders import UnifiedTreeBuilder
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000011
12def _addSteps4SystemCompiler(
13 f,
14 stage_idx = 0,
15 clean = True,
16 jobs = None,
17 extra_configure_args = None,
18 env = None):
19
20 # Index is zero-based, so we want to use a human friendly number instead.
21 stage_num = stage_idx + 1
22
23 # Directories to use on this stage.
24 obj_dir = f.stage_objdirs[stage_idx]
25 src_dir = LLVMBuildFactory.pathRelativeToBuild(f.llvm_srcdir, obj_dir)
26 install_dir = LLVMBuildFactory.pathRelativeToBuild(f.stage_installdirs[stage_idx], obj_dir)
27
28 # This stage could use incremental build.
29 # Clean stage1, only if requested.
30 f.addStep(RemoveDirectory(name='clean-%s-dir' % obj_dir,
31 dir=obj_dir,
32 haltOnFailure=False,
33 flunkOnFailure=False,
34 doStepIf=clean
35 ))
36 f.addStep(RemoveDirectory(name='clean-%s-dir' % f.stage_installdirs[stage_idx],
37 dir=f.stage_installdirs[stage_idx],
38 haltOnFailure=False,
39 flunkOnFailure=False,
40 doStepIf=clean
41 ))
42
43 # Reconcile the cmake options for this stage.
44
45 # Make a local copy of the configure args, as we are going to modify that.
46 if extra_configure_args:
47 cmake_args = extra_configure_args[:]
48 else:
49 cmake_args = list()
50
51 # Set proper defaults.
52 CmakeCommand.applyDefaultOptions(cmake_args, [
53 ('-DCMAKE_BUILD_TYPE=', 'Release'),
54 ('-DCLANG_BUILD_EXAMPLES=', 'OFF'),
55 ('-DLLVM_BUILD_TESTS=', 'ON'),
56 ('-DLLVM_ENABLE_ASSERTIONS=', 'OFF'),
57 ('-DLLVM_OPTIMIZED_TABLEGEN=', 'ON'),
58 # Do not expect warning free build by the system toolchain.
59 ('-DLLVM_ENABLE_WERROR=', 'OFF'),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000060 ])
61
62 # Some options are required for this stage no matter what.
63 CmakeCommand.applyRequiredOptions(cmake_args, [
Galina Kistanova122a6f42017-09-21 19:19:28 +000064 ('-G', 'Ninja'),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000065 ('-DCMAKE_INSTALL_PREFIX=', install_dir),
66 ])
67
Galina Kistanova51129ad2019-10-20 03:53:16 +000068 if not f.is_legacy_mode:
69 CmakeCommand.applyRequiredOptions(cmake_args, [
70 ('-DLLVM_ENABLE_PROJECTS=', ";".join(f.depends_on_projects)),
71 ])
72
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000073 # Note: On this stage we do not care of warnings, as we build with
74 # a system toolchain and cannot control the environment.
75 # Warnings are likely, and we ignore them.
76
77 # Create configuration files with cmake
78 f.addStep(CmakeCommand(name="cmake-configure-stage%s" % stage_num,
79 description=["stage%s cmake configure" % stage_num],
80 haltOnFailure=True,
81 flunkOnWarnings=False,
82 options=cmake_args,
83 path=src_dir,
84 env=env,
85 workdir=obj_dir,
Galina Kistanova122a6f42017-09-21 19:19:28 +000086 doStepIf=FileDoesNotExist("CMakeCache.txt")
87 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000088
89 # Build clang by the system compiler
Galina Kistanova122a6f42017-09-21 19:19:28 +000090 f.addStep(NinjaCommand(name="build-stage%s-compiler" % stage_num,
91 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000092 haltOnFailure=True,
93 flunkOnWarnings=False,
94 description=["build stage%s compiler" % stage_num],
95 env=env,
Galina Kistanova122a6f42017-09-21 19:19:28 +000096 workdir=obj_dir,
97 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +000098
99 # Test stage1 compiler
Galina Kistanova122a6f42017-09-21 19:19:28 +0000100 f.addStep(NinjaCommand(name="test-stage%s-compiler"% stage_num,
101 targets=["check-all"], # or "check-llvm", "check-clang"
102 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000103 haltOnFailure=True,
104 flunkOnWarnings=False,
105 description=["test stage%s compiler" % stage_num],
106 env=env,
Galina Kistanova122a6f42017-09-21 19:19:28 +0000107 workdir=obj_dir,
108 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000109
110 # Install stage1 compiler
Galina Kistanova122a6f42017-09-21 19:19:28 +0000111 f.addStep(NinjaCommand(name="install-stage%s-compiler"% stage_num,
112 targets=["install"],
113 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000114 haltOnFailure=True,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000115 description=["install stage%s compiler" % stage_num],
116 env=env,
Galina Kistanova122a6f42017-09-21 19:19:28 +0000117 workdir=obj_dir,
118 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000119
120
121def _addSteps4StagedCompiler(
122 f,
123 stage_idx = 1,
124 use_stage_idx = -1,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000125 jobs = None,
126 extra_configure_args = None,
127 env = None):
128
129 if use_stage_idx < 0:
130 use_stage_idx = stage_idx - 1
131
132 # Index is zero-based, so we want to use a human friendly number instead.
133 stage_num = stage_idx + 1
134
135 # Directories to use on this stage.
136 obj_dir = f.stage_objdirs[stage_idx]
137 src_dir = LLVMBuildFactory.pathRelativeToBuild(f.llvm_srcdir, obj_dir)
138 install_dir = LLVMBuildFactory.pathRelativeToBuild(f.stage_installdirs[stage_idx], obj_dir)
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000139 staged_install = f.stage_installdirs[use_stage_idx]
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000140
141 # Always do a clean build for the staged compiler.
142 f.addStep(RemoveDirectory(name='clean-%s-dir' % obj_dir,
143 dir=obj_dir,
144 haltOnFailure=False,
145 flunkOnFailure=False,
146 ))
147
148 f.addStep(RemoveDirectory(name='clean-%s-dir' % f.stage_installdirs[stage_idx],
149 dir=f.stage_installdirs[stage_idx],
150 haltOnFailure=False,
151 flunkOnFailure=False,
152 ))
153
154 # Reconcile the cmake options for this stage.
155
156 # Make a local copy of the configure args, as we are going to modify that.
157 if extra_configure_args:
158 cmake_args = extra_configure_args[:]
159 else:
160 cmake_args = list()
161
162 # Set proper defaults.
163 CmakeCommand.applyDefaultOptions(cmake_args, [
164 ('-DCMAKE_BUILD_TYPE=', 'Release'),
165 ('-DCLANG_BUILD_EXAMPLES=', 'OFF'),
166 ('-DLLVM_BUILD_TESTS=', 'ON'),
167 ('-DLLVM_ENABLE_ASSERTIONS=', 'ON'),
168 ('-DLLVM_OPTIMIZED_TABLEGEN=', 'ON'),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000169 ])
170
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 Kistanova51129ad2019-10-20 03:53:16 +0000186 if not f.is_legacy_mode:
187 CmakeCommand.applyRequiredOptions(cmake_args, [
188 ('-DLLVM_ENABLE_PROJECTS=', ";".join(f.depends_on_projects)),
189 ])
190
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000191 # Create configuration files with cmake
192 f.addStep(CmakeCommand(name="cmake-configure-stage%s" % stage_num,
193 description=["stage%s cmake configure" % stage_num],
194 haltOnFailure=True,
195 options=cmake_args,
196 path=src_dir,
197 env=env,
198 workdir=obj_dir,
199 doStepIf=FileDoesNotExist("CMakeCache.txt")
200 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000201
202 # Build clang by the staged compiler
203 f.addStep(NinjaCommand(name="build-stage%s-compiler" % stage_num,
Galina Kistanovae490af82016-12-21 00:47:26 +0000204 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000205 haltOnFailure=True,
206 description=["build stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000207 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000208 env=env,
209 workdir=obj_dir,
210 ))
211
212 # Test just built compiler
213 f.addStep(NinjaCommand(name="test-stage%s-compiler"% stage_num,
214 targets=["check-all"],
Galina Kistanovae490af82016-12-21 00:47:26 +0000215 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000216 haltOnFailure=True,
217 description=["test stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000218 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000219 env=env,
220 workdir=obj_dir,
221 ))
222
223 # Install just built compiler
224 f.addStep(NinjaCommand(name="install-stage%s-compiler"% stage_num,
225 targets=["install"],
Galina Kistanovae490af82016-12-21 00:47:26 +0000226 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000227 haltOnFailure=True,
228 description=["install stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000229 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000230 env=env,
231 workdir=obj_dir,
232 ))
233
234
235def getClangWithLTOBuildFactory(
Galina Kistanova9a7a1b62016-10-16 05:02:20 +0000236 depends_on_projects = None,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000237 clean = False,
238 jobs = None,
239 extra_configure_args = None,
240 compare_last_2_stages = True,
Galina Kistanova83d12a92016-10-13 19:32:23 +0000241 lto = None, # The string gets passed to -flto flag as is. Like -flto=thin.
Galina Kistanova51129ad2019-10-20 03:53:16 +0000242 env = None,
243 **kwargs):
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000244
245 # Set defaults
Galina Kistanova9a7a1b62016-10-16 05:02:20 +0000246 if depends_on_projects:
247 depends_on_projects = list(depends_on_projects)
248 else:
249 # By default we link with LLD.
250 depends_on_projects = ['llvm', 'clang', 'lld']
251
Galina Kistanova78490c72016-10-20 19:54:33 +0000252 if lto is None:
253 lto = 'ON'
254
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000255 if jobs is None:
256 jobs = "%(jobs)s"
257
258 if extra_configure_args is None:
259 extra_configure_args = []
Galina Kistanova17d62422016-10-20 18:41:02 +0000260 else:
261 extra_configure_args = list(extra_configure_args)
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000262
263 # Make sure CMAKE_INSTALL_PREFIX and -G are not specified
264 # in the extra_configure_args. We set them internally as needed.
265 # TODO: assert extra_configure_args.
266 install_prefix_specified = any(a.startswith('-DCMAKE_INSTALL_PREFIX=') for a in extra_configure_args)
Galina Kistanova06635582017-06-17 01:21:35 +0000267 assert not install_prefix_specified, "Please do not explicitly specify the install prefix for multi-stage build."
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000268
269 # Prepare environmental variables. Set here all env we want everywhere.
270 merged_env = {
271 'TERM' : 'dumb' # Be cautious and disable color output from all tools.
272 }
273 if env is not None:
274 # Overwrite pre-set items with the given ones, so user can set anything.
275 merged_env.update(env)
276
Galina Kistanova51129ad2019-10-20 03:53:16 +0000277 f = UnifiedTreeBuilder.getLLVMBuildFactoryAndPrepareForSourcecodeSteps(
Galina Kistanova9a7a1b62016-10-16 05:02:20 +0000278 depends_on_projects=depends_on_projects,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000279 stage_objdirs=[
280 "build/stage1",
281 "build/stage2",
282 "build/stage3",
283 "build/stage4",
284 ],
285 stage_installdirs=[
286 "install/stage1",
287 "install/stage2",
288 "install/stage3",
289 "install/stage4",
290 ],
Galina Kistanova51129ad2019-10-20 03:53:16 +0000291 staged_compiler_idx = 1,
292 **kwargs)
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000293
Galina Kistanova51129ad2019-10-20 03:53:16 +0000294 # Consume is_legacy_mode if given.
295 # TODO: Remove this once legacy mode gets dropped.
296 kwargs.pop('is_legacy_mode', None)
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000297
Galina Kistanova51129ad2019-10-20 03:53:16 +0000298 cleanBuildRequested = lambda step: clean or step.build.getProperty("clean", default=step.build.getProperty("clean_obj"))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000299
300 # Get the source code.
Galina Kistanova1c20bf32019-10-15 23:12:30 +0000301 f.addGetSourcecodeSteps()
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000302
303 # Build with the system compiler first
304 _addSteps4SystemCompiler(f,
305 stage_idx=0,
306 clean=cleanBuildRequested,
307 jobs=jobs,
308 extra_configure_args=extra_configure_args,
309 env=merged_env)
310
311 # Then build the compiler we would use for the bootstrap.
312 _addSteps4StagedCompiler(f,
313 stage_idx=1,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000314 jobs=jobs,
315 extra_configure_args=extra_configure_args,
316 env=merged_env)
317
318 # Build all the remaining stages with exactly the same configuration.
319
Galina Kistanova17d62422016-10-20 18:41:02 +0000320 CmakeCommand.applyRequiredOptions(extra_configure_args, [
Galina Kistanova78490c72016-10-20 19:54:33 +0000321 ('-DLLVM_ENABLE_LTO=', lto),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000322 ])
323
Galina Kistanova17d62422016-10-20 18:41:02 +0000324 # If we build LLD, we would link with LLD.
325 # Otherwise we link with the system linker.
326 if 'lld' in depends_on_projects:
327 CmakeCommand.applyRequiredOptions(extra_configure_args, [
328 ('-DLLVM_ENABLE_LLD=', 'ON'),
329 ])
330
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000331 # The rest are test stages, which depend on the staged compiler we are ultimately after.
Galina Kistanovab1668332017-07-07 02:00:28 +0000332 s = f.staged_compiler_idx + 1
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000333 staged_install = f.stage_installdirs[f.staged_compiler_idx]
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000334 for i in range(s, len(f.stage_objdirs[s:]) + s):
335 configure_args = extra_configure_args[:]
336
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000337 configure_args.append(
338 WithProperties(
339 "-DCMAKE_AR=%(workdir)s/" + staged_install + "/bin/llvm-ar"
340 ))
341 configure_args.append(
342 WithProperties(
343 "-DCMAKE_RANLIB=%(workdir)s/" + staged_install + "/bin/llvm-ranlib"
344 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000345
346 _addSteps4StagedCompiler(f,
347 stage_idx=i,
348 use_stage_idx=f.staged_compiler_idx,
349 jobs=jobs,
350 extra_configure_args=configure_args,
351 env=merged_env)
352
353 if compare_last_2_stages:
354 # Compare the compilers built on the last 2 stages if requested.
355 diff_command = [
356 "diff",
357 "-q",
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000358 f.stage_installdirs[-2] + "/bin/clang",
359 f.stage_installdirs[-1] + "/bin/clang",
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000360 ]
361 f.addStep(
362 ShellCommand(
363 name="compare-compilers",
364 description=[
365 "compare",
366 "stage%d" % (len(f.stage_installdirs)-1),
367 "and",
368 "stage%d" % len(f.stage_installdirs),
369 "compilers",
370 ],
Galina Kistanovab1668332017-07-07 02:00:28 +0000371 haltOnFailure=False,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000372 command=WithProperties(" ".join(diff_command)),
373 workdir=".",
374 env=merged_env
375 )
376 )
377
Galina Kistanovab1668332017-07-07 02:00:28 +0000378 # Only if the compare-compilers step has failed.
379 def _prevStepFailed(step):
380 steps = step.build.getStatus().getSteps()
381 prev_step = steps[-2]
382 (result, _) = prev_step.getResults()
383 return (result == FAILURE)
384
385 dir1 = f.stage_objdirs[-2]
386 dir2 = f.stage_objdirs[-1]
387 inc_pattern = "-type f -not -name *.inc -printf '%f\n'"
388 find_cmd = "find %s %s" % (dir1, dir2)
389 diff_cmd = "diff -ru %s %s -x '*.tmp*' -X -" % (dir1, dir2)
390
391 # Note: Use a string here as we want the command executed by a shell.
392 diff_tablegen_inc_files_command = "%s %s | %s" % (find_cmd, inc_pattern, diff_cmd)
393
394 f.addStep(
395 ShellCommand(
396 name="compare-tablegen-inc-files",
397 description=[
398 "compare",
399 "stage%d" % (len(f.stage_installdirs)-1),
400 "and",
401 "stage%d" % len(f.stage_installdirs),
402 "Tablegen inc files",
403 ],
404 command=diff_tablegen_inc_files_command,
405 workdir=".",
406 env=merged_env,
407 doStepIf=_prevStepFailed,
408 )
409 )
410
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000411 return f