aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiana Picus <diana.picus@linaro.org>2018-02-14 14:51:00 +0100
committerDiana Picus <diana.picus@linaro.org>2018-02-21 13:47:37 +0000
commit2c58083715559f6245a1a7406a3426d94110e28a (patch)
tree3f5d8fed65ce375a0c69dae39eda2c460d800c7d
parentfcfc628c2471e0908fa8e6d03c28092482dea519 (diff)
downloadlinaro-scripts-2c58083715559f6245a1a7406a3426d94110e28a.tar.gz
build-and-test: Make it possible to customize stage 1
Add support for custom subprojects, custom CMake definitions and custom build flags/targets for the first stage of the build. The subprojects are preserved for stage 2, but the other flags aren't. They will be configured separately. We're still hardcoding the CMake generator, but we can fix that later. This also extracts a couple of helpers for processing the command line arguments, which we can use both for this subcommand and for the others. Change-Id: Id6f8773b075815eb394eddff48adc9a7123f0da9
-rw-r--r--scripts/llvm.py73
-rw-r--r--tests/cli/testbuildandtest.py96
2 files changed, 163 insertions, 6 deletions
diff --git a/scripts/llvm.py b/scripts/llvm.py
index 6184bca..53ffd89 100644
--- a/scripts/llvm.py
+++ b/scripts/llvm.py
@@ -44,6 +44,18 @@ def dump_config(config):
print(" + {}".format(subproj))
+def subproj_to_repo_map(subprojs, proj, reposRoot, dry=False):
+ """Get a dictionary mapping each subproject in subprojs to its repo."""
+ subprojsToRepos = {}
+ repo = None
+ for subproj in subprojs:
+ if not dry:
+ repo = Clone(proj, os.path.join(reposRoot, subproj))
+ subprojsToRepos[subproj] = repo
+
+ return subprojsToRepos
+
+
def projects(args):
"""Add/remove subprojects based on the values in args."""
@@ -60,9 +72,7 @@ def projects(args):
to_add = {}
if args.add:
- for subproj in args.add:
- repo = Clone(proj, os.path.join(llvm_repos_root, subproj))
- to_add[subproj] = repo
+ to_add = subproj_to_repo_map(args.add, proj, llvm_repos_root)
try:
config.update(to_add, args.remove)
@@ -92,6 +102,14 @@ def push_current_branch(args):
die("Failed to push branch because: " + str(exc) + str(exc.__cause__))
+def cmake_flags_from_args(defs):
+ """
+ Get a list of valid CMake flags from the input VAR=VALUE list.
+ This boils down to just adding -D in front of each of them.
+ """
+ return ["-D{}".format(v) for v in defs]
+
+
def configure_build(args):
"""Configure a given build directory."""
@@ -110,7 +128,7 @@ def configure_build(args):
buildConfig = LLVMBuildConfig(sourceConfig, args.build, consumer)
if args.defs:
- args.defs = ["-D{}".format(v) for v in args.defs]
+ args.defs = cmake_flags_from_args(args.defs)
try:
buildConfig.cmake(args.defs, args.generator)
@@ -177,6 +195,10 @@ def build_and_test(args):
llvmWorktreeRoot = args.sources
stage1BuildDir = args.stage1
+ stage1Subprojs = args.stage1Subprojs
+ stage1Defs = cmake_flags_from_args(args.stage1Defs)
+ stage1BuildFlags = args.stage1BuildFlags
+
stage2BuildDir = args.stage2
enableTestSuite = args.enableTestSuite
@@ -189,13 +211,21 @@ def build_and_test(args):
try:
sourceConfig = LLVMSourceConfig(proj, llvmWorktreeRoot, args.dry)
+ if stage1Subprojs:
+ # FIXME: Decide whether or not we want to remove anything that isn't
+ # in stage1Subprojs (in case there are already some enabled
+ # subprojects in the source config).
+ sourceConfig.update(
+ subproj_to_repo_map(stage1Subprojs, proj, llvmRepos,
+ args.dry),
+ [])
if not dryRun and not os.path.exists(stage1BuildDir):
os.makedirs(stage1BuildDir)
buildConfig1 = LLVMBuildConfig(sourceConfig, stage1BuildDir, consumer)
- buildConfig1.cmake([], "Ninja")
- buildConfig1.build()
+ buildConfig1.cmake(stage1Defs, "Ninja")
+ buildConfig1.build(stage1BuildFlags)
testedBuildDir = stage1BuildDir
if stage2BuildDir is not None:
@@ -453,6 +483,37 @@ buildAndTest.add_argument(
required=True,
help="Path to the build directory for stage 1.")
buildAndTest.add_argument(
+ '--stage1-subproject',
+ dest='stage1Subprojs',
+ metavar='SUBPROJ',
+ choices=valid_subprojects,
+ default=[],
+ action='append',
+ help="Subprojects to enable for stage 1 of the build. Can be passed "
+ "multiple times. Valid values for the subproject are: {}. "
+ "If this is a 2-stage build, the same subprojects will be used for "
+ "both stages unless other subprojects are explicitly requested for "
+ "stage 2.".format(" ".join(valid_subprojects)))
+buildAndTest.add_argument(
+ '--stage1-cmake-def',
+ dest='stage1Defs',
+ metavar='VAR=VALUE',
+ default=[],
+ action='append',
+ help="Additional CMake definitions for stage 1, e.g. "
+ "CMAKE_BUILD_TYPE=Release. Can be passed multiple times. "
+ "The -D is added automatically. Does not affect stage 2.")
+buildAndTest.add_argument(
+ '--stage1-build-flag',
+ dest='stage1BuildFlags',
+ metavar='FLAG',
+ default=[],
+ action='append',
+ help="Additional flags for the stage 1 build command (e.g. targets to "
+ "build). Can be passed multiple times. If your flag starts with "
+ "a '-', use '--stage1-build-flag=-FLAG' to pass it. "
+ "Does not affect stage 2.")
+buildAndTest.add_argument(
'--stage2-build-dir',
dest='stage2',
help="Path to the build directory for stage 2.")
diff --git a/tests/cli/testbuildandtest.py b/tests/cli/testbuildandtest.py
index a60f7e2..1475958 100644
--- a/tests/cli/testbuildandtest.py
+++ b/tests/cli/testbuildandtest.py
@@ -39,6 +39,43 @@ class Testllvmbuildandtest(LLVMTestCase):
self.assertRegex(commands[1],
"{build}\$ ninja".format(build=buildDir))
+ def test_custom_stage1(self):
+ """Test that we can customize the first stage of the build."""
+ reposDir = "path-to-repos"
+ sourceDir = "path-to-sources"
+ buildDir = "path-to-stage1"
+
+ output = self.run_with_output(
+ self.llvm_build_and_test(
+ "--dry-run",
+ "--repos-dir", reposDir,
+ "--source-dir", sourceDir,
+ "--stage1-build-dir", buildDir,
+ "--stage1-subproject", "clang",
+ "--stage1-subproject", "compiler-rt",
+ "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
+ "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True",
+ "--stage1-build-flag=-j8",
+ "--stage1-build-flag", "check-all"))
+
+ commands = output.splitlines()
+
+ self.assertRegex(commands[0],
+ "{build}\$ cmake -G Ninja .* {sources}".format(
+ build=buildDir, sources=sourceDir))
+
+ self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
+ self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
+ self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
+ self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
+
+ self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
+ self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
+
+ self.assertRegex(commands[1],
+ "{build}\$ ninja -j8 check-all".format(build=buildDir))
+
+
def test_stage1_and_testsuite(self):
"""
Test that we dump the correct commands for a single stage build of LLVM
@@ -124,6 +161,65 @@ class Testllvmbuildandtest(LLVMTestCase):
commands[3],
"{stage2}\$ ninja".format(stage2=buildDir2))
+ def test_custom_stage1_default_stage2(self):
+ """
+ Test that we preserve the subprojects, but not the CMake or build flags.
+ """
+ reposDir = "path-to-repos"
+ sourceDir = "path-to-sources"
+ buildDir1 = "path-to-stage1"
+ buildDir2 = "path-to-stage2"
+
+ output = self.run_with_output(
+ self.llvm_build_and_test(
+ "--dry-run",
+ "--repos-dir", reposDir,
+ "--source-dir", sourceDir,
+ "--stage1-build-dir", buildDir1,
+ "--stage1-subproject", "clang",
+ "--stage1-subproject", "compiler-rt",
+ "--stage1-cmake-def", "CMAKE_CXX_FLAGS=-marm",
+ "--stage1-cmake-def", "LLVM_ENABLE_ASSERTIONS=True",
+ "--stage1-build-flag=-j8",
+ "--stage1-build-flag", "check-all",
+ "--stage2-build-dir", buildDir2))
+
+ commands = output.splitlines()
+
+ self.assertRegex(commands[0],
+ "{build}\$ cmake -G Ninja .* {sources}".format(
+ build=buildDir1, sources=sourceDir))
+
+ self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[0])
+ self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[0])
+ self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[0])
+ self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[0])
+
+ self.assertIn("-DCMAKE_CXX_FLAGS=-marm", commands[0])
+ self.assertIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[0])
+
+ self.assertRegex(commands[1],
+ "{build}\$ ninja -j8 check-all".format(build=buildDir1))
+
+ self.assertRegex(
+ commands[2], "{stage2}\$ cmake -G Ninja .* "
+ "-DCMAKE_C_COMPILER={stage1}/bin/clang "
+ "-DCMAKE_CXX_COMPILER={stage1}/bin/clang\+\+ {sources}".format(
+ stage1=buildDir1, stage2=buildDir2, sources=sourceDir))
+
+ self.assertIn("-DLLVM_TOOL_CLANG_BUILD=ON", commands[2])
+ self.assertIn("-DLLVM_TOOL_COMPILER_RT_BUILD=ON", commands[2])
+ self.assertIn("-DLLVM_TOOL_LIBCXX_BUILD=OFF", commands[2])
+ self.assertIn("-DLLVM_TOOL_LLDB_BUILD=OFF", commands[2])
+
+ self.assertNotIn("-DCMAKE_CXX_FLAGS=-marm", commands[2])
+ self.assertNotIn("-DLLVM_ENABLE_ASSERTIONS=True", commands[2])
+
+ self.assertRegex(
+ commands[3],
+ "{stage2}\$ ninja".format(stage2=buildDir2))
+
+
def test_stage2_and_testsuite(self):
"""
Test that we dump the correct commands for a 2-stage build of LLVM and a