blob: 70ba713c589f035171817612b121f94225e049fb [file] [log] [blame]
Diana Picus3b2ef822016-10-13 16:53:18 +03001"""This is the main tool for handling llvm builds, bisects etc."""
2
3import os
Diana Picusadb07c42017-11-22 16:12:57 +01004from sys import argv
Diana Picus3b2ef822016-10-13 16:53:18 +03005from sys import exit
6
Diana Picus052b7d32017-11-24 16:19:41 +01007from modules.llvm import LLVMBuildConfig
Diana Picus95226d42017-11-01 13:16:54 +01008from modules.llvm import LLVMSubproject
9from modules.llvm import LLVMSourceConfig
Diana Picusb368cb62018-01-23 16:41:59 +010010from modules.llvm import run_test_suite
Diana Picusf73abbf2018-01-26 07:06:20 +010011from modules.llvm import setup_test_suite
Diana Picus052b7d32017-11-24 16:19:41 +010012from modules.utils import CommandPrinter
13from modules.utils import CommandRunner
Diana Picus5ad55422017-12-14 17:57:10 +010014from modules.utils import get_remote_branch
15from modules.utils import push_branch
Diana Picus95226d42017-11-01 13:16:54 +010016
Diana Picus052b7d32017-11-24 16:19:41 +010017from linaropy.cd import cd
Diana Picus3b2ef822016-10-13 16:53:18 +030018from linaropy.git.clone import Clone
19from linaropy.proj import Proj
20
21from argparse import Action, ArgumentParser, RawTextHelpFormatter
Diana Picusefc7bda2017-06-09 19:14:08 +020022from functools import partial
Diana Picus3b2ef822016-10-13 16:53:18 +030023
24
25def die(message, config_to_dump=None):
26 """Print an error message and exit."""
Diana Picusb4307602017-04-05 19:48:39 +020027 print(message)
Diana Picus3b2ef822016-10-13 16:53:18 +030028
29 if config_to_dump is not None:
30 dump_config(config_to_dump)
31
32 exit(1)
33
Diana Picus3d1a3012017-03-14 17:38:32 +010034
Diana Picus3b2ef822016-10-13 16:53:18 +030035def dump_config(config):
36 """Dump the list of projects that are enabled in the given config."""
37
Diana Picusb4307602017-04-05 19:48:39 +020038 print("Projects linked:")
Diana Picus3b2ef822016-10-13 16:53:18 +030039 enabled = config.get_enabled_subprojects()
40 if not enabled:
Diana Picusb4307602017-04-05 19:48:39 +020041 print("none")
Diana Picus3b2ef822016-10-13 16:53:18 +030042 else:
43 for subproj in sorted(enabled):
Diana Picusb4307602017-04-05 19:48:39 +020044 print(" + {}".format(subproj))
Diana Picus3b2ef822016-10-13 16:53:18 +030045
46
Diana Picus2c580832018-02-14 14:51:00 +010047def subproj_to_repo_map(subprojs, proj, reposRoot, dry=False):
48 """Get a dictionary mapping each subproject in subprojs to its repo."""
49 subprojsToRepos = {}
50 repo = None
51 for subproj in subprojs:
52 if not dry:
53 repo = Clone(proj, os.path.join(reposRoot, subproj))
54 subprojsToRepos[subproj] = repo
55
56 return subprojsToRepos
57
58
Diana Picus3b2ef822016-10-13 16:53:18 +030059def projects(args):
60 """Add/remove subprojects based on the values in args."""
61
62 proj = Proj()
Diana Picus3d1a3012017-03-14 17:38:32 +010063
Diana Picus9f756862017-12-20 10:35:08 +010064 llvm_worktree_root = args.sources
Diana Picus81089db2017-05-05 22:26:49 +020065 llvm_repos_root = args.repos
Diana Picusb1dbcba2018-02-07 01:33:17 +010066 config = LLVMSourceConfig(proj, llvm_worktree_root, dry=False)
Diana Picus3b2ef822016-10-13 16:53:18 +030067
68 if not args.add and not args.remove:
69 # Nothing to change, just print the current configuration
70 dump_config(config)
71 exit(0)
72
73 to_add = {}
74 if args.add:
Diana Picus2c580832018-02-14 14:51:00 +010075 to_add = subproj_to_repo_map(args.add, proj, llvm_repos_root)
Diana Picus3b2ef822016-10-13 16:53:18 +030076
77 try:
78 config.update(to_add, args.remove)
79 except (EnvironmentError, ValueError) as exc:
80 die("Failed to update subprojects because:\n{}".format(str(exc)))
81
82 dump_config(config)
83
Diana Picusefc7bda2017-06-09 19:14:08 +020084
Diana Picus95226d42017-11-01 13:16:54 +010085def push_current_branch(args):
Diana Picusefc7bda2017-06-09 19:14:08 +020086 """Push current branch to origin."""
87
88 proj = Proj()
89
Diana Picus9f756862017-12-20 10:35:08 +010090 llvm_worktree_root = args.sources
Diana Picusb1dbcba2018-02-07 01:33:17 +010091 config = LLVMSourceConfig(proj, llvm_worktree_root, dry=False)
Diana Picusefc7bda2017-06-09 19:14:08 +020092
Diana Picus95226d42017-11-01 13:16:54 +010093 llvm_worktree = Clone(proj, llvm_worktree_root)
94 local_branch = llvm_worktree.getbranch()
Diana Picusefc7bda2017-06-09 19:14:08 +020095
96 try:
Diana Picus95226d42017-11-01 13:16:54 +010097 remote_branch = get_remote_branch(llvm_worktree, local_branch)
98 config.for_each_enabled(partial(push_branch, proj, local_branch,
99 remote_branch))
100 print("Pushed to {}".format(remote_branch))
101 except (EnvironmentError, RuntimeError) as exc:
Diana Picusefc7bda2017-06-09 19:14:08 +0200102 die("Failed to push branch because: " + str(exc) + str(exc.__cause__))
103
Diana Picus95226d42017-11-01 13:16:54 +0100104
Diana Picus2c580832018-02-14 14:51:00 +0100105def cmake_flags_from_args(defs):
106 """
107 Get a list of valid CMake flags from the input VAR=VALUE list.
108 This boils down to just adding -D in front of each of them.
109 """
110 return ["-D{}".format(v) for v in defs]
111
112
Diana Picus052b7d32017-11-24 16:19:41 +0100113def configure_build(args):
114 """Configure a given build directory."""
115
116 proj = Proj()
117
Diana Picus9f756862017-12-20 10:35:08 +0100118 llvm_worktree_root = args.sources
Diana Picusb1dbcba2018-02-07 01:33:17 +0100119 sourceConfig = LLVMSourceConfig(proj, llvm_worktree_root, args.dry)
Diana Picus052b7d32017-11-24 16:19:41 +0100120
Diana Picus052b7d32017-11-24 16:19:41 +0100121 if args.dry:
122 consumer = CommandPrinter()
123 else:
124 if not os.path.exists(args.build):
125 os.makedirs(args.build)
126 consumer = CommandRunner()
127
Diana Picus6b1935f2018-02-07 16:44:11 +0100128 buildConfig = LLVMBuildConfig(sourceConfig, args.build, consumer)
129
130 if args.defs:
Diana Picus2c580832018-02-14 14:51:00 +0100131 args.defs = cmake_flags_from_args(args.defs)
Diana Picus6b1935f2018-02-07 16:44:11 +0100132
Diana Picus052b7d32017-11-24 16:19:41 +0100133 try:
Diana Picus6b1935f2018-02-07 16:44:11 +0100134 buildConfig.cmake(args.defs, args.generator)
Diana Picus052b7d32017-11-24 16:19:41 +0100135 except RuntimeError as exc:
136 die("Failed to configure {} because:\n{}".format(args.build, str(exc)))
137
138
Diana Picus37126b82018-01-19 16:14:26 +0100139def run_build(args):
140 """Run a build command in a given directory."""
141 build_dir = args.build
142
143 if args.dry:
144 consumer = CommandPrinter()
145 else:
146 consumer = CommandRunner()
147
148 try:
Diana Picus6b1935f2018-02-07 16:44:11 +0100149 LLVMBuildConfig(None, args.build, consumer).build(args.flags)
Diana Picus37126b82018-01-19 16:14:26 +0100150 except RuntimeError as exc:
151 die("Failed to build {} because:\n{}".format(args.build, str(exc)))
152
153
Diana Picusf73abbf2018-01-26 07:06:20 +0100154def setup_the_test_suite(args):
155 """Setup a sandbox for the test-suite."""
156 if args.dry:
157 consumer = CommandPrinter()
158 else:
159 consumer = CommandRunner()
160
161 try:
162 setup_test_suite(consumer, args.sandbox, args.lnt)
163 except RuntimeError as exc:
164 die("Failed to setup the test-suite because:\n{}".format(str(exc)))
165
166
Diana Picusb368cb62018-01-23 16:41:59 +0100167def run_the_test_suite(args):
168 """Run the test-suite in a given sandbox."""
169 if args.dry:
170 consumer = CommandPrinter()
171 else:
172 consumer = CommandRunner()
173
174 compilers = ["--cc={}".format(args.cc)]
175 if args.cxx:
176 compilers.append("--cxx={}".format(args.cxx))
177
178 try:
179 run_test_suite(consumer, args.sandbox, args.testsuite, args.lit,
180 compilers + args.flags)
181 except RuntimeError as exc:
182 die("Failed to run the test-suite because:\n{}".format(str(exc)))
183
Diana Picusb03e5082018-02-05 12:36:49 +0100184
185def build_and_test(args):
186 """
187 Build a set of LLVM subprojects, in one or two stages, with or without a
188 test-suite run.
189 """
190
191 proj = Proj()
192
193 dryRun = args.dry
Diana Picusfcfc6282018-02-14 18:50:24 +0100194 llvmRepos = args.repos
Diana Picusb03e5082018-02-05 12:36:49 +0100195 llvmWorktreeRoot = args.sources
196
197 stage1BuildDir = args.stage1
Diana Picus2c580832018-02-14 14:51:00 +0100198 stage1Subprojs = args.stage1Subprojs
199 stage1Defs = cmake_flags_from_args(args.stage1Defs)
200 stage1BuildFlags = args.stage1BuildFlags
201
Diana Picusb03e5082018-02-05 12:36:49 +0100202 stage2BuildDir = args.stage2
Diana Picus6cdb5162018-02-15 05:29:46 +0100203 stage2Subprojs = args.stage2Subprojs
204 stage2Defs = cmake_flags_from_args(args.stage2Defs)
205 stage2BuildFlags = args.stage2BuildFlags
Diana Picusfcfc6282018-02-14 18:50:24 +0100206
207 enableTestSuite = args.enableTestSuite
Diana Picusb03e5082018-02-05 12:36:49 +0100208 sandboxDir = args.sandbox
Diana Picus49ee93a2018-02-15 05:52:34 +0100209 testSuiteFlags = args.testSuiteFlags
Diana Picusb03e5082018-02-05 12:36:49 +0100210
Diana Picusbb6a76e2018-02-23 13:18:37 +0100211 if not "clang" in stage1Subprojs:
212 if enableTestSuite:
213 die("Can't enable the test-suite if stage 1 doesn't build clang."
214 "Please add clang to the subprojects to be built for stage 1.")
215
216 if stage2BuildDir:
217 die("Can't enable stage 2 if stage 1 doesn't build clang."
218 "Please add clang to the subprojects to be built for stage 1.")
219
Diana Picusb03e5082018-02-05 12:36:49 +0100220 if dryRun:
221 consumer = CommandPrinter()
222 else:
223 consumer = CommandRunner()
224
225 try:
226 sourceConfig = LLVMSourceConfig(proj, llvmWorktreeRoot, args.dry)
Diana Picus2c580832018-02-14 14:51:00 +0100227 if stage1Subprojs:
228 # FIXME: Decide whether or not we want to remove anything that isn't
229 # in stage1Subprojs (in case there are already some enabled
230 # subprojects in the source config).
231 sourceConfig.update(
232 subproj_to_repo_map(stage1Subprojs, proj, llvmRepos,
233 args.dry),
234 [])
Diana Picusb03e5082018-02-05 12:36:49 +0100235
236 if not dryRun and not os.path.exists(stage1BuildDir):
237 os.makedirs(stage1BuildDir)
238
239 buildConfig1 = LLVMBuildConfig(sourceConfig, stage1BuildDir, consumer)
Diana Picus2c580832018-02-14 14:51:00 +0100240 buildConfig1.cmake(stage1Defs, "Ninja")
241 buildConfig1.build(stage1BuildFlags)
Diana Picusb03e5082018-02-05 12:36:49 +0100242 testedBuildDir = stage1BuildDir
243
244 if stage2BuildDir is not None:
Diana Picus6cdb5162018-02-15 05:29:46 +0100245 if stage2Subprojs:
246 toAdd = list(set(stage2Subprojs) - set(stage1Subprojs))
247 toRemove = list(set(stage1Subprojs) - set(stage2Subprojs))
248 sourceConfig.update(
249 subproj_to_repo_map(toAdd, proj, llvmRepos, args.dry),
250 toRemove)
251
Diana Picusb03e5082018-02-05 12:36:49 +0100252 if not dryRun and not os.path.exists(stage2BuildDir):
253 os.makedirs(stage2BuildDir)
254
255 buildConfig2 = LLVMBuildConfig(sourceConfig, stage2BuildDir,
256 consumer)
257
Diana Picusb03e5082018-02-05 12:36:49 +0100258 buildConfig2.cmake(
Diana Picus6cdb5162018-02-15 05:29:46 +0100259 stage2Defs + [
Diana Picusb03e5082018-02-05 12:36:49 +0100260 "-DCMAKE_C_COMPILER={}/bin/clang".format(stage1BuildDir),
261 "-DCMAKE_CXX_COMPILER={}/bin/clang++".format(stage1BuildDir)],
262 "Ninja")
Diana Picus6cdb5162018-02-15 05:29:46 +0100263 buildConfig2.build(stage2BuildFlags)
Diana Picusb03e5082018-02-05 12:36:49 +0100264 testedBuildDir = stage2BuildDir
265
Diana Picusfcfc6282018-02-14 18:50:24 +0100266 if enableTestSuite:
267 testSuiteDir = os.path.join(llvmRepos, "test-suite")
268 lntDir = os.path.join(llvmRepos, "lnt")
269
Diana Picusb03e5082018-02-05 12:36:49 +0100270 setup_test_suite(consumer, sandboxDir, lntDir)
271
Diana Picusb03e5082018-02-05 12:36:49 +0100272 lit = os.path.join(testedBuildDir, "bin", "llvm-lit")
273 clang = os.path.join(testedBuildDir, "bin", "clang")
274 run_test_suite(consumer, sandboxDir, testSuiteDir, lit,
Diana Picus49ee93a2018-02-15 05:52:34 +0100275 ["--cc={}".format(clang)] + testSuiteFlags)
Diana Picusb03e5082018-02-05 12:36:49 +0100276
277 except RuntimeError as exc:
278 die("Failed because:\n{}".format(str(exc)))
279
280
Diana Picus3b2ef822016-10-13 16:53:18 +0300281##########################################################################
282# Command line parsing #
283##########################################################################
284
285# If we decide we want shorthands for the subprojects, we can append to this
286# list
Diana Picusb4307602017-04-05 19:48:39 +0200287valid_subprojects = list(LLVMSubproject.get_all_subprojects().keys())
Diana Picus3b2ef822016-10-13 16:53:18 +0300288
289options = ArgumentParser(formatter_class=RawTextHelpFormatter)
Diana Picusadb07c42017-11-22 16:12:57 +0100290subcommands = options.add_subparsers(dest="subcommand")
Diana Picus3b2ef822016-10-13 16:53:18 +0300291
292# Subcommand for adding / removing subprojects
Diana Picus36317e82017-10-31 15:35:24 +0100293projs = subcommands.add_parser(
294 "projects", help="Add/remove LLVM subprojects.\n"
295 "Adding a subproject will create a worktree for it "
296 "somewhere in the LLVM source tree, on the same git "
297 "branch as LLVM itself.\n"
298 "Removing a subproject will remove the worktree, but "
299 "not the underlying git branch.")
Diana Picus3b2ef822016-10-13 16:53:18 +0300300projs.set_defaults(run_command=projects)
301
302# TODO: Overwriting previous values is not necessarily what users expect (so for
303# instance --add S1 S2 --remove S3 --add S4 would lead to adding only S4). We
304# can do better by using action='append', which would create a list (of lists?
305# or of lists and scalars?) that we can flatten to obtain all the values passed
306# by the user.
307projs.add_argument(
308 '-a', '--add',
309 nargs='+',
310 choices=valid_subprojects,
311 metavar='subproject',
Diana Picus36317e82017-10-31 15:35:24 +0100312 help="Enable given subprojects. Valid values are:\n\t{}\n".format(
Diana Picus3b2ef822016-10-13 16:53:18 +0300313 "\n\t".join(valid_subprojects)))
314projs.add_argument(
315 '-r', '--remove',
316 nargs='+',
317 choices=valid_subprojects,
318 metavar='subproject',
Diana Picus36317e82017-10-31 15:35:24 +0100319 help="Disable given subprojects.")
Diana Picusadb07c42017-11-22 16:12:57 +0100320projs.add_argument(
321 '--repos',
322 help="Path to the directory containing the repositories for all LLVM "
323 "subprojects.")
Diana Picus9f756862017-12-20 10:35:08 +0100324projs.add_argument(
325 '--source-dir',
326 dest='sources',
327 required=True,
328 help="Path to the directory containing the LLVM worktree that we're adding "
329 "or removing subprojects from.")
Diana Picus3b2ef822016-10-13 16:53:18 +0300330
Diana Picusefc7bda2017-06-09 19:14:08 +0200331# Subcommand for pushing the current branch to origin
332push = subcommands.add_parser(
333 "push",
Diana Picus36317e82017-10-31 15:35:24 +0100334 help="Push current branch to origin linaro-local/<user>/<branch>, "
335 "for all enabled subprojects.")
Diana Picus95226d42017-11-01 13:16:54 +0100336push.set_defaults(run_command=push_current_branch)
Diana Picus9f756862017-12-20 10:35:08 +0100337push.add_argument(
338 '--source-dir',
339 dest='sources',
340 required=True,
341 help="Path to the directory containing the LLVM worktree.")
Diana Picusefc7bda2017-06-09 19:14:08 +0200342
Diana Picus052b7d32017-11-24 16:19:41 +0100343# Subcommand for configuring a build directory
344configure = subcommands.add_parser(
345 'configure',
346 help="Run CMake in the given build directory.")
347configure.add_argument(
Diana Picus9f756862017-12-20 10:35:08 +0100348 '--source-dir',
349 dest='sources',
350 required=True,
351 help="Path to the sources directory. It should contain an LLVM worktree.")
352configure.add_argument(
Diana Picus052b7d32017-11-24 16:19:41 +0100353 '--build-dir',
354 dest='build',
355 required=True,
356 help="Path to the build directory. It will be created if it does not exist")
357configure.add_argument(
358 '--cmake-generator',
359 dest='generator',
360 default='Ninja',
361 help="CMake generator to use (default is Ninja).")
362configure.add_argument(
363 '--cmake-def',
364 dest='defs',
365 metavar='VAR=VALUE',
366 default=[],
367 action='append',
368 # We add the -D in front of the variable ourselves because the argument
369 # parsing gets confused otherwise (and quoting doesn't help).
370 help="Additional CMake definitions, e.g. CMAKE_BUILD_TYPE=Release."
371 "May be passed several times. The -D is added automatically.")
372configure.add_argument(
373 '-n', '--dry-run',
374 dest='dry',
375 action='store_true',
376 default=False,
377 help="Print the CMake command instead of executing it.")
378configure.set_defaults(run_command=configure_build)
379
Diana Picus37126b82018-01-19 16:14:26 +0100380# Subcommand for building a target
381build = subcommands.add_parser(
382 'build',
383 help="Run a build command in the given directory."
384 "The build command can be either a 'ninja' or a 'make' command, depending "
385 "on what the build directory contains. First, we look for a 'build.ninja' "
386 "file. If that is not found, we look for a 'Makefile'. If that is not "
387 "found either, the script fails.")
388build.add_argument(
389 '--build-dir',
390 dest='build',
391 required=True,
392 help="Path to the build directory. It must have already been configured.")
393build.add_argument(
394 '-n', '--dry-run',
395 dest='dry',
396 action='store_true',
397 default=False,
398 help="Print the build command instead of executing it.")
399build.add_argument(
400 '--build-flag',
401 dest='flags',
402 metavar='FLAG',
403 default=[],
404 action='append',
405 help="Additional flags for the build command (e.g. targets to build). "
406 "May be passed several times. If your flag starts with a '-', use "
407 "'--build-flag=-FLAG' to pass it.")
408build.set_defaults(run_command=run_build)
409
Diana Picusf73abbf2018-01-26 07:06:20 +0100410# Subcommand for setting up the test-suite
411setupTestSuite = subcommands.add_parser(
412 'setup-test-suite',
413 help="Prepare a sandbox for running the test-suite.")
414setupTestSuite.add_argument(
415 '--sandbox',
416 required=True,
417 help="Path where we should setup the sandbox.")
418setupTestSuite.add_argument(
419 '--lnt',
420 required=True,
421 help="Path to the LNT sources.")
422setupTestSuite.add_argument(
423 '-n', '--dry-run',
424 dest='dry',
425 action='store_true',
426 default=False,
427 help="Print the commands instead of executing them.")
428setupTestSuite.set_defaults(run_command=setup_the_test_suite)
429
Diana Picusb368cb62018-01-23 16:41:59 +0100430# Subcommand for running the test-suite
431runTestSuite = subcommands.add_parser(
432 'run-test-suite',
433 help="Run the test-suite in the given sandbox.")
434runTestSuite.add_argument(
435 '--sandbox',
436 required=True,
437 help="Path to the sandbox. It must point to a virtualenv with a LNT setup.")
438runTestSuite.add_argument(
439 '--test-suite',
440 dest="testsuite",
441 required=True,
442 help="Path to the test-suite repo.")
443runTestSuite.add_argument(
444 '--use-lit',
445 dest="lit",
446 required=True,
447 help="Path to llvm-lit.")
448runTestSuite.add_argument(
449 '--lnt-flag',
450 dest='flags',
451 metavar='FLAG',
452 default=[],
453 action='append',
454 help="Additional flags to be passed to LNT when running the test-suite."
455 "May be passed several times. If your flag starts with a '-', use "
456 "'--lnt-flag=-FLAG' to pass it.")
457runTestSuite.add_argument(
458 # We can pass --cc through the --lnt-flag interface, but we generally won't
459 # want to test the system compiler, so force the user to be specific.
460 '--cc',
461 required=True,
462 help="The path to the C compiler that we're testing.")
463runTestSuite.add_argument(
464 # For symmetry, we also provide a --cxx argument, but this one isn't
465 # required since LNT tries to guess it based on the value of --cc.
466 '--cxx',
467 required=False,
468 help="The path to the C++ compiler that we're testing.")
469runTestSuite.add_argument(
470 '-n', '--dry-run',
471 dest='dry',
472 action='store_true',
473 default=False,
474 help="Print the commands instead of executing them.")
475runTestSuite.set_defaults(run_command=run_the_test_suite)
476
Diana Picusb03e5082018-02-05 12:36:49 +0100477buildAndTest = subcommands.add_parser(
478 'build-and-test', # TODO: This really needs a better name...
Diana Picusfec612c2018-02-19 19:14:00 +0100479 fromfile_prefix_chars='@',
Diana Picusb03e5082018-02-05 12:36:49 +0100480 help="Run complex build scenarios with one or two stages of clang and "
481 "optionally a test-suite run. This should be flexible enough to allow "
482 "us to reproduce any buildbot configuration, but it can obviously be "
483 "used for other purposes as well.")
484buildAndTest.set_defaults(run_command=build_and_test)
485buildAndTest.add_argument(
Diana Picusfcfc6282018-02-14 18:50:24 +0100486 '--repos-dir',
487 dest='repos',
488 required=True,
489 help="Path to the root directory containing the repositories for LLVM and "
490 "the other subprojects.")
491buildAndTest.add_argument(
Diana Picusb03e5082018-02-05 12:36:49 +0100492 '--source-dir',
493 dest='sources',
494 required=True,
495 help="Path to the directory containing the LLVM worktree that we're going "
496 "to build from.")
497buildAndTest.add_argument(
498 '--stage1-build-dir',
499 dest='stage1',
500 required=True,
501 help="Path to the build directory for stage 1.")
502buildAndTest.add_argument(
Diana Picus2c580832018-02-14 14:51:00 +0100503 '--stage1-subproject',
504 dest='stage1Subprojs',
505 metavar='SUBPROJ',
506 choices=valid_subprojects,
507 default=[],
508 action='append',
509 help="Subprojects to enable for stage 1 of the build. Can be passed "
510 "multiple times. Valid values for the subproject are: {}. "
511 "If this is a 2-stage build, the same subprojects will be used for "
512 "both stages unless other subprojects are explicitly requested for "
513 "stage 2.".format(" ".join(valid_subprojects)))
514buildAndTest.add_argument(
515 '--stage1-cmake-def',
516 dest='stage1Defs',
517 metavar='VAR=VALUE',
518 default=[],
519 action='append',
520 help="Additional CMake definitions for stage 1, e.g. "
521 "CMAKE_BUILD_TYPE=Release. Can be passed multiple times. "
522 "The -D is added automatically. Does not affect stage 2.")
523buildAndTest.add_argument(
524 '--stage1-build-flag',
525 dest='stage1BuildFlags',
526 metavar='FLAG',
527 default=[],
528 action='append',
529 help="Additional flags for the stage 1 build command (e.g. targets to "
530 "build). Can be passed multiple times. If your flag starts with "
531 "a '-', use '--stage1-build-flag=-FLAG' to pass it. "
532 "Does not affect stage 2.")
533buildAndTest.add_argument(
Diana Picusb03e5082018-02-05 12:36:49 +0100534 '--stage2-build-dir',
535 dest='stage2',
536 help="Path to the build directory for stage 2.")
537buildAndTest.add_argument(
Diana Picus6cdb5162018-02-15 05:29:46 +0100538 '--stage2-subproject',
539 dest='stage2Subprojs',
540 metavar='SUBPROJ',
541 choices=valid_subprojects,
542 default=[],
543 action='append',
544 help="Subprojects to enable for stage 2 of the build. Can be passed "
545 "multiple times. Valid values for the subproject are: {}. "
546 "If this is a 2-stage build, the same subprojects will be used for "
547 "both stages unless other subprojects are explicitly requested for "
548 "stage 2.".format(" ".join(valid_subprojects)))
549buildAndTest.add_argument(
550 '--stage2-cmake-def',
551 dest='stage2Defs',
552 metavar='VAR=VALUE',
553 default=[],
554 action='append',
555 help="Additional CMake definitions for stage 2, e.g. "
556 "CMAKE_BUILD_TYPE=Release. Can be passed multiple times. "
557 "The -D is added automatically.")
558buildAndTest.add_argument(
559 '--stage2-build-flag',
560 dest='stage2BuildFlags',
561 metavar='FLAG',
562 default=[],
563 action='append',
564 help="Additional flags for the stage 2 build command (e.g. targets to "
565 "build). Can be passed multiple times. If your flag starts with "
566 "a '-', use '--stage2-build-flag=-FLAG' to pass it.")
567buildAndTest.add_argument(
Diana Picusfcfc6282018-02-14 18:50:24 +0100568 "--enable-test-suite",
569 dest='enableTestSuite',
570 action='store_true',
571 default=False,
572 help="Whether or not to run the test-suite with the last compiler built.")
Diana Picusb03e5082018-02-05 12:36:49 +0100573buildAndTest.add_argument(
574 "--sandbox",
575 help="Path to the sandbox where the test-suite should be setup.")
576buildAndTest.add_argument(
Diana Picus49ee93a2018-02-15 05:52:34 +0100577 '--lnt-flag',
578 dest='testSuiteFlags',
579 metavar='FLAG',
580 default=[],
581 action='append',
582 help="Additional flags to be passed to LNT when running the test-suite."
583 "May be passed several times. If your flag starts with a '-', use "
584 "'--lnt-flag=-FLAG' to pass it.")
585buildAndTest.add_argument(
Diana Picusb03e5082018-02-05 12:36:49 +0100586 '-n', '--dry-run',
587 dest='dry',
588 action='store_true',
589 default=False,
590 help="Print the commands instead of executing them.")
591
Diana Picus3b2ef822016-10-13 16:53:18 +0300592args = options.parse_args()
Diana Picusadb07c42017-11-22 16:12:57 +0100593if args.subcommand == "projects" and args.add and not args.repos:
594 projs.error(
595 "When adding a subproject you must also pass the --repos argument")
Diana Picus3b2ef822016-10-13 16:53:18 +0300596args.run_command(args)