From 579c4bec6e2352448f78d9333f7382ff34a08e5a Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Tue, 24 Mar 2015 00:02:50 -0400 Subject: [PATCH 1/4] Properties: Add CROSSCOMPILING_EMULATOR target property. Add CROSSCOMPILING_EMULATOR target property for executables. This is used by subsequent patches to run exectuables created for the target system when crosscompiling. The property is initialized by the CMAKE_CROSSCOMPILING_EMULATOR variable when defined. --- Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst | 4 +++ .../CMAKE_CROSSCOMPILING_EMULATOR.rst | 5 ++++ Source/cmTarget.cxx | 1 + Tests/RunCMake/CMakeLists.txt | 4 +++ .../CrosscompilingEmulator/CMakeLists.txt | 3 ++ .../CrosscompilingEmulatorProperty.cmake | 28 +++++++++++++++++++ .../CrosscompilingEmulator/RunCMakeTest.cmake | 6 ++++ .../CrosscompilingEmulator/simple_src.cxx | 4 +++ Tests/RunCMake/pseudo_emulator.c | 15 ++++++++++ 11 files changed, 72 insertions(+) create mode 100644 Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst create mode 100644 Help/variable/CMAKE_CROSSCOMPILING_EMULATOR.rst create mode 100644 Tests/RunCMake/CrosscompilingEmulator/CMakeLists.txt create mode 100644 Tests/RunCMake/CrosscompilingEmulator/CrosscompilingEmulatorProperty.cmake create mode 100644 Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/CrosscompilingEmulator/simple_src.cxx create mode 100644 Tests/RunCMake/pseudo_emulator.c diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index affa75f2a..02d164b5c 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -119,6 +119,7 @@ Properties on Targets /prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /prop_tgt/CONFIG_OUTPUT_NAME /prop_tgt/CONFIG_POSTFIX + /prop_tgt/CROSSCOMPILING_EMULATOR /prop_tgt/CXX_EXTENSIONS /prop_tgt/CXX_STANDARD /prop_tgt/CXX_STANDARD_REQUIRED diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index c342dbee1..63f704da5 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -25,6 +25,7 @@ Variables that Provide Information /variable/CMAKE_CFG_INTDIR /variable/CMAKE_COMMAND /variable/CMAKE_CROSSCOMPILING + /variable/CMAKE_CROSSCOMPILING_EMULATOR /variable/CMAKE_CTEST_COMMAND /variable/CMAKE_CURRENT_BINARY_DIR /variable/CMAKE_CURRENT_LIST_DIR diff --git a/Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst b/Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst new file mode 100644 index 000000000..2b5fd4d3d --- /dev/null +++ b/Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst @@ -0,0 +1,4 @@ +CROSSCOMPILING_EMULATOR +----------------------- + +Use the given emulator to run executables created when crosscompiling. diff --git a/Help/variable/CMAKE_CROSSCOMPILING_EMULATOR.rst b/Help/variable/CMAKE_CROSSCOMPILING_EMULATOR.rst new file mode 100644 index 000000000..fa6f1b743 --- /dev/null +++ b/Help/variable/CMAKE_CROSSCOMPILING_EMULATOR.rst @@ -0,0 +1,5 @@ +CMAKE_CROSSCOMPILING_EMULATOR +----------------------------- + +Default value for the :prop_tgt:`CROSSCOMPILING_EMULATOR` target property of +executables. See that target property for additional information. diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index b3d115543..85e5165b1 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -442,6 +442,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) if(this->TargetTypeValue == cmTarget::EXECUTABLE) { this->SetPropertyDefault("ANDROID_GUI", 0); + this->SetPropertyDefault("CROSSCOMPILING_EMULATOR", 0); } if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY || this->TargetTypeValue == cmTarget::MODULE_LIBRARY) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 60a8a8222..977721de8 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -226,3 +226,7 @@ add_RunCMake_test(COMPILE_LANGUAGE-genex) if(CMake_TEST_FindMatlab) add_RunCMake_test(FindMatlab) endif() + +add_executable(pseudo_emulator pseudo_emulator.c) +add_RunCMake_test(CrosscompilingEmulator + -DPSEUDO_EMULATOR=$) diff --git a/Tests/RunCMake/CrosscompilingEmulator/CMakeLists.txt b/Tests/RunCMake/CrosscompilingEmulator/CMakeLists.txt new file mode 100644 index 000000000..2d7598574 --- /dev/null +++ b/Tests/RunCMake/CrosscompilingEmulator/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.1) +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CrosscompilingEmulator/CrosscompilingEmulatorProperty.cmake b/Tests/RunCMake/CrosscompilingEmulator/CrosscompilingEmulatorProperty.cmake new file mode 100644 index 000000000..22d537c38 --- /dev/null +++ b/Tests/RunCMake/CrosscompilingEmulator/CrosscompilingEmulatorProperty.cmake @@ -0,0 +1,28 @@ +# This tests setting the CROSSCOMPILING_EMULATOR target property from the +# CMAKE_CROSSCOMPILING_EMULATOR variable. + +# -DCMAKE_CROSSCOMPILING_EMULATOR=/path/to/pseudo_emulator is passed to this +# test +add_executable(target_with_emulator simple_src.cxx) +get_property(emulator TARGET target_with_emulator + PROPERTY CROSSCOMPILING_EMULATOR) +if(NOT "${emulator}" MATCHES "pseudo_emulator") + message(SEND_ERROR "Default CROSSCOMPILING_EMULATOR property not set") +endif() + +set_property(TARGET target_with_emulator + PROPERTY CROSSCOMPILING_EMULATOR "another_emulator") +get_property(emulator TARGET target_with_emulator + PROPERTY CROSSCOMPILING_EMULATOR) +if(NOT "${emulator}" MATCHES "another_emulator") + message(SEND_ERROR + "set_property/get_property CROSSCOMPILING_EMULATOR is not consistent") +endif() + +unset(CMAKE_CROSSCOMPILING_EMULATOR CACHE) +add_executable(target_without_emulator simple_src.cxx) +get_property(emulator TARGET target_without_emulator + PROPERTY CROSSCOMPILING_EMULATOR) +if(NOT "${emulator}" STREQUAL "") + message(SEND_ERROR "Default CROSSCOMPILING_EMULATOR property not set to null") +endif() diff --git a/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake b/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake new file mode 100644 index 000000000..cecc57f86 --- /dev/null +++ b/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake @@ -0,0 +1,6 @@ +include(RunCMake) + +set(RunCMake_TEST_OPTIONS + "-DCMAKE_CROSSCOMPILING_EMULATOR=${PSEUDO_EMULATOR}") + +run_cmake(CrosscompilingEmulatorProperty) diff --git a/Tests/RunCMake/CrosscompilingEmulator/simple_src.cxx b/Tests/RunCMake/CrosscompilingEmulator/simple_src.cxx new file mode 100644 index 000000000..630adc6bc --- /dev/null +++ b/Tests/RunCMake/CrosscompilingEmulator/simple_src.cxx @@ -0,0 +1,4 @@ +int main(int, char **) +{ + return 0; +} diff --git a/Tests/RunCMake/pseudo_emulator.c b/Tests/RunCMake/pseudo_emulator.c new file mode 100644 index 000000000..9308f75aa --- /dev/null +++ b/Tests/RunCMake/pseudo_emulator.c @@ -0,0 +1,15 @@ +#include + +int main(int argc, char * argv[] ) +{ + int ii; + + printf("Command:"); + for(ii = 1; ii < argc; ++ii) + { + printf(" \"%s\"", argv[ii]); + } + printf("\n"); + + return 42; +} From e942526b3d9e886da4ce832d9d3adb99cc5ede2f Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sat, 28 Mar 2015 14:18:38 -0400 Subject: [PATCH 2/4] try_run: Use CMAKE_CROSSCOMPILING_EMULATOR. If the CMAKE_CROSSCOMPILING_EMULATOR variable is defined, and CMAKE_CROSSCOMPILING is TRUE, then use CMAKE_CROSSCOMPILING_EMULATOR to run the try_run executables. This prevents the need to populate TryRunResults.cmake when cross compiling. --- Help/command/try_run.rst | 3 ++- .../CMAKE_CROSSCOMPILING_EMULATOR.rst | 11 ++++++-- Source/cmTryRunCommand.cxx | 26 +++++++++++++++++-- .../CrosscompilingEmulator/RunCMakeTest.cmake | 1 + .../CrosscompilingEmulator/TryRun-stdout.txt | 1 + .../CrosscompilingEmulator/TryRun.cmake | 18 +++++++++++++ .../CrosscompilingEmulator/simple_src.cxx | 2 +- 7 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 Tests/RunCMake/CrosscompilingEmulator/TryRun-stdout.txt create mode 100644 Tests/RunCMake/CrosscompilingEmulator/TryRun.cmake diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst index 43ee21960..e3bd57d50 100644 --- a/Help/command/try_run.rst +++ b/Help/command/try_run.rst @@ -73,7 +73,8 @@ When cross compiling, the executable compiled in the first step usually cannot be run on the build host. The ``try_run`` command checks the :variable:`CMAKE_CROSSCOMPILING` variable to detect whether CMake is in cross-compiling mode. If that is the case, it will still try to compile -the executable, but it will not try to run the executable. Instead it +the executable, but it will not try to run the executable unless the +:variable:`CMAKE_CROSSCOMPILING_EMULATOR` variable is set. Instead it will create cache variables which must be filled by the user or by presetting them in some CMake script file to the values the executable would have produced if it had been run on its actual target platform. diff --git a/Help/variable/CMAKE_CROSSCOMPILING_EMULATOR.rst b/Help/variable/CMAKE_CROSSCOMPILING_EMULATOR.rst index fa6f1b743..95d2c7ffc 100644 --- a/Help/variable/CMAKE_CROSSCOMPILING_EMULATOR.rst +++ b/Help/variable/CMAKE_CROSSCOMPILING_EMULATOR.rst @@ -1,5 +1,12 @@ CMAKE_CROSSCOMPILING_EMULATOR ----------------------------- -Default value for the :prop_tgt:`CROSSCOMPILING_EMULATOR` target property of -executables. See that target property for additional information. +This variable is only used when :variable:`CMAKE_CROSSCOMPILING` is on. It +should point to a command on the host system that can run executable built +for the target system. + +The command will be used to run :command:`try_run` generated executables, +which avoids manual population of the TryRunResults.cmake file. + +It is also used as the default value for the +:prop_tgt:`CROSSCOMPILING_EMULATOR` target property of executables. diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index b5280cfd7..8b68d64c1 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -149,7 +149,8 @@ bool cmTryRunCommand { // "run" it and capture the output std::string runOutputContents; - if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING")) + if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING") && + !this->Makefile->IsDefinitionSet("CMAKE_CROSSCOMPILING_EMULATOR")) { this->DoNotRunExecutable(runArgs, argv[3], @@ -195,7 +196,28 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs, std::string* out) { int retVal = -1; - std::string finalCommand = cmSystemTools::ConvertToRunCommandPath( + + std::string finalCommand; + const std::string emulator = + this->Makefile->GetSafeDefinition("CMAKE_CROSSCOMPILING_EMULATOR"); + if (!emulator.empty()) + { + std::vector emulatorWithArgs; + cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs); + finalCommand += cmSystemTools::ConvertToRunCommandPath( + emulatorWithArgs[0].c_str()); + finalCommand += " "; + for (std::vector::const_iterator ei = + emulatorWithArgs.begin()+1; + ei != emulatorWithArgs.end(); ++ei) + { + finalCommand += "\""; + finalCommand += *ei; + finalCommand += "\""; + finalCommand += " "; + } + } + finalCommand += cmSystemTools::ConvertToRunCommandPath( this->OutputFile.c_str()); if (!runArgs.empty()) { diff --git a/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake b/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake index cecc57f86..04fb7db84 100644 --- a/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake +++ b/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake @@ -4,3 +4,4 @@ set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSSCOMPILING_EMULATOR=${PSEUDO_EMULATOR}") run_cmake(CrosscompilingEmulatorProperty) +run_cmake(TryRun) diff --git a/Tests/RunCMake/CrosscompilingEmulator/TryRun-stdout.txt b/Tests/RunCMake/CrosscompilingEmulator/TryRun-stdout.txt new file mode 100644 index 000000000..d012974b5 --- /dev/null +++ b/Tests/RunCMake/CrosscompilingEmulator/TryRun-stdout.txt @@ -0,0 +1 @@ +run_result: 42 diff --git a/Tests/RunCMake/CrosscompilingEmulator/TryRun.cmake b/Tests/RunCMake/CrosscompilingEmulator/TryRun.cmake new file mode 100644 index 000000000..4851cc778 --- /dev/null +++ b/Tests/RunCMake/CrosscompilingEmulator/TryRun.cmake @@ -0,0 +1,18 @@ +set(CMAKE_CROSSCOMPILING 1) + +try_run(run_result compile_result + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/simple_src.cxx + RUN_OUTPUT_VARIABLE run_output) + +message(STATUS "run_output: ${run_output}") +message(STATUS "run_result: ${run_result}") + +set(CMAKE_CROSSCOMPILING_EMULATOR ${CMAKE_CROSSCOMPILING_EMULATOR} + --flag + "multi arg") +try_run(run_result compile_result + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/simple_src.cxx + RUN_OUTPUT_VARIABLE run_output) +message(STATUS "Emulator with arguments run_output: ${run_output}") diff --git a/Tests/RunCMake/CrosscompilingEmulator/simple_src.cxx b/Tests/RunCMake/CrosscompilingEmulator/simple_src.cxx index 630adc6bc..e5e94f27e 100644 --- a/Tests/RunCMake/CrosscompilingEmulator/simple_src.cxx +++ b/Tests/RunCMake/CrosscompilingEmulator/simple_src.cxx @@ -1,4 +1,4 @@ int main(int, char **) { - return 0; + return 13; } From 9160d6c241adaeacc106d5b2ce4530f223345f22 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sat, 28 Mar 2015 22:05:35 -0400 Subject: [PATCH 3/4] TestGenerator: Add CROSSCOMPILING_EMULATOR support. Prefix test commands with the CROSSCOMPILING_EMULATOR property for target executables. This allows test suites to be run on the host when crosscompiling. --- Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst | 4 +++- Source/cmTestGenerator.cxx | 21 ++++++++++++++++++- .../AddTest-check.cmake | 12 +++++++++++ .../CrosscompilingEmulator/AddTest.cmake | 8 +++++++ .../InitialCache.txt.in | 1 + .../CrosscompilingEmulator/RunCMakeTest.cmake | 1 + 6 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/CrosscompilingEmulator/AddTest-check.cmake create mode 100644 Tests/RunCMake/CrosscompilingEmulator/AddTest.cmake create mode 100644 Tests/RunCMake/CrosscompilingEmulator/InitialCache.txt.in diff --git a/Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst b/Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst index 2b5fd4d3d..3ef8e0308 100644 --- a/Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst +++ b/Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst @@ -1,4 +1,6 @@ CROSSCOMPILING_EMULATOR ----------------------- -Use the given emulator to run executables created when crosscompiling. +Use the given emulator to run executables created when crosscompiling. This +command will be added as a prefix to :command:`add_test` test commands for +built target system executables. diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index f87a5353f..add80fa68 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -82,11 +82,31 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // be translated. std::string exe = command[0]; cmMakefile* mf = this->Test->GetMakefile(); + cmLocalGenerator* lg = mf->GetLocalGenerator(); cmTarget* target = mf->FindTargetToUse(exe); if(target && target->GetType() == cmTarget::EXECUTABLE) { // Use the target file on disk. exe = target->GetFullPath(config); + + // Prepend with the emulator when cross compiling if required. + const char * emulator = + target->GetProperty("CROSSCOMPILING_EMULATOR"); + if (emulator != 0) + { + std::vector emulatorWithArgs; + cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs); + std::string emulatorExe(emulatorWithArgs[0]); + cmSystemTools::ConvertToUnixSlashes(emulatorExe); + os << lg->EscapeForCMake(emulatorExe) << " "; + for(std::vector::const_iterator ei = + emulatorWithArgs.begin()+1; + ei != emulatorWithArgs.end(); + ++ei) + { + os << lg->EscapeForCMake(*ei) << " "; + } + } } else { @@ -96,7 +116,6 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, } // Generate the command line with full escapes. - cmLocalGenerator* lg = mf->GetLocalGenerator(); os << lg->EscapeForCMake(exe); for(std::vector::const_iterator ci = command.begin()+1; ci != command.end(); ++ci) diff --git a/Tests/RunCMake/CrosscompilingEmulator/AddTest-check.cmake b/Tests/RunCMake/CrosscompilingEmulator/AddTest-check.cmake new file mode 100644 index 000000000..0aae06cc7 --- /dev/null +++ b/Tests/RunCMake/CrosscompilingEmulator/AddTest-check.cmake @@ -0,0 +1,12 @@ +set(testfile "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake") +if(EXISTS "${testfile}") + file(READ "${testfile}" testfile_contents) +else() + message(FATAL_ERROR "Could not find expected CTestTestfile.cmake.") +endif() +if(testfile_contents MATCHES "add_test[(]DoesNotUseEmulator ^(pseudo_emulator)+$") + message(SEND_ERROR "Used emulator when it should not be used.") +endif() +if(NOT testfile_contents MATCHES "add_test[(]UsesEmulator .+pseudo_emulator.+$") + message(SEND_ERROR "Did not use emulator when it should be used.") +endif() diff --git a/Tests/RunCMake/CrosscompilingEmulator/AddTest.cmake b/Tests/RunCMake/CrosscompilingEmulator/AddTest.cmake new file mode 100644 index 000000000..41850f267 --- /dev/null +++ b/Tests/RunCMake/CrosscompilingEmulator/AddTest.cmake @@ -0,0 +1,8 @@ +set(CMAKE_CROSSCOMPILING 1) +enable_testing() +add_test(NAME DoesNotUseEmulator + COMMAND ${CMAKE_COMMAND} -E echo "Hi") + +add_executable(generated_exe simple_src.cxx) +add_test(NAME UsesEmulator + COMMAND generated_exe) diff --git a/Tests/RunCMake/CrosscompilingEmulator/InitialCache.txt.in b/Tests/RunCMake/CrosscompilingEmulator/InitialCache.txt.in new file mode 100644 index 000000000..c95fd8bb1 --- /dev/null +++ b/Tests/RunCMake/CrosscompilingEmulator/InitialCache.txt.in @@ -0,0 +1 @@ +CMAKE_EMULATOR:STRING=@PSEUDO_EMULATOR@ diff --git a/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake b/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake index 04fb7db84..2581cfcc2 100644 --- a/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake +++ b/Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake @@ -5,3 +5,4 @@ set(RunCMake_TEST_OPTIONS run_cmake(CrosscompilingEmulatorProperty) run_cmake(TryRun) +run_cmake(AddTest) From 1975d53ae19c46ee4f7384cc96be355f7e94df61 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 8 Apr 2015 09:03:45 -0400 Subject: [PATCH 4/4] Help: Add notes for topic 'emulator-property' --- Help/release/dev/emulator-property.rst | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Help/release/dev/emulator-property.rst diff --git a/Help/release/dev/emulator-property.rst b/Help/release/dev/emulator-property.rst new file mode 100644 index 000000000..1bc2f2d97 --- /dev/null +++ b/Help/release/dev/emulator-property.rst @@ -0,0 +1,7 @@ +emulator-property +----------------- + +* A :prop_tgt:`CROSSCOMPILING_EMULATOR` target property and supporting + :variable:`CMAKE_CROSSCOMPILING_EMULATOR` variable were introduced + to allow target platform binaries to run on the host during cross + compiling.