[LNT] r297125 - Add cross-compilation support to 'lnt runtest test-suite'
Kristof Beyls via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 7 00:04:33 PST 2017
Author: kbeyls
Date: Tue Mar 7 02:04:33 2017
New Revision: 297125
URL: http://llvm.org/viewvc/llvm-project?rev=297125&view=rev
Log:
Add cross-compilation support to 'lnt runtest test-suite'
This adds cross-compilation support for the cmake+lit-based way to build
and run the test-suite, by letting users specify a cmake toolchain file
if they want to cross-compile.
The main functional changes are:
* Making sure the correct target is picked up for the report.json.
* --cc is no longer a required command line option.
* Documentation is written to explain how to best perform
test-suite runs in a cross-compile set up.
Differential Revision: https://reviews.llvm.org/D29030
Modified:
lnt/trunk/docs/tests.rst
lnt/trunk/lnt/tests/test_suite.py
lnt/trunk/tests/SharedInputs/FakeCompilers/fakecompiler.py
lnt/trunk/tests/runtest/Inputs/test-suite-cmake/fake-cmake
lnt/trunk/tests/runtest/test_suite.py
Modified: lnt/trunk/docs/tests.rst
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/docs/tests.rst?rev=297125&r1=297124&r2=297125&view=diff
==============================================================================
--- lnt/trunk/docs/tests.rst (original)
+++ lnt/trunk/docs/tests.rst Tue Mar 7 02:04:33 2017
@@ -305,3 +305,49 @@ for figuring out what is going on with a
This will run the test-suite many times over, collecting useful information
in a report directory. The report collects many things like execution profiles,
compiler time reports, intermediate files, binary files, and build information.
+
+
+Cross-compiling
++++++++++++++++
+
+The best way to run the test-suite in a cross-compiling setup with the
+cmake driver is to use cmake's built-in support for cross-compiling as much as
+possible. In practice, the recommended way to cross-compile is to use a cmake
+toolchain file (see
+https://cmake.org/cmake/help/v3.0/manual/cmake-toolchains.7.html#cross-compiling)
+
+An example command line for cross-compiling on an X86 machine, targeting
+AArch64 linux, is::
+
+ $ lnt runtest test-suite \
+ --sandbox SANDBOX \
+ --test-suite /work/llvm-test-suite \
+ --use-lit lit \
+ --cppflags="-O3" \
+ --run-under=$HOME/dev/aarch64-emu/aarch64-qemu.sh \
+ --cmake-define=CMAKE_TOOLCHAIN_FILE:FILEPATH=$HOME/clang_aarch64_linux.cmake
+
+The key part here is the CMAKE_TOOLCHAIN_FILE define. As you're
+cross-compiling, you may need a --run-under command as the produced binaries
+probably won't run natively on your development machine, but something extra
+needs to be done (e.g. running under a qemu simulator, or transferring the
+binaries to a development board). This isn't explained further here.
+
+In your toolchain file, it's important to specify that the cmake variables
+defining the toolchain must be cached in CMakeCache.txt, as that's where lnt
+reads them from to figure out which compiler was used when needing to construct
+metadata for the json report. An example is below. The important keywords to
+make the variables appear in the CMakeCache.txt are "CACHE STRING "" FORCE"::
+
+ $ cat clang_aarch64_linux.cmake
+ set(CMAKE_SYSTEM_NAME Linux )
+ set(triple aarch64-linux-gnu )
+ set(CMAKE_C_COMPILER /home/user/build/bin/clang CACHE STRING "" FORCE)
+ set(CMAKE_C_COMPILER_TARGET ${triple} CACHE STRING "" FORCE)
+ set(CMAKE_CXX_COMPILER /home/user/build/bin/clang++ CACHE STRING "" FORCE)
+ set(CMAKE_CXX_COMPILER_TARGET ${triple} CACHE STRING "" FORCE)
+ set(CMAKE_SYSROOT /home/user/aarch64-emu/sysroot-glibc-linaro-2.23-2016.11-aarch64-linux-gnu )
+ set(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN /home/user/aarch64-emu/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu )
+ set(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN /home/user/aarch64-emu/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu )
+
+
Modified: lnt/trunk/lnt/tests/test_suite.py
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/tests/test_suite.py?rev=297125&r1=297124&r2=297125&view=diff
==============================================================================
--- lnt/trunk/lnt/tests/test_suite.py (original)
+++ lnt/trunk/lnt/tests/test_suite.py Tue Mar 7 02:04:33 2017
@@ -220,19 +220,6 @@ class TestSuiteTest(BuiltinTest):
type=str, default=None,
help="Path to the C++ compiler to test (inferred from"
" --cc where possible")
- group.add_option("", "--llvm-arch", dest="llvm_arch",
- type='choice', default=None,
- help="Override the CMake-inferred architecture",
- choices=TEST_SUITE_KNOWN_ARCHITECTURES)
- group.add_option("", "--cross-compiling", dest="cross_compiling",
- action="store_true", default=False,
- help="Inform CMake that it should be cross-compiling")
- group.add_option("", "--cross-compiling-system-name", type=str,
- default=None, dest="cross_compiling_system_name",
- help="The parameter to pass to CMAKE_SYSTEM_NAME when"
- " cross-compiling. By default this is 'Linux' "
- "unless -arch is in the cflags, in which case "
- "it is 'Darwin'")
group.add_option("", "--cppflags", type=str, action="append",
dest="cppflags", default=[],
help="Extra flags to pass the compiler in C or C++ mode. "
@@ -359,34 +346,30 @@ class TestSuiteTest(BuiltinTest):
else:
parser.error("Expected no positional arguments (got: %r)" % (args,))
- for a in ['cross_compiling', 'cross_compiling_system_name', 'llvm_arch']:
- if getattr(opts, a):
- parser.error('option "%s" is not yet implemented!' % a)
-
if self.opts.sandbox_path is None:
parser.error('--sandbox is required')
- if self.opts.cc is None:
- parser.error('--cc is required')
-
- # Option validation.
- opts.cc = resolve_command_path(opts.cc)
+ if self.opts.cc is not None:
+ self.opts.cc = resolve_command_path(self.opts.cc)
- if not lnt.testing.util.compilers.is_valid(opts.cc):
- parser.error('--cc does not point to a valid executable.')
+ if not lnt.testing.util.compilers.is_valid(self.opts.cc):
+ parser.error('--cc does not point to a valid executable.')
- # If there was no --cxx given, attempt to infer it from the --cc.
- if opts.cxx is None:
- opts.cxx = lnt.testing.util.compilers.infer_cxx_compiler(opts.cc)
- if opts.cxx is not None:
- note("Inferred C++ compiler under test as: %r" % (opts.cxx,))
+ # If there was no --cxx given, attempt to infer it from the --cc.
+ if self.opts.cxx is None:
+ self.opts.cxx = \
+ lnt.testing.util.compilers.infer_cxx_compiler(self.opts.cc)
+ if self.opts.cxx is not None:
+ note("Inferred C++ compiler under test as: %r"
+ % (self.opts.cxx,))
+ else:
+ parser.error("unable to infer --cxx - set it manually.")
else:
- parser.error("unable to infer --cxx - set it manually.")
- else:
- opts.cxx = resolve_command_path(opts.cxx)
+ self.opts.cxx = resolve_command_path(self.opts.cxx)
- if not os.path.exists(opts.cxx):
- parser.error("invalid --cxx argument %r, does not exist" % (opts.cxx))
+ if not os.path.exists(self.opts.cxx):
+ parser.error("invalid --cxx argument %r, does not exist"
+ % (self.opts.cxx))
if opts.test_suite_root is None:
parser.error('--test-suite is required')
@@ -471,6 +454,14 @@ class TestSuiteTest(BuiltinTest):
# output.
self._configure_if_needed()
+ # Verify that we can actually find a compiler before continuing
+ cmake_vars = self._extract_cmake_vars_from_cache()
+ if "CMAKE_C_COMPILER" not in cmake_vars or \
+ not os.path.exists(cmake_vars["CMAKE_C_COMPILER"]):
+ parser.error(
+ "Couldn't find C compiler (%s). Maybe you should specify --cc?"
+ % cmake_vars.get("CMAKE_C_COMPILER"))
+
# We don't support compiling without testing as we can't get compile-
# time numbers from LIT without running the tests.
if opts.compile_multisample > opts.exec_multisample:
@@ -480,7 +471,7 @@ class TestSuiteTest(BuiltinTest):
if opts.auto_name:
# Construct the nickname from a few key parameters.
- cc_info = self._get_cc_info()
+ cc_info = self._get_cc_info(cmake_vars)
cc_nick = '%s_%s' % (cc_info['cc_name'], cc_info['cc_build'])
self.nick += "__%s__%s" % (cc_nick,
cc_info['cc_target'].split('-')[0])
@@ -490,7 +481,7 @@ class TestSuiteTest(BuiltinTest):
# is a horrible failure mode because all of our data ends up going
# to order 0. The user needs to give an order if we can't detect!
if opts.run_order is None:
- cc_info = self._get_cc_info()
+ cc_info = self._get_cc_info(cmake_vars)
if cc_info['inferred_run_order'] == 0:
fatal("Cannot detect compiler version. Specify --run-order"
" to manually define it.")
@@ -501,7 +492,7 @@ class TestSuiteTest(BuiltinTest):
for i in range(max(opts.exec_multisample, opts.compile_multisample)):
c = i < opts.compile_multisample
e = i < opts.exec_multisample
- run_report, json_data = self.run(compile=c, test=e)
+ run_report, json_data = self.run(cmake_vars, compile=c, test=e)
reports.append(run_report)
json_reports.append(json_data)
@@ -534,7 +525,7 @@ class TestSuiteTest(BuiltinTest):
self._clean(self._base_path)
self.configured = True
- def run(self, compile=True, test=True):
+ def run(self, cmake_vars, compile=True, test=True):
mkdir_p(self._base_path)
if self.opts.pgo:
@@ -551,7 +542,7 @@ class TestSuiteTest(BuiltinTest):
self.compiled = True
data = self._lit(self._base_path, test)
- return self._parse_lit_output(self._base_path, data), data
+ return self._parse_lit_output(self._base_path, data, cmake_vars), data
def _create_merged_report(self, reports):
if len(reports) == 1:
@@ -600,11 +591,12 @@ class TestSuiteTest(BuiltinTest):
def _configure(self, path, extra_cmake_defs=[], execute=True):
cmake_cmd = self.opts.cmake
- defs = {
- # FIXME: Support ARCH, SMALL/LARGE etc
- 'CMAKE_C_COMPILER': self.opts.cc,
- 'CMAKE_CXX_COMPILER': self.opts.cxx,
- }
+ defs = {}
+ if self.opts.cc:
+ defs['CMAKE_C_COMPILER'] = self.opts.cc
+ if self.opts.cxx:
+ defs['CMAKE_CXX_COMPILER'] = self.opts.cxx,
+
if self.opts.cppflags or self.opts.cflags:
all_cflags = ' '.join([self.opts.cppflags, self.opts.cflags])
defs['CMAKE_C_FLAGS'] = self._unix_quote_args(all_cflags)
@@ -759,44 +751,55 @@ class TestSuiteTest(BuiltinTest):
name = raw_name.rsplit('.test', 1)[0]
return not os.path.exists(os.path.join(path, name))
- def _get_target_flags(self, cmake_vars):
- build_type = cmake_vars["build_type"]
- cflags = cmake_vars["c_flags"]
- if build_type != "":
- cflags = \
- " ".join(cflags.split(" ") +
- cmake_vars["c_flags_"+build_type.lower()].split(" "))
- return shlex.split(cflags)
-
- def _get_cc_info(self):
+ def _extract_cmake_vars_from_cache(self):
assert self.configured is True
cmake_lah_output = self._check_output(
[self.opts.cmake] + ['-LAH', '-N'] + [self._base_path])
pattern2var = [
- (re.compile("^%s:[^=]*=(.*)$" % cmakevar), var)
- for cmakevar, var in (
- ("CMAKE_C_COMPILER", "cc"),
- ("CMAKE_BUILD_TYPE", "build_type"),
- ("CMAKE_CXX_FLAGS", "cxx_flags"),
- ("CMAKE_CXX_FLAGS_DEBUG", "cxx_flags_debug"),
- ("CMAKE_CXX_FLAGS_MINSIZEREL", "cxx_flags_minsizerel"),
- ("CMAKE_CXX_FLAGS_RELEASE", "cxx_flags_release"),
- ("CMAKE_CXX_FLAGS_RELWITHDEBINFO", "cxx_flags_relwithdebinfo"),
- ("CMAKE_C_FLAGS", "c_flags"),
- ("CMAKE_C_FLAGS_DEBUG", "c_flags_debug"),
- ("CMAKE_C_FLAGS_MINSIZEREL", "c_flags_minsizerel"),
- ("CMAKE_C_FLAGS_RELEASE", "c_flags_release"),
- ("CMAKE_C_FLAGS_RELWITHDEBINFO", "c_flags_relwithdebinfo"),)]
+ (re.compile("^%s:[^=]*=(.*)$" % cmakevar), cmakevar)
+ for cmakevar in (
+ "CMAKE_C_COMPILER",
+ "CMAKE_BUILD_TYPE",
+ "CMAKE_CXX_FLAGS",
+ "CMAKE_CXX_FLAGS_DEBUG",
+ "CMAKE_CXX_FLAGS_MINSIZEREL",
+ "CMAKE_CXX_FLAGS_RELEASE",
+ "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
+ "CMAKE_C_FLAGS",
+ "CMAKE_C_FLAGS_DEBUG",
+ "CMAKE_C_FLAGS_MINSIZEREL",
+ "CMAKE_C_FLAGS_RELEASE",
+ "CMAKE_C_FLAGS_RELWITHDEBINFO",
+ "CMAKE_C_COMPILER_TARGET",
+ "CMAKE_CXX_COMPILER_TARGET",
+ )]
cmake_vars = {}
for line in cmake_lah_output.split("\n"):
for pattern, varname in pattern2var:
m = re.match(pattern, line)
if m:
cmake_vars[varname] = m.group(1)
+ return cmake_vars
+
+ def _get_cc_info(self, cmake_vars):
+ build_type = cmake_vars["CMAKE_BUILD_TYPE"]
+ cflags = cmake_vars["CMAKE_C_FLAGS"]
+ if build_type != "":
+ cflags = \
+ " ".join(cflags.split(" ") +
+ cmake_vars["CMAKE_C_FLAGS_" + build_type.upper()]
+ .split(" "))
+ # FIXME: this probably needs to be conditionalized on the compiler
+ # being clang. Or maybe we need an
+ # lnt.testing.util.compilers.get_cc_info uses cmake somehow?
+ if "CMAKE_C_COMPILER_TARGET" in cmake_vars:
+ cflags += " --target=" + cmake_vars["CMAKE_C_COMPILER_TARGET"]
+ target_flags = shlex.split(cflags)
+
return lnt.testing.util.compilers.get_cc_info(
- cmake_vars["cc"], self._get_target_flags(cmake_vars))
+ cmake_vars["CMAKE_C_COMPILER"], target_flags)
- def _parse_lit_output(self, path, data, only_test=False):
+ def _parse_lit_output(self, path, data, cmake_vars, only_test=False):
LIT_METRIC_TO_LNT = {
'compile_time': 'compile',
'exec_time': 'exec',
@@ -901,7 +904,7 @@ class TestSuiteTest(BuiltinTest):
run_info = {
'tag': 'nts'
}
- run_info.update(self._get_cc_info())
+ run_info.update(self._get_cc_info(cmake_vars))
run_info['run_order'] = run_info['inferred_run_order']
if self.opts.run_order:
run_info['run_order'] = self.opts.run_order
Modified: lnt/trunk/tests/SharedInputs/FakeCompilers/fakecompiler.py
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/tests/SharedInputs/FakeCompilers/fakecompiler.py?rev=297125&r1=297124&r2=297125&view=diff
==============================================================================
--- lnt/trunk/tests/SharedInputs/FakeCompilers/fakecompiler.py (original)
+++ lnt/trunk/tests/SharedInputs/FakeCompilers/fakecompiler.py Tue Mar 7 02:04:33 2017
@@ -21,7 +21,7 @@ class FakeCompiler(object):
def print_dumpmachine(self):
raise NotImplementedError
- def print_llvm_target(self):
+ def print_llvm_target(self, args):
raise NotImplementedError
def print_as_version(self):
@@ -40,7 +40,7 @@ icc version 12.1.3 (gcc version 4.2.1 co
... more boring stuff here ...
"""
- def print_llvm_target(self):
+ def print_llvm_target(self, args):
print """\
icc: command line warning #10006: ignoring unknown option '-flto'
.file "null"
@@ -53,14 +53,18 @@ icc: command line warning #10006: ignori
print """i686-apple-darwin11"""
class LLVMCompiler(FakeCompiler):
- def print_llvm_target(self):
+ def print_llvm_target(self, args):
+ target = "x86_64-apple-darwin11.0.0"
+ for arg in args:
+ if arg.startswith("--target="):
+ target = arg[len("--target="):]
print """\
; ModuleID = '/dev/null'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-\
n8:16:32:64"
-target triple = "x86_64-apple-darwin11.0.0"
-"""
+target triple = "%s"
+""" % target
def print_dumpmachine(self):
print """x86_64-apple-darwin11.0.0"""
@@ -201,7 +205,7 @@ def main():
elif 'Wl,-v' in args:
compiler_instance.print_ld_version()
elif args_contained_in(args, ('-S', '-flto', '-o', '-', '/dev/null')):
- compiler_instance.print_llvm_target()
+ compiler_instance.print_llvm_target(args)
else:
raise SystemExit("unrecognized argument vector: %r" % (
args,))
Modified: lnt/trunk/tests/runtest/Inputs/test-suite-cmake/fake-cmake
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/tests/runtest/Inputs/test-suite-cmake/fake-cmake?rev=297125&r1=297124&r2=297125&view=diff
==============================================================================
--- lnt/trunk/tests/runtest/Inputs/test-suite-cmake/fake-cmake (original)
+++ lnt/trunk/tests/runtest/Inputs/test-suite-cmake/fake-cmake Tue Mar 7 02:04:33 2017
@@ -4,6 +4,7 @@ CMAKE_SRC_DIR="notfound"
DUMP_VARS=false
CMAKE_C_COMPILER=""
CMAKE_CXX_COMPILER=""
+CMAKE_C_COMPILER_TARGET="notfound"
while test $# -gt 0
do
@@ -16,6 +17,7 @@ do
# handle -D arguments to cmake.
if [[ $1 == -DCMAKE_C_COMPILER:* ]]; then CMAKE_C_COMPILER=${1#*=}; fi
if [[ $1 == -DCMAKE_CXX_COMPILER:* ]]; then CMAKE_CXX_COMPILER=${1#*=}; fi
+ if [[ $1 == -DCMAKE_C_COMPILER_TARGET:* ]]; then CMAKE_C_COMPILER_TARGET=${1#*=}; fi
shift
elif [[ $1 == -LAH && $2 == -N ]]; then
DUMP_VARS=true
@@ -31,6 +33,7 @@ do
if [[ -f $1/CMakeCache.txt ]]; then
CMAKE_C_COMPILER=`grep CMAKE_C_COMPILER:FILEPATH= $1/CMakeCache.txt | cut -f2 -d'='`
CMAKE_CXX_COMPILER=`grep CMAKE_CXX_COMPILER:FILEPATH= $1/CMakeCache.txt | cut -f2 -d'='`
+ CMAKE_C_COMPILER_TARGET=`grep CMAKE_C_COMPILER_TARGET:STRING= $1/CMakeCache.txt | cut -f2 -d'='`
fi
shift
fi
@@ -40,6 +43,9 @@ if [[ $DUMP_VARS == "true" ]]
then
echo CMAKE_C_COMPILER:FILEPATH=$CMAKE_C_COMPILER
echo CMAKE_CXX_COMPILER:FILEPATH=$CMAKE_CXX_COMPILER
+ if [[ $CMAKE_C_COMPILER_TARGET != "notfound" ]]; then
+ echo CMAKE_C_COMPILER_TARGET:STRING=$CMAKE_C_COMPILER_TARGET
+ fi
echo CMAKE_BUILD_TYPE:STRING=RelWithDebInfo
echo CMAKE_C_FLAGS:STRING=-O0
echo CMAKE_CXX_FLAGS:STRING=
@@ -50,6 +56,9 @@ else
echo "Dummy" > CMakeCache.txt
echo CMAKE_C_COMPILER:FILEPATH=$CMAKE_C_COMPILER >> CMakeCache.txt
echo CMAKE_CXX_COMPILER:FILEPATH=$CMAKE_CXX_COMPILER >> CMakeCache.txt
+ if [[ $CMAKE_C_COMPILER_TARGET != "notfound" ]]; then
+ echo CMAKE_C_COMPILER_TARGET:STRING=$CMAKE_C_COMPILER_TARGET >> CMakeCache.txt
+ fi
mkdir subtest
cp $CMAKE_SRC_DIR/fake-test $CMAKE_SRC_DIR/fake-results.json subtest
fi
Modified: lnt/trunk/tests/runtest/test_suite.py
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/tests/runtest/test_suite.py?rev=297125&r1=297124&r2=297125&view=diff
==============================================================================
--- lnt/trunk/tests/runtest/test_suite.py (original)
+++ lnt/trunk/tests/runtest/test_suite.py Tue Mar 7 02:04:33 2017
@@ -378,7 +378,7 @@
# RUN: --use-lit %S/Inputs/test-suite-cmake/fake-lit \
# RUN: > %t.log 2> %t.err || true
# RUN: FileCheck --check-prefix CHECK-MISSING-CC < %t.err %s
-# CHECK-MISSING-CC: error: --cc is required
+# CHECK-MISSING-CC: error: Couldn't find C compiler (). Maybe you should specify --cc?
# Check on conflicting -cc and -cmake-define=CMAKE_C_COMPILER
# options, the right compiler gets stored in the json report
@@ -395,6 +395,20 @@
# RUN: FileCheck --check-prefix CHECK-CC-CONFL-CMAKEDEFINE < %t.SANDBOX/build/report.json %s
# CHECK-CC-CONFL-CMAKEDEFINE: "run_order": "154332"
+# Check that while cross-compiling, the target architecture is recognized
+# correctly.
+# RUN: lnt runtest test-suite \
+# RUN: --sandbox %t.SANDBOX \
+# RUN: --no-timestamp \
+# RUN: --test-suite %S/Inputs/test-suite-cmake \
+# RUN: --cmake-define=CMAKE_C_COMPILER_TARGET:STRING=targetarch-linux-gnu \
+# RUN: --cc %{shared_inputs}/FakeCompilers/clang-r154331 \
+# RUN: --use-cmake %S/Inputs/test-suite-cmake/fake-cmake \
+# RUN: --use-make %S/Inputs/test-suite-cmake/fake-make \
+# RUN: --use-lit %S/Inputs/test-suite-cmake/fake-lit \
+# RUN: > %t.log 2> %t.err || true
+# RUN: FileCheck --check-prefix CHECK-CROSS-TARGET < %t.SANDBOX/build/report.json %s
+# CHECK-CROSS-TARGET: "cc_target": "targetarch-linux-gnu"
# Check running with PGO
# RUN: lnt runtest test-suite \
More information about the llvm-commits
mailing list