diff --git a/Help/command/FIND_XXX_ROOT.txt b/Help/command/FIND_XXX_ROOT.txt index 407375a03..7f80dcb10 100644 --- a/Help/command/FIND_XXX_ROOT.txt +++ b/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 diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 59e806443..dd82b409d 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/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 diff --git a/Help/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN.rst b/Help/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN.rst new file mode 100644 index 000000000..86c0b0e42 --- /dev/null +++ b/Help/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN.rst @@ -0,0 +1,13 @@ +CMAKE__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__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. diff --git a/Help/variable/CMAKE_LANG_COMPILER_TARGET.rst b/Help/variable/CMAKE_LANG_COMPILER_TARGET.rst new file mode 100644 index 000000000..7c8efee9b --- /dev/null +++ b/Help/variable/CMAKE_LANG_COMPILER_TARGET.rst @@ -0,0 +1,11 @@ +CMAKE__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. diff --git a/Help/variable/CMAKE_SYSROOT.rst b/Help/variable/CMAKE_SYSROOT.rst new file mode 100644 index 000000000..e42e63a22 --- /dev/null +++ b/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. diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index 0d47a60a9..438a98a5d 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/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 diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index e88218922..5f9d9bf60 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/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 diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 7fa45340c..efb06c094 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/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) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 315d57ec3..829b6ffd4 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/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}) diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index 7d7be5c4b..055aad639 100644 --- a/Modules/Compiler/Clang.cmake +++ b/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() diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake index 504704dad..f01255cf6 100644 --- a/Modules/Compiler/GNU.cmake +++ b/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 diff --git a/Modules/Platform/QNX.cmake b/Modules/Platform/QNX.cmake index 068799f91..9afde0557 100644 --- a/Modules/Platform/QNX.cmake +++ b/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. diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index d4644c3cc..3152c2a0b 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1901,6 +1901,8 @@ void cmComputeLinkInformation::GetRPath(std::vector& runtimeDirs, } if(use_build_rpath || use_link_rpath) { + std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + cmSystemTools::ConvertToUnixSlashes(rootPath); std::vector const& rdirs = this->GetRuntimeSearchPath(); for(std::vector::const_iterator ri = rdirs.begin(); ri != rdirs.end(); ++ri) @@ -1909,9 +1911,14 @@ void cmComputeLinkInformation::GetRPath(std::vector& 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& 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) { - runtimeDirs.push_back(*ri); + d = d.substr(rootPath.size()); + } + if(emitted.insert(d).second) + { + runtimeDirs.push_back(d); } } } diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 479a6995c..bbfc427a4 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -405,6 +405,41 @@ int cmCoreTryCompile::TryCompileCode(std::vector 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"); diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 7beeda097..8c4281113 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -138,16 +138,27 @@ void cmFindCommon::RerootPaths(std::vector& 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 roots; - cmSystemTools::ExpandListArgument(rootPath, roots); + if (rootPath) + { + cmSystemTools::ExpandListArgument(rootPath, roots); + } + if (sysroot) + { + roots.push_back(sysroot); + } for(std::vector::iterator ri = roots.begin(); ri != roots.end(); ++ri) { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 63ec576d8..d2784a927 100644 --- a/Source/cmLocalGenerator.cxx +++ b/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& dirs, return; } + std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + std::vector implicitDirs; // Load implicit include directories for this language. std::string impDirVar = "CMAKE_"; @@ -1474,7 +1521,9 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector& dirs, for(std::vector::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);