blob: 448bcf025eb76b24e5a6f65ca94479aa9856c1a4 [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,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000119 jobs = None,
120 extra_configure_args = None,
121 env = None):
122
123 if use_stage_idx < 0:
124 use_stage_idx = stage_idx - 1
125
126 # Index is zero-based, so we want to use a human friendly number instead.
127 stage_num = stage_idx + 1
128
129 # Directories to use on this stage.
130 obj_dir = f.stage_objdirs[stage_idx]
131 src_dir = LLVMBuildFactory.pathRelativeToBuild(f.llvm_srcdir, obj_dir)
132 install_dir = LLVMBuildFactory.pathRelativeToBuild(f.stage_installdirs[stage_idx], obj_dir)
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000133 staged_install = f.stage_installdirs[use_stage_idx]
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000134
135 # Always do a clean build for the staged compiler.
136 f.addStep(RemoveDirectory(name='clean-%s-dir' % obj_dir,
137 dir=obj_dir,
138 haltOnFailure=False,
139 flunkOnFailure=False,
140 ))
141
142 f.addStep(RemoveDirectory(name='clean-%s-dir' % f.stage_installdirs[stage_idx],
143 dir=f.stage_installdirs[stage_idx],
144 haltOnFailure=False,
145 flunkOnFailure=False,
146 ))
147
148 # Reconcile the cmake options for this stage.
149
150 # Make a local copy of the configure args, as we are going to modify that.
151 if extra_configure_args:
152 cmake_args = extra_configure_args[:]
153 else:
154 cmake_args = list()
155
156 # Set proper defaults.
157 CmakeCommand.applyDefaultOptions(cmake_args, [
158 ('-DCMAKE_BUILD_TYPE=', 'Release'),
159 ('-DCLANG_BUILD_EXAMPLES=', 'OFF'),
160 ('-DLLVM_BUILD_TESTS=', 'ON'),
161 ('-DLLVM_ENABLE_ASSERTIONS=', 'ON'),
162 ('-DLLVM_OPTIMIZED_TABLEGEN=', 'ON'),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000163 ])
164
165 # Some options are required for this stage no matter what.
166 CmakeCommand.applyRequiredOptions(cmake_args, [
167 ('-G', 'Ninja'),
168 ('-DCMAKE_INSTALL_PREFIX=', install_dir),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000169 ])
170
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000171 cmake_args.append(
172 WithProperties(
173 "-DCMAKE_CXX_COMPILER=%(workdir)s/" + staged_install + "/bin/clang++"
174 ))
175 cmake_args.append(
176 WithProperties(
177 "-DCMAKE_C_COMPILER=%(workdir)s/" + staged_install + "/bin/clang"
178 ))
179
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000180 # Create configuration files with cmake
181 f.addStep(CmakeCommand(name="cmake-configure-stage%s" % stage_num,
182 description=["stage%s cmake configure" % stage_num],
183 haltOnFailure=True,
184 options=cmake_args,
185 path=src_dir,
186 env=env,
187 workdir=obj_dir,
188 doStepIf=FileDoesNotExist("CMakeCache.txt")
189 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000190
191 # Build clang by the staged compiler
192 f.addStep(NinjaCommand(name="build-stage%s-compiler" % stage_num,
Galina Kistanovae490af82016-12-21 00:47:26 +0000193 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000194 haltOnFailure=True,
195 description=["build stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000196 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000197 env=env,
198 workdir=obj_dir,
199 ))
200
201 # Test just built compiler
202 f.addStep(NinjaCommand(name="test-stage%s-compiler"% stage_num,
203 targets=["check-all"],
Galina Kistanovae490af82016-12-21 00:47:26 +0000204 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000205 haltOnFailure=True,
206 description=["test 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 # Install just built compiler
213 f.addStep(NinjaCommand(name="install-stage%s-compiler"% stage_num,
214 targets=["install"],
Galina Kistanovae490af82016-12-21 00:47:26 +0000215 jobs=jobs,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000216 haltOnFailure=True,
217 description=["install 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
224def getClangWithLTOBuildFactory(
Galina Kistanova9a7a1b62016-10-16 05:02:20 +0000225 depends_on_projects = None,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000226 clean = False,
227 jobs = None,
228 extra_configure_args = None,
229 compare_last_2_stages = True,
Galina Kistanova83d12a92016-10-13 19:32:23 +0000230 lto = None, # The string gets passed to -flto flag as is. Like -flto=thin.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000231 env = None):
232
233 # Set defaults
Galina Kistanova9a7a1b62016-10-16 05:02:20 +0000234 if depends_on_projects:
235 depends_on_projects = list(depends_on_projects)
236 else:
237 # By default we link with LLD.
238 depends_on_projects = ['llvm', 'clang', 'lld']
239
Galina Kistanova78490c72016-10-20 19:54:33 +0000240 if lto is None:
241 lto = 'ON'
242
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000243 if jobs is None:
244 jobs = "%(jobs)s"
245
246 if extra_configure_args is None:
247 extra_configure_args = []
Galina Kistanova17d62422016-10-20 18:41:02 +0000248 else:
249 extra_configure_args = list(extra_configure_args)
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000250
251 # Make sure CMAKE_INSTALL_PREFIX and -G are not specified
252 # in the extra_configure_args. We set them internally as needed.
253 # TODO: assert extra_configure_args.
254 install_prefix_specified = any(a.startswith('-DCMAKE_INSTALL_PREFIX=') for a in extra_configure_args)
Galina Kistanova06635582017-06-17 01:21:35 +0000255 assert not install_prefix_specified, "Please do not explicitly specify the install prefix for multi-stage build."
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000256
257 # Prepare environmental variables. Set here all env we want everywhere.
258 merged_env = {
259 'TERM' : 'dumb' # Be cautious and disable color output from all tools.
260 }
261 if env is not None:
262 # Overwrite pre-set items with the given ones, so user can set anything.
263 merged_env.update(env)
264
265 f = LLVMBuildFactory(
Galina Kistanova9a7a1b62016-10-16 05:02:20 +0000266 depends_on_projects=depends_on_projects,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000267 stage_objdirs=[
268 "build/stage1",
269 "build/stage2",
270 "build/stage3",
271 "build/stage4",
272 ],
273 stage_installdirs=[
274 "install/stage1",
275 "install/stage2",
276 "install/stage3",
277 "install/stage4",
278 ],
279 staged_compiler_idx = 1)
280
281 cleanBuildRequested = lambda step: step.build.getProperty("clean") or clean
282
283 # Do a clean checkout if requested.
284 f.addStep(RemoveDirectory(name='clean-src-dir',
285 dir=f.llvm_srcdir,
286 haltOnFailure=False,
287 flunkOnFailure=False,
288 doStepIf=cleanBuildRequested,
289 ))
290
291 # Get the source code.
Galina Kistanova1c20bf32019-10-15 23:12:30 +0000292 f.addGetSourcecodeSteps()
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000293
294 # Build with the system compiler first
295 _addSteps4SystemCompiler(f,
296 stage_idx=0,
297 clean=cleanBuildRequested,
298 jobs=jobs,
299 extra_configure_args=extra_configure_args,
300 env=merged_env)
301
302 # Then build the compiler we would use for the bootstrap.
303 _addSteps4StagedCompiler(f,
304 stage_idx=1,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000305 jobs=jobs,
306 extra_configure_args=extra_configure_args,
307 env=merged_env)
308
309 # Build all the remaining stages with exactly the same configuration.
310
Galina Kistanova17d62422016-10-20 18:41:02 +0000311 CmakeCommand.applyRequiredOptions(extra_configure_args, [
Galina Kistanova78490c72016-10-20 19:54:33 +0000312 ('-DLLVM_ENABLE_LTO=', lto),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000313 ])
314
Galina Kistanova17d62422016-10-20 18:41:02 +0000315 # If we build LLD, we would link with LLD.
316 # Otherwise we link with the system linker.
317 if 'lld' in depends_on_projects:
318 CmakeCommand.applyRequiredOptions(extra_configure_args, [
319 ('-DLLVM_ENABLE_LLD=', 'ON'),
320 ])
321
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000322 # The rest are test stages, which depend on the staged compiler we are ultimately after.
Galina Kistanovab1668332017-07-07 02:00:28 +0000323 s = f.staged_compiler_idx + 1
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000324 staged_install = f.stage_installdirs[f.staged_compiler_idx]
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000325 for i in range(s, len(f.stage_objdirs[s:]) + s):
326 configure_args = extra_configure_args[:]
327
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000328 configure_args.append(
329 WithProperties(
330 "-DCMAKE_AR=%(workdir)s/" + staged_install + "/bin/llvm-ar"
331 ))
332 configure_args.append(
333 WithProperties(
334 "-DCMAKE_RANLIB=%(workdir)s/" + staged_install + "/bin/llvm-ranlib"
335 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000336
337 _addSteps4StagedCompiler(f,
338 stage_idx=i,
339 use_stage_idx=f.staged_compiler_idx,
340 jobs=jobs,
341 extra_configure_args=configure_args,
342 env=merged_env)
343
344 if compare_last_2_stages:
345 # Compare the compilers built on the last 2 stages if requested.
346 diff_command = [
347 "diff",
348 "-q",
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000349 f.stage_installdirs[-2] + "/bin/clang",
350 f.stage_installdirs[-1] + "/bin/clang",
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000351 ]
352 f.addStep(
353 ShellCommand(
354 name="compare-compilers",
355 description=[
356 "compare",
357 "stage%d" % (len(f.stage_installdirs)-1),
358 "and",
359 "stage%d" % len(f.stage_installdirs),
360 "compilers",
361 ],
Galina Kistanovab1668332017-07-07 02:00:28 +0000362 haltOnFailure=False,
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000363 command=WithProperties(" ".join(diff_command)),
364 workdir=".",
365 env=merged_env
366 )
367 )
368
Galina Kistanovab1668332017-07-07 02:00:28 +0000369 # Only if the compare-compilers step has failed.
370 def _prevStepFailed(step):
371 steps = step.build.getStatus().getSteps()
372 prev_step = steps[-2]
373 (result, _) = prev_step.getResults()
374 return (result == FAILURE)
375
376 dir1 = f.stage_objdirs[-2]
377 dir2 = f.stage_objdirs[-1]
378 inc_pattern = "-type f -not -name *.inc -printf '%f\n'"
379 find_cmd = "find %s %s" % (dir1, dir2)
380 diff_cmd = "diff -ru %s %s -x '*.tmp*' -X -" % (dir1, dir2)
381
382 # Note: Use a string here as we want the command executed by a shell.
383 diff_tablegen_inc_files_command = "%s %s | %s" % (find_cmd, inc_pattern, diff_cmd)
384
385 f.addStep(
386 ShellCommand(
387 name="compare-tablegen-inc-files",
388 description=[
389 "compare",
390 "stage%d" % (len(f.stage_installdirs)-1),
391 "and",
392 "stage%d" % len(f.stage_installdirs),
393 "Tablegen inc files",
394 ],
395 command=diff_tablegen_inc_files_command,
396 workdir=".",
397 env=merged_env,
398 doStepIf=_prevStepFailed,
399 )
400 )
401
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000402 return f