瀏覽代碼

Merge topic 'cross-compiling-toolchain-variables'

7cd65c9 Add CMAKE_SYSROOT variable to set --sysroot when cross compiling.
5096967 Allow toolchain files to specify an external toolchain.
76552d5 Add compiler target compile options.
f41ecd1 CMakeDetermineCompilerId: Look for internal file only on host
Brad King 12 年之前
父節點
當前提交
46ec48c93d

+ 9 - 2
Help/command/FIND_XXX_ROOT.txt

@@ -1,10 +1,17 @@
 The CMake variable CMAKE_FIND_ROOT_PATH specifies one or more
 directories to be prepended to all other search directories.  This
 effectively "re-roots" the entire search under given locations.  By
-default it is empty.  It is especially useful when cross-compiling to
+default it is empty.
+
+The :variable:`CMAKE_SYSROOT` variable can also be used to specify exactly one
+directory to use as a prefix.  Setting :variable:`CMAKE_SYSROOT` also has other
+effects.  See the documentation for that variable for more.
+
+These variables are especially useful when cross-compiling to
 point to the root directory of the target environment and CMake will
 search there too.  By default at first the directories listed in
-CMAKE_FIND_ROOT_PATH and then the non-rooted directories will be
+CMAKE_FIND_ROOT_PATH are searched, then the :variable:`CMAKE_SYSROOT` directory is
+searched, and then the non-rooted directories will be
 searched.  The default behavior can be adjusted by setting
 |CMAKE_FIND_ROOT_PATH_MODE_XXX|.  This behavior can be manually
 overridden on a per-call basis.  By using CMAKE_FIND_ROOT_PATH_BOTH

+ 3 - 0
Help/manual/cmake-variables.7.rst

@@ -91,6 +91,7 @@ Variables that Change Behavior
    /variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName
    /variable/CMAKE_ERROR_DEPRECATED
    /variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
+   /variable/CMAKE_SYSROOT
    /variable/CMAKE_FIND_LIBRARY_PREFIXES
    /variable/CMAKE_FIND_LIBRARY_SUFFIXES
    /variable/CMAKE_FIND_PACKAGE_WARN_NO_MODULE
@@ -234,6 +235,8 @@ Variables for Languages
    /variable/CMAKE_LANG_COMPILER_ID
    /variable/CMAKE_LANG_COMPILER_LOADED
    /variable/CMAKE_LANG_COMPILER
+   /variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN
+   /variable/CMAKE_LANG_COMPILER_TARGET
    /variable/CMAKE_LANG_COMPILER_VERSION
    /variable/CMAKE_LANG_CREATE_SHARED_LIBRARY
    /variable/CMAKE_LANG_CREATE_SHARED_MODULE

+ 13 - 0
Help/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN.rst

@@ -0,0 +1,13 @@
+CMAKE_<LANG>_COMPILER_EXTERNAL_TOOLCHAIN
+----------------------------------------
+
+The external toolchain for cross-compiling, if supported.
+
+Some compiler toolchains do not ship their own auxilliary utilities such as
+archivers and linkers.  The compiler driver may support a command-line argument
+to specify the location of such tools.  CMAKE_<LANG>_COMPILER_EXTERNAL_TOOLCHAIN
+may be set to a path to a path to the external toolchain and will be passed
+to the compiler driver if supported.
+
+This variable may only be set in a toolchain file specified by
+the ``CMAKE_TOOLCHAIN_FILE`` variable.

+ 11 - 0
Help/variable/CMAKE_LANG_COMPILER_TARGET.rst

@@ -0,0 +1,11 @@
+CMAKE_<LANG>_COMPILER_TARGET
+----------------------------
+
+The target for cross-compiling, if supported.
+
+Some compiler drivers are inherently cross-compilers, such as clang and
+QNX qcc. These compiler drivers support a command-line argument to specify
+the target to cross-compile for.
+
+This variable may only be set in a toolchain file specified by
+the ``CMAKE_TOOLCHAIN_FILE`` variable.

+ 12 - 0
Help/variable/CMAKE_SYSROOT.rst

@@ -0,0 +1,12 @@
+CMAKE_SYSROOT
+-------------
+
+Path to pass to the compiler in the ``--sysroot`` flag.
+
+The ``CMAKE_SYSROOT`` content is passed to the compiler in the ``--sysroot``
+flag, if supported.  The path is also stripped from the RPATH/RUNPATH if
+necessary on installation.  The ``CMAKE_SYSROOT`` is also used to prefix
+paths searched by the ``find_*`` commands.
+
+This variable may only be set in a toolchain file specified by
+the ``CMAKE_TOOLCHAIN_FILE`` variable.

+ 6 - 0
Modules/CMakeDetermineCCompiler.cmake

@@ -158,6 +158,12 @@ if (CMAKE_CROSSCOMPILING  AND NOT _CMAKE_TOOLCHAIN_PREFIX)
     get_filename_component(COMPILER_BASENAME "${CMAKE_C_COMPILER}" NAME)
     if (COMPILER_BASENAME MATCHES "^(.+-)(clang|g?cc)(-[0-9]+\\.[0-9]+\\.[0-9]+)?(\\.exe)?$")
       set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+    elseif("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
+      set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_C_COMPILER_TARGET}-)
+    elseif(COMPILER_BASENAME MATCHES "qcc(\\.exe)?$")
+      if(CMAKE_C_COMPILER_TARGET MATCHES "gcc_nto([^_le]+)(le)?.*$")
+        set(_CMAKE_TOOLCHAIN_PREFIX nto${CMAKE_MATCH_1}-)
+      endif()
     endif ()
 
     # if "llvm-" is part of the prefix, remove it, since llvm doesn't have its own binutils

+ 6 - 0
Modules/CMakeDetermineCXXCompiler.cmake

@@ -156,6 +156,12 @@ if (CMAKE_CROSSCOMPILING  AND NOT  _CMAKE_TOOLCHAIN_PREFIX)
     get_filename_component(COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME)
     if (COMPILER_BASENAME MATCHES "^(.+-)(clan)?[gc]\\+\\+(-[0-9]+\\.[0-9]+\\.[0-9]+)?(\\.exe)?$")
       set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+    elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
+      set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_CXX_COMPILER_TARGET}-)
+    elseif(COMPILER_BASENAME MATCHES "QCC(\\.exe)?$")
+      if(CMAKE_CXX_COMPILER_TARGET MATCHES "gcc_nto([^_le]+)(le)?.*$")
+        set(_CMAKE_TOOLCHAIN_PREFIX nto${CMAKE_MATCH_1}-)
+      endif()
     endif ()
 
     # if "llvm-" is part of the prefix, remove it, since llvm doesn't have its own binutils

+ 1 - 1
Modules/CMakeDetermineCompilerId.cmake

@@ -85,7 +85,7 @@ endfunction()
 #-----------------------------------------------------------------------------
 # Function to write the compiler id source file.
 function(CMAKE_DETERMINE_COMPILER_ID_WRITE lang src)
-  find_file(src_in ${src}.in PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH)
+  find_file(src_in ${src}.in PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
   file(READ ${src_in} ID_CONTENT_IN)
   unset(src_in CACHE)
   string(CONFIGURE "${ID_CONTENT_IN}" ID_CONTENT_OUT @ONLY)

+ 6 - 1
Modules/CMakeFindBinUtils.cmake

@@ -43,7 +43,12 @@ if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC"
 
 # in all other cases search for ar, ranlib, etc.
 else()
-
+  if(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN)
+    set(_CMAKE_TOOLCHAIN_LOCATION ${_CMAKE_TOOLCHAIN_LOCATION} ${CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN}/bin)
+  endif()
+  if(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN)
+    set(_CMAKE_TOOLCHAIN_LOCATION ${_CMAKE_TOOLCHAIN_LOCATION} ${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}/bin)
+  endif()
   find_program(CMAKE_AR NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ar${_CMAKE_TOOLCHAIN_SUFFIX} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
 
   find_program(CMAKE_RANLIB NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ranlib HINTS ${_CMAKE_TOOLCHAIN_LOCATION})

+ 2 - 0
Modules/Compiler/Clang.cmake

@@ -30,5 +30,7 @@ else()
     set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
     set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
     set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
+    set(CMAKE_${lang}_COMPILE_OPTIONS_TARGET "-target ")
+    set(CMAKE_${lang}_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "-gcc-toolchain ")
   endmacro()
 endif()

+ 1 - 0
Modules/Compiler/GNU.cmake

@@ -30,6 +30,7 @@ macro(__compiler_gnu lang)
   endif()
   set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
   set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
+  set(CMAKE_${lang}_COMPILE_OPTIONS_SYSROOT "--sysroot=")
 
   # Older versions of gcc (< 4.5) contain a bug causing them to report a missing
   # header file as a warning if depfiles are enabled, causing check_header_file

+ 3 - 0
Modules/Platform/QNX.cmake

@@ -16,6 +16,9 @@ set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":")
 set(CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG "-Wl,-rpath-link,")
 set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,")
 set(CMAKE_EXE_EXPORTS_C_FLAG "-Wl,--export-dynamic")
+# http://www.qnx.com/developers/docs/6.4.0/neutrino/utilities/q/qcc.html#examples
+set(CMAKE_C_COMPILE_OPTIONS_TARGET "-V")
+set(CMAKE_CXX_COMPILE_OPTIONS_TARGET "-V")
 
 # Shared libraries with no builtin soname may not be linked safely by
 # specifying the file path.

+ 16 - 4
Source/cmComputeLinkInformation.cxx

@@ -1901,6 +1901,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
     }
   if(use_build_rpath || use_link_rpath)
     {
+    std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+    cmSystemTools::ConvertToUnixSlashes(rootPath);
     std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath();
     for(std::vector<std::string>::const_iterator ri = rdirs.begin();
         ri != rdirs.end(); ++ri)
@@ -1909,9 +1911,14 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
       // support or if using the link path as an rpath.
       if(use_build_rpath)
         {
-        if(emitted.insert(*ri).second)
+        std::string d = *ri;
+        if (!rootPath.empty() && d.find(rootPath) == 0)
           {
-          runtimeDirs.push_back(*ri);
+          d = d.substr(rootPath.size());
+          }
+        if(emitted.insert(d).second)
+          {
+          runtimeDirs.push_back(d);
           }
         }
       else if(use_link_rpath)
@@ -1924,9 +1931,14 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
            !cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) &&
            !cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir))
           {
-          if(emitted.insert(*ri).second)
+          std::string d = *ri;
+          if (!rootPath.empty() && d.find(rootPath) == 0)
+            {
+            d = d.substr(rootPath.size());
+            }
+          if(emitted.insert(d).second)
             {
-            runtimeDirs.push_back(*ri);
+            runtimeDirs.push_back(d);
             }
           }
         }

+ 35 - 0
Source/cmCoreTryCompile.cxx

@@ -405,6 +405,41 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
       flag += this->Makefile->GetSafeDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
       cmakeFlags.push_back(flag);
       }
+    if (const char *cxxDef
+              = this->Makefile->GetDefinition("CMAKE_CXX_COMPILER_TARGET"))
+      {
+      std::string flag="-DCMAKE_CXX_COMPILER_TARGET=";
+      flag += cxxDef;
+      cmakeFlags.push_back(flag);
+      }
+    if (const char *cDef
+                = this->Makefile->GetDefinition("CMAKE_C_COMPILER_TARGET"))
+      {
+      std::string flag="-DCMAKE_C_COMPILER_TARGET=";
+      flag += cDef;
+      cmakeFlags.push_back(flag);
+      }
+    if (const char *tcxxDef = this->Makefile->GetDefinition(
+                                  "CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN"))
+      {
+      std::string flag="-DCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN=";
+      flag += tcxxDef;
+      cmakeFlags.push_back(flag);
+      }
+    if (const char *tcDef = this->Makefile->GetDefinition(
+                                    "CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN"))
+      {
+      std::string flag="-DCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN=";
+      flag += tcDef;
+      cmakeFlags.push_back(flag);
+      }
+    if (const char *rootDef
+              = this->Makefile->GetDefinition("CMAKE_SYSROOT"))
+      {
+      std::string flag="-DCMAKE_SYSROOT=";
+      flag += rootDef;
+      cmakeFlags.push_back(flag);
+      }
     if(this->Makefile->GetDefinition("CMAKE_POSITION_INDEPENDENT_CODE")!=0)
       {
       fprintf(fout, "set(CMAKE_POSITION_INDEPENDENT_CODE \"ON\")\n");

+ 13 - 2
Source/cmFindCommon.cxx

@@ -138,16 +138,27 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
     {
     return;
     }
+  const char* sysroot =
+    this->Makefile->GetDefinition("CMAKE_SYSROOT");
   const char* rootPath =
     this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
-  if((rootPath == 0) || (strlen(rootPath) == 0))
+  const bool noSysroot = !sysroot || !*sysroot;
+  const bool noRootPath = !rootPath || !*rootPath;
+  if(noSysroot && noRootPath)
     {
     return;
     }
 
   // Construct the list of path roots with no trailing slashes.
   std::vector<std::string> roots;
-  cmSystemTools::ExpandListArgument(rootPath, roots);
+  if (rootPath)
+    {
+    cmSystemTools::ExpandListArgument(rootPath, roots);
+    }
+  if (sysroot)
+    {
+    roots.push_back(sysroot);
+    }
   for(std::vector<std::string>::iterator ri = roots.begin();
       ri != roots.end(); ++ri)
     {

+ 50 - 1
Source/cmLocalGenerator.cxx

@@ -1043,11 +1043,38 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
       // If this is the compiler then look for the extra variable
       // _COMPILER_ARG1 which must be the first argument to the compiler
       const char* compilerArg1 = 0;
+      const char* compilerTarget = 0;
+      const char* compilerOptionTarget = 0;
+      const char* compilerExternalToolchain = 0;
+      const char* compilerOptionExternalToolchain = 0;
+      const char* compilerSysroot = 0;
+      const char* compilerOptionSysroot = 0;
       if(actualReplace == "CMAKE_${LANG}_COMPILER")
         {
         std::string arg1 = actualReplace + "_ARG1";
         cmSystemTools::ReplaceString(arg1, "${LANG}", lang);
         compilerArg1 = this->Makefile->GetDefinition(arg1.c_str());
+        compilerTarget
+              = this->Makefile->GetDefinition(
+                (std::string("CMAKE_") + lang + "_COMPILER_TARGET").c_str());
+        compilerOptionTarget
+              = this->Makefile->GetDefinition(
+                (std::string("CMAKE_") + lang +
+                                          "_COMPILE_OPTIONS_TARGET").c_str());
+        compilerExternalToolchain
+              = this->Makefile->GetDefinition(
+                (std::string("CMAKE_") + lang +
+                                    "_COMPILER_EXTERNAL_TOOLCHAIN").c_str());
+        compilerOptionExternalToolchain
+              = this->Makefile->GetDefinition(
+                (std::string("CMAKE_") + lang +
+                              "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN").c_str());
+        compilerSysroot
+              = this->Makefile->GetDefinition("CMAKE_SYSROOT");
+        compilerOptionSysroot
+              = this->Makefile->GetDefinition(
+                (std::string("CMAKE_") + lang +
+                              "_COMPILE_OPTIONS_SYSROOT").c_str());
         }
       if(actualReplace.find("${LANG}") != actualReplace.npos)
         {
@@ -1068,6 +1095,24 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
             ret += " ";
             ret += compilerArg1;
             }
+          if (compilerTarget && compilerOptionTarget)
+            {
+            ret += " ";
+            ret += compilerOptionTarget;
+            ret += compilerTarget;
+            }
+          if (compilerExternalToolchain && compilerOptionExternalToolchain)
+            {
+            ret += " ";
+            ret += compilerOptionExternalToolchain;
+            ret += this->EscapeForShell(compilerExternalToolchain, true);
+            }
+          if (compilerSysroot && compilerOptionSysroot)
+            {
+            ret += " ";
+            ret += compilerOptionSysroot;
+            ret += this->EscapeForShell(compilerSysroot, true);
+            }
           return ret;
           }
         return replace;
@@ -1462,6 +1507,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
     return;
     }
 
+  std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+
   std::vector<std::string> implicitDirs;
   // Load implicit include directories for this language.
   std::string impDirVar = "CMAKE_";
@@ -1474,7 +1521,9 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
     for(std::vector<std::string>::const_iterator i = impDirVec.begin();
         i != impDirVec.end(); ++i)
       {
-      emitted.insert(*i);
+      std::string d = rootPath + *i;
+      cmSystemTools::ConvertToUnixSlashes(d);
+      emitted.insert(d);
       if (!stripImplicitInclDirs)
         {
         implicitDirs.push_back(*i);