blob: 2c88f82a13363c5c867c69c67954598195dec71d [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 Kistanovab3ff2752016-08-15 19:35:56 +00003from buildbot.process.properties import WithProperties
Galina Kistanova1e2edfc2016-08-08 22:08:21 +00004
5from zorg.buildbot.commands.CmakeCommand import CmakeCommand
6from zorg.buildbot.commands.NinjaCommand import NinjaCommand
7from zorg.buildbot.conditions.FileConditions import FileDoesNotExist
8from zorg.buildbot.process.factory import LLVMBuildFactory
9
10def _addSteps4SystemCompiler(
11 f,
12 stage_idx = 0,
13 clean = True,
14 jobs = None,
15 extra_configure_args = None,
16 env = None):
17
18 # Index is zero-based, so we want to use a human friendly number instead.
19 stage_num = stage_idx + 1
20
21 # Directories to use on this stage.
22 obj_dir = f.stage_objdirs[stage_idx]
23 src_dir = LLVMBuildFactory.pathRelativeToBuild(f.llvm_srcdir, obj_dir)
24 install_dir = LLVMBuildFactory.pathRelativeToBuild(f.stage_installdirs[stage_idx], obj_dir)
25
26 # This stage could use incremental build.
27 # Clean stage1, only if requested.
28 f.addStep(RemoveDirectory(name='clean-%s-dir' % obj_dir,
29 dir=obj_dir,
30 haltOnFailure=False,
31 flunkOnFailure=False,
32 doStepIf=clean
33 ))
34 f.addStep(RemoveDirectory(name='clean-%s-dir' % f.stage_installdirs[stage_idx],
35 dir=f.stage_installdirs[stage_idx],
36 haltOnFailure=False,
37 flunkOnFailure=False,
38 doStepIf=clean
39 ))
40
41 # Reconcile the cmake options for this stage.
42
43 # Make a local copy of the configure args, as we are going to modify that.
44 if extra_configure_args:
45 cmake_args = extra_configure_args[:]
46 else:
47 cmake_args = list()
48
49 # Set proper defaults.
50 CmakeCommand.applyDefaultOptions(cmake_args, [
51 ('-DCMAKE_BUILD_TYPE=', 'Release'),
52 ('-DCLANG_BUILD_EXAMPLES=', 'OFF'),
53 ('-DLLVM_BUILD_TESTS=', 'ON'),
54 ('-DLLVM_ENABLE_ASSERTIONS=', 'OFF'),
55 ('-DLLVM_OPTIMIZED_TABLEGEN=', 'ON'),
56 # Do not expect warning free build by the system toolchain.
57 ('-DLLVM_ENABLE_WERROR=', 'OFF'),
58 ('-DCMAKE_COLOR_MAKEFILE=', 'OFF'),
59 ])
60
61 # Some options are required for this stage no matter what.
62 CmakeCommand.applyRequiredOptions(cmake_args, [
63 ('-G', 'Unix Makefiles'),
64 ('-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,
80 doStepIf=FileDoesNotExist("CMakeCache.txt")))
81
82 # Build clang by the system compiler
83 f.addStep(ShellCommand(name="build-stage%s-compiler"% stage_num,
84 command=['make', WithProperties("-j%s" % jobs), "-k"],
85 haltOnFailure=True,
86 flunkOnWarnings=False,
87 description=["build stage%s compiler" % stage_num],
88 env=env,
89 workdir=obj_dir))
90
91 # Test stage1 compiler
92 f.addStep(ShellCommand(name="test-stage%s-compiler"% stage_num,
93 command=["make", WithProperties("-j%s" % jobs), "check-all"], # or "check-llvm", "check-clang"
94 haltOnFailure=True,
95 flunkOnWarnings=False,
96 description=["test stage%s compiler" % stage_num],
97 env=env,
98 workdir=obj_dir))
99
100 # Install stage1 compiler
101 f.addStep(ShellCommand(name="install-stage%s-compiler"% stage_num,
102 command=["make", WithProperties("-j%s" % jobs), "install"],
103 haltOnFailure=True,
104 flunkOnWarnings=False,
105 description=["install stage%s compiler" % stage_num],
106 env=env,
107 workdir=obj_dir))
108
109
110def _addSteps4StagedCompiler(
111 f,
112 stage_idx = 1,
113 use_stage_idx = -1,
114 withLTOSupport = False,
115 jobs = None,
116 extra_configure_args = None,
117 env = None):
118
119 if use_stage_idx < 0:
120 use_stage_idx = stage_idx - 1
121
122 # Index is zero-based, so we want to use a human friendly number instead.
123 stage_num = stage_idx + 1
124
125 # Directories to use on this stage.
126 obj_dir = f.stage_objdirs[stage_idx]
127 src_dir = LLVMBuildFactory.pathRelativeToBuild(f.llvm_srcdir, obj_dir)
128 install_dir = LLVMBuildFactory.pathRelativeToBuild(f.stage_installdirs[stage_idx], obj_dir)
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000129 staged_install = f.stage_installdirs[use_stage_idx]
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000130
131 # Always do a clean build for the staged compiler.
132 f.addStep(RemoveDirectory(name='clean-%s-dir' % obj_dir,
133 dir=obj_dir,
134 haltOnFailure=False,
135 flunkOnFailure=False,
136 ))
137
138 f.addStep(RemoveDirectory(name='clean-%s-dir' % f.stage_installdirs[stage_idx],
139 dir=f.stage_installdirs[stage_idx],
140 haltOnFailure=False,
141 flunkOnFailure=False,
142 ))
143
144 # Reconcile the cmake options for this stage.
145
146 # Make a local copy of the configure args, as we are going to modify that.
147 if extra_configure_args:
148 cmake_args = extra_configure_args[:]
149 else:
150 cmake_args = list()
151
152 # Set proper defaults.
153 CmakeCommand.applyDefaultOptions(cmake_args, [
154 ('-DCMAKE_BUILD_TYPE=', 'Release'),
155 ('-DCLANG_BUILD_EXAMPLES=', 'OFF'),
156 ('-DLLVM_BUILD_TESTS=', 'ON'),
157 ('-DLLVM_ENABLE_ASSERTIONS=', 'ON'),
158 ('-DLLVM_OPTIMIZED_TABLEGEN=', 'ON'),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000159 ])
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000160 if withLTOSupport:
161 CmakeCommand.applyDefaultOptions(cmake_args, [
162 # LTO Plugin dependency:
163 ('-DLLVM_BINUTILS_INCDIR=', '/opt/binutils/include'),
164 ])
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000165
166 # Some options are required for this stage no matter what.
167 CmakeCommand.applyRequiredOptions(cmake_args, [
168 ('-G', 'Ninja'),
169 ('-DCMAKE_INSTALL_PREFIX=', install_dir),
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000170 ])
171
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000172 cmake_args.append(
173 WithProperties(
174 "-DCMAKE_CXX_COMPILER=%(workdir)s/" + staged_install + "/bin/clang++"
175 ))
176 cmake_args.append(
177 WithProperties(
178 "-DCMAKE_C_COMPILER=%(workdir)s/" + staged_install + "/bin/clang"
179 ))
180
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000181 # Create configuration files with cmake
182 f.addStep(CmakeCommand(name="cmake-configure-stage%s" % stage_num,
183 description=["stage%s cmake configure" % stage_num],
184 haltOnFailure=True,
185 options=cmake_args,
186 path=src_dir,
187 env=env,
188 workdir=obj_dir,
189 doStepIf=FileDoesNotExist("CMakeCache.txt")
190 ))
191 if withLTOSupport:
192 # Build LTO plugin if requested.
193 f.addStep(NinjaCommand(name="build-stage%s-LLVMgold.so" % stage_num,
194 targets=['lib/LLVMgold.so'],
195 haltOnFailure=True,
196 description=["stage%s build LLVMgold.so" % stage_num],
197 env=env,
198 workdir=obj_dir,
199 ))
200
201 # Build clang by the staged compiler
202 f.addStep(NinjaCommand(name="build-stage%s-compiler" % stage_num,
203 haltOnFailure=True,
204 description=["build stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000205 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000206 env=env,
207 workdir=obj_dir,
208 ))
209
210 # Test just built compiler
211 f.addStep(NinjaCommand(name="test-stage%s-compiler"% stage_num,
212 targets=["check-all"],
213 haltOnFailure=True,
214 description=["test stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000215 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000216 env=env,
217 workdir=obj_dir,
218 ))
219
220 # Install just built compiler
221 f.addStep(NinjaCommand(name="install-stage%s-compiler"% stage_num,
222 targets=["install"],
223 haltOnFailure=True,
224 description=["install stage%s compiler" % stage_num],
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000225 timeout=10800, # LTO could take time.
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000226 env=env,
227 workdir=obj_dir,
228 ))
229
230
231def getClangWithLTOBuildFactory(
232 clean = False,
233 jobs = None,
234 extra_configure_args = None,
235 compare_last_2_stages = True,
236 env = None):
237
238 # Set defaults
239 if jobs is None:
240 jobs = "%(jobs)s"
241
242 if extra_configure_args is None:
243 extra_configure_args = []
244
245 # Make sure CMAKE_INSTALL_PREFIX and -G are not specified
246 # in the extra_configure_args. We set them internally as needed.
247 # TODO: assert extra_configure_args.
248 install_prefix_specified = any(a.startswith('-DCMAKE_INSTALL_PREFIX=') for a in extra_configure_args)
249 assert True, "Please do not explicitly specify the install prefix for multi-stage build."
250
251 # Prepare environmental variables. Set here all env we want everywhere.
252 merged_env = {
253 'TERM' : 'dumb' # Be cautious and disable color output from all tools.
254 }
255 if env is not None:
256 # Overwrite pre-set items with the given ones, so user can set anything.
257 merged_env.update(env)
258
259 f = LLVMBuildFactory(
260 depends_on_projects=['llvm', 'clang', 'lld'],
261 llvm_srcdir="llvm.src",
262 stage_objdirs=[
263 "build/stage1",
264 "build/stage2",
265 "build/stage3",
266 "build/stage4",
267 ],
268 stage_installdirs=[
269 "install/stage1",
270 "install/stage2",
271 "install/stage3",
272 "install/stage4",
273 ],
274 staged_compiler_idx = 1)
275
276 cleanBuildRequested = lambda step: step.build.getProperty("clean") or clean
277
278 # Do a clean checkout if requested.
279 f.addStep(RemoveDirectory(name='clean-src-dir',
280 dir=f.llvm_srcdir,
281 haltOnFailure=False,
282 flunkOnFailure=False,
283 doStepIf=cleanBuildRequested,
284 ))
285
286 # Get the source code.
287 f.addSVNSteps()
288
289 # Build with the system compiler first
290 _addSteps4SystemCompiler(f,
291 stage_idx=0,
292 clean=cleanBuildRequested,
293 jobs=jobs,
294 extra_configure_args=extra_configure_args,
295 env=merged_env)
296
297 # Then build the compiler we would use for the bootstrap.
298 _addSteps4StagedCompiler(f,
299 stage_idx=1,
300 withLTOSupport=True,
301 jobs=jobs,
302 extra_configure_args=extra_configure_args,
303 env=merged_env)
304
305 # Build all the remaining stages with exactly the same configuration.
306
307 # Set proper compile and link flags.
308 CmakeCommand.appendFlags(extra_configure_args, [
309 ('-DCMAKE_CXX_FLAGS=', ['-flto']),
310 ('-DCMAKE_EXE_LINKER_FLAGS=', ['-flto', '-fuse-ld=lld']),
311 ('-DCMAKE_MODULE_LINKER_FLAGS=', ['-flto', '-fuse-ld=lld']),
312 ('-DCMAKE_SHARED_LINKER_FLAGS=', ['-flto', '-fuse-ld=lld']),
313 ])
314
315 # The rest are test stages, which depend on the staged compiler we are ultimately after.
316 s = f.staged_compiler_idx + 1
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000317 staged_install = f.stage_installdirs[f.staged_compiler_idx]
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000318 for i in range(s, len(f.stage_objdirs[s:]) + s):
319 configure_args = extra_configure_args[:]
320
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000321 configure_args.append(
322 WithProperties(
323 "-DCMAKE_AR=%(workdir)s/" + staged_install + "/bin/llvm-ar"
324 ))
325 configure_args.append(
326 WithProperties(
327 "-DCMAKE_RANLIB=%(workdir)s/" + staged_install + "/bin/llvm-ranlib"
328 ))
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000329
330 _addSteps4StagedCompiler(f,
331 stage_idx=i,
332 use_stage_idx=f.staged_compiler_idx,
333 jobs=jobs,
334 extra_configure_args=configure_args,
335 env=merged_env)
336
337 if compare_last_2_stages:
338 # Compare the compilers built on the last 2 stages if requested.
339 diff_command = [
340 "diff",
341 "-q",
Galina Kistanovab3ff2752016-08-15 19:35:56 +0000342 f.stage_installdirs[-2] + "/bin/clang",
343 f.stage_installdirs[-1] + "/bin/clang",
Galina Kistanova1e2edfc2016-08-08 22:08:21 +0000344 ]
345 f.addStep(
346 ShellCommand(
347 name="compare-compilers",
348 description=[
349 "compare",
350 "stage%d" % (len(f.stage_installdirs)-1),
351 "and",
352 "stage%d" % len(f.stage_installdirs),
353 "compilers",
354 ],
355 haltOnFailure=True,
356 command=WithProperties(" ".join(diff_command)),
357 workdir=".",
358 env=merged_env
359 )
360 )
361
362 return f