Browse Source

Merge topic 'emulator-property'

1975d53a Help: Add notes for topic 'emulator-property'
9160d6c2 TestGenerator: Add CROSSCOMPILING_EMULATOR support.
e942526b try_run: Use CMAKE_CROSSCOMPILING_EMULATOR.
579c4bec Properties: Add CROSSCOMPILING_EMULATOR target property.
Brad King 10 years ago
parent
commit
977796e307

+ 2 - 1
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.

+ 1 - 0
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

+ 1 - 0
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

+ 6 - 0
Help/prop_tgt/CROSSCOMPILING_EMULATOR.rst

@@ -0,0 +1,6 @@
+CROSSCOMPILING_EMULATOR
+-----------------------
+
+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.

+ 7 - 0
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.

+ 12 - 0
Help/variable/CMAKE_CROSSCOMPILING_EMULATOR.rst

@@ -0,0 +1,12 @@
+CMAKE_CROSSCOMPILING_EMULATOR
+-----------------------------
+
+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.

+ 1 - 0
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)

+ 20 - 1
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<std::string> emulatorWithArgs;
+      cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs);
+      std::string emulatorExe(emulatorWithArgs[0]);
+      cmSystemTools::ConvertToUnixSlashes(emulatorExe);
+      os << lg->EscapeForCMake(emulatorExe) << " ";
+      for(std::vector<std::string>::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<std::string>::const_iterator ci = command.begin()+1;
       ci != command.end(); ++ci)

+ 24 - 2
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<std::string> emulatorWithArgs;
+    cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs);
+    finalCommand += cmSystemTools::ConvertToRunCommandPath(
+                                 emulatorWithArgs[0].c_str());
+    finalCommand += " ";
+    for (std::vector<std::string>::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())
     {

+ 4 - 0
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=$<TARGET_FILE:pseudo_emulator>)

+ 12 - 0
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()

+ 8 - 0
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)

+ 3 - 0
Tests/RunCMake/CrosscompilingEmulator/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.1)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)

+ 28 - 0
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()

+ 1 - 0
Tests/RunCMake/CrosscompilingEmulator/InitialCache.txt.in

@@ -0,0 +1 @@
+CMAKE_EMULATOR:STRING=@PSEUDO_EMULATOR@

+ 8 - 0
Tests/RunCMake/CrosscompilingEmulator/RunCMakeTest.cmake

@@ -0,0 +1,8 @@
+include(RunCMake)
+
+set(RunCMake_TEST_OPTIONS
+    "-DCMAKE_CROSSCOMPILING_EMULATOR=${PSEUDO_EMULATOR}")
+
+run_cmake(CrosscompilingEmulatorProperty)
+run_cmake(TryRun)
+run_cmake(AddTest)

+ 1 - 0
Tests/RunCMake/CrosscompilingEmulator/TryRun-stdout.txt

@@ -0,0 +1 @@
+run_result: 42

+ 18 - 0
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}")

+ 4 - 0
Tests/RunCMake/CrosscompilingEmulator/simple_src.cxx

@@ -0,0 +1,4 @@
+int main(int, char **)
+{
+  return 13;
+}

+ 15 - 0
Tests/RunCMake/pseudo_emulator.c

@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+int main(int argc, char * argv[] )
+{
+ int ii;
+
+ printf("Command:");
+ for(ii = 1; ii < argc; ++ii)
+ {
+ printf(" \"%s\"", argv[ii]);
+ }
+ printf("\n");
+
+ return 42;
+}