diff options
-rw-r--r-- | Help/command/FIND_XXX_ROOT.txt | 8 | ||||
-rw-r--r-- | Help/manual/cmake-variables.7.rst | 1 | ||||
-rw-r--r-- | Help/variable/CMAKE_FIND_NO_INSTALL_PREFIX.rst | 6 | ||||
-rw-r--r-- | Help/variable/CMAKE_STAGING_PREFIX.rst | 13 | ||||
-rw-r--r-- | Help/variable/CMAKE_SYSTEM_PREFIX_PATH.rst | 6 | ||||
-rw-r--r-- | Modules/Platform/UnixPaths.cmake | 6 | ||||
-rw-r--r-- | Modules/Platform/WindowsPaths.cmake | 11 | ||||
-rw-r--r-- | Source/cmComputeLinkInformation.cxx | 20 | ||||
-rw-r--r-- | Source/cmFindCommon.cxx | 7 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 5 | ||||
-rw-r--r-- | Tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/StagingPrefix/CMakeLists.txt | 89 | ||||
-rw-r--r-- | Tests/StagingPrefix/Consumer/CMakeLists.txt | 22 | ||||
-rw-r--r-- | Tests/StagingPrefix/Consumer/cmake/FindBar.cmake | 6 | ||||
-rw-r--r-- | Tests/StagingPrefix/Consumer/main.cpp | 10 | ||||
-rw-r--r-- | Tests/StagingPrefix/Producer/CMakeLists.txt | 26 | ||||
-rw-r--r-- | Tests/StagingPrefix/Producer/bar.cpp | 7 | ||||
-rw-r--r-- | Tests/StagingPrefix/Producer/bar.h | 10 | ||||
-rw-r--r-- | Tests/StagingPrefix/Producer/foo.cpp | 7 | ||||
-rw-r--r-- | Tests/StagingPrefix/Producer/foo.h | 10 | ||||
-rw-r--r-- | Tests/StagingPrefix/main.cpp | 5 |
21 files changed, 267 insertions, 9 deletions
diff --git a/Help/command/FIND_XXX_ROOT.txt b/Help/command/FIND_XXX_ROOT.txt index 7f80dcb..efc076f 100644 --- a/Help/command/FIND_XXX_ROOT.txt +++ b/Help/command/FIND_XXX_ROOT.txt @@ -1,7 +1,9 @@ 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. +effectively "re-roots" the entire search under given locations. +Paths which are descendants of the :variable:`CMAKE_STAGING_PREFIX` are excluded +from this re-rooting, because that variable is always a path on the host system. +By default the CMAKE_FIND_ROOT_PATH 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 @@ -18,4 +20,4 @@ overridden on a per-call basis. By using CMAKE_FIND_ROOT_PATH_BOTH the search order will be as described above. If NO_CMAKE_FIND_ROOT_PATH is used then CMAKE_FIND_ROOT_PATH will not be used. If ONLY_CMAKE_FIND_ROOT_PATH is used then only the re-rooted -directories will be searched. +directories and directories below :variable:`CMAKE_STAGING_PREFIX` will be searched. diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index dd82b40..a46539f 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -110,6 +110,7 @@ Variables that Change Behavior /variable/CMAKE_PREFIX_PATH /variable/CMAKE_PROGRAM_PATH /variable/CMAKE_SKIP_INSTALL_ALL_DEPENDENCY + /variable/CMAKE_STAGING_PREFIX /variable/CMAKE_SYSTEM_IGNORE_PATH /variable/CMAKE_SYSTEM_INCLUDE_PATH /variable/CMAKE_SYSTEM_LIBRARY_PATH diff --git a/Help/variable/CMAKE_FIND_NO_INSTALL_PREFIX.rst b/Help/variable/CMAKE_FIND_NO_INSTALL_PREFIX.rst index 91231b0..70d920b 100644 --- a/Help/variable/CMAKE_FIND_NO_INSTALL_PREFIX.rst +++ b/Help/variable/CMAKE_FIND_NO_INSTALL_PREFIX.rst @@ -3,11 +3,13 @@ CMAKE_FIND_NO_INSTALL_PREFIX Ignore the :variable:`CMAKE_INSTALL_PREFIX` when searching for assets. -CMake adds the :variable:`CMAKE_INSTALL_PREFIX` to the +CMake adds the :variable:`CMAKE_INSTALL_PREFIX` and the +:variable:`CMAKE_STAGING_PREFIX` variable to the :variable:`CMAKE_SYSTEM_PREFIX_PATH` by default. This variable may be set on the command line to control that behavior. Set :variable:`CMAKE_FIND_NO_INSTALL_PREFIX` to TRUE to tell find_package not -to search in the :variable:`CMAKE_INSTALL_PREFIX` by default. Note that the +to search in the :variable:`CMAKE_INSTALL_PREFIX` or +:variable:`CMAKE_STAGING_PREFIX` by default. Note that the prefix may still be searched for other reasons, such as being the same prefix as the CMake installation, or for being a built-in system prefix. diff --git a/Help/variable/CMAKE_STAGING_PREFIX.rst b/Help/variable/CMAKE_STAGING_PREFIX.rst new file mode 100644 index 0000000..c4de7da --- /dev/null +++ b/Help/variable/CMAKE_STAGING_PREFIX.rst @@ -0,0 +1,13 @@ +CMAKE_STAGING_PREFIX +-------------------- + +This variable may be set to a path to install to when cross-compiling. This can +be useful if the path in :variable:`CMAKE_SYSROOT` is read-only, or otherwise +should remain pristine. + +The CMAKE_STAGING_PREFIX location is also used as a search prefix by the ``find_*`` +commands. This can be controlled by setting the :variable:`CMAKE_FIND_NO_INSTALL_PREFIX` +variable. + +If any RPATH/RUNPATH entries passed to the linker contain the CMAKE_STAGING_PREFIX, +the matching path fragments are replaced with the :variable:`CMAKE_INSTALL_PREFIX`. diff --git a/Help/variable/CMAKE_SYSTEM_PREFIX_PATH.rst b/Help/variable/CMAKE_SYSTEM_PREFIX_PATH.rst index 2dbae1f..537eaba 100644 --- a/Help/variable/CMAKE_SYSTEM_PREFIX_PATH.rst +++ b/Help/variable/CMAKE_SYSTEM_PREFIX_PATH.rst @@ -9,8 +9,8 @@ appropriate subdirectories to the base directories. So FIND_PROGRAM() adds /bin to each of the directories in the path, FIND_LIBRARY() appends /lib to each of the directories, and FIND_PATH() and FIND_FILE() append /include . By default this contains the standard -directories for the current system and the CMAKE_INSTALL_PREFIX. It -is NOT intended to be modified by the project, use CMAKE_PREFIX_PATH -for this. See also CMAKE_SYSTEM_INCLUDE_PATH, +directories for the current system, the CMAKE_INSTALL_PREFIX and +the :variable:`CMAKE_STAGING_PREFIX`. It is NOT intended to be modified by +the project, use CMAKE_PREFIX_PATH for this. See also CMAKE_SYSTEM_INCLUDE_PATH, CMAKE_SYSTEM_LIBRARY_PATH, CMAKE_SYSTEM_PROGRAM_PATH, and CMAKE_SYSTEM_IGNORE_PATH. diff --git a/Modules/Platform/UnixPaths.cmake b/Modules/Platform/UnixPaths.cmake index 7a424c4..eca3280 100644 --- a/Modules/Platform/UnixPaths.cmake +++ b/Modules/Platform/UnixPaths.cmake @@ -43,6 +43,12 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX) # Project install destination. "${CMAKE_INSTALL_PREFIX}" ) + if(CMAKE_STAGING_PREFIX) + list(APPEND CMAKE_SYSTEM_PREFIX_PATH + # User-supplied staging prefix. + "${CMAKE_STAGING_PREFIX}" + ) + endif() endif() # List common include file locations not under the common prefixes. diff --git a/Modules/Platform/WindowsPaths.cmake b/Modules/Platform/WindowsPaths.cmake index c231495..3240c23 100644 --- a/Modules/Platform/WindowsPaths.cmake +++ b/Modules/Platform/WindowsPaths.cmake @@ -79,6 +79,12 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX) # Project install destination. "${CMAKE_INSTALL_PREFIX}" ) + if (CMAKE_STAGING_PREFIX) + list(APPEND CMAKE_SYSTEM_PREFIX_PATH + # User-supplied staging prefix. + "${CMAKE_STAGING_PREFIX}" + ) + endif() endif() if(CMAKE_CROSSCOMPILING AND NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") @@ -94,6 +100,11 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX) list(APPEND CMAKE_SYSTEM_LIBRARY_PATH "${CMAKE_INSTALL_PREFIX}/bin" ) + if (CMAKE_STAGING_PREFIX) + list(APPEND CMAKE_SYSTEM_LIBRARY_PATH + "${CMAKE_STAGING_PREFIX}/bin" + ) + endif() endif() list(APPEND CMAKE_SYSTEM_LIBRARY_PATH "${_CMAKE_INSTALL_DIR}/bin" diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 3152c2a..0ef3d2e 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1902,6 +1902,10 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, if(use_build_rpath || use_link_rpath) { std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + const char *stagePath + = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); + const char *installPrefix + = this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); cmSystemTools::ConvertToUnixSlashes(rootPath); std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath(); for(std::vector<std::string>::const_iterator ri = rdirs.begin(); @@ -1916,6 +1920,14 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, { d = d.substr(rootPath.size()); } + else if (stagePath && *stagePath && d.find(stagePath) == 0) + { + std::string suffix = d.substr(strlen(stagePath)); + d = installPrefix; + d += "/"; + d += suffix; + cmSystemTools::ConvertToUnixSlashes(d); + } if(emitted.insert(d).second) { runtimeDirs.push_back(d); @@ -1936,6 +1948,14 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, { d = d.substr(rootPath.size()); } + else if (stagePath && *stagePath && d.find(stagePath) == 0) + { + std::string suffix = d.substr(strlen(stagePath)); + d = installPrefix; + d += "/"; + d += suffix; + cmSystemTools::ConvertToUnixSlashes(d); + } if(emitted.insert(d).second) { runtimeDirs.push_back(d); diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 8c42811..e8c8da3 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -165,6 +165,9 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) cmSystemTools::ConvertToUnixSlashes(*ri); } + const char* stagePrefix = + this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); + // Copy the original set of unrooted paths. std::vector<std::string> unrootedPaths = paths; paths.clear(); @@ -179,7 +182,9 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) // already inside. Skip the unrooted path if it is relative to // a user home directory or is empty. std::string rootedDir; - if(cmSystemTools::IsSubDirectory(ui->c_str(), ri->c_str())) + if(cmSystemTools::IsSubDirectory(ui->c_str(), ri->c_str()) + || (stagePrefix + && cmSystemTools::IsSubDirectory(ui->c_str(), stagePrefix))) { rootedDir = *ui; } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index d2784a9..cf5798f 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -370,6 +370,11 @@ void cmLocalGenerator::GenerateInstallRules() prefix = "/usr/local"; } #endif + if (const char *stagingPrefix + = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX")) + { + prefix = stagingPrefix; + } // Compute the set of configurations. std::vector<std::string> configurationTypes; diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 48abfae..f7a320a 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -269,6 +269,7 @@ if(BUILD_TESTING) ADD_TEST_MACRO(CompileOptions CompileOptions) ADD_TEST_MACRO(CompatibleInterface CompatibleInterface) ADD_TEST_MACRO(AliasTarget AliasTarget) + ADD_TEST_MACRO(StagingPrefix StagingPrefix) ADD_TEST_MACRO(InterfaceLibrary InterfaceLibrary) set_tests_properties(EmptyLibrary PROPERTIES PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test") diff --git a/Tests/StagingPrefix/CMakeLists.txt b/Tests/StagingPrefix/CMakeLists.txt new file mode 100644 index 0000000..922776d --- /dev/null +++ b/Tests/StagingPrefix/CMakeLists.txt @@ -0,0 +1,89 @@ + +cmake_minimum_required(VERSION 2.8.12) +project(StagingPrefix) + +# Wipe out the install tree +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/CleanupProject + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/ConsumerBuild + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/ProducerBuild + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/stage + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/prefix + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/ignored + ) +add_custom_target(CleanupTarget ALL DEPENDS ${CMAKE_BINARY_DIR}/CleanupProject) +set_property( + SOURCE ${CMAKE_BINARY_DIR}/CleanupProject + PROPERTY SYMBOLIC 1 + ) + +if(CMAKE_CONFIGURATION_TYPES) + set(NESTED_CONFIG_TYPE -C "${CMAKE_CFG_INTDIR}") +else() + if(CMAKE_BUILD_TYPE) + set(NESTED_CONFIG_TYPE -C "${CMAKE_BUILD_TYPE}") + else() + set(NESTED_CONFIG_TYPE) + endif() +endif() + +# Build and install the producer. +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/ProducerProject + COMMAND ${CMAKE_CTEST_COMMAND} ${NESTED_CONFIG_TYPE} + --build-and-test + ${CMAKE_SOURCE_DIR}/Producer + ${CMAKE_BINARY_DIR}/ProducerBuild + --build-noclean + --build-project Producer + --build-target install + --build-generator ${CMAKE_GENERATOR} + --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}" + --build-options + -DCMAKE_VERBOSE_MAKEFILE=1 + "-DCMAKE_STAGING_PREFIX=${CMAKE_BINARY_DIR}/stage" + "-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/prefix" + VERBATIM + ) + +add_custom_target(ProducerTarget ALL DEPENDS ${CMAKE_BINARY_DIR}/ProducerProject) +add_dependencies(ProducerTarget CleanupTarget) +set_property( + SOURCE ${CMAKE_BINARY_DIR}/ProducerProject + PROPERTY SYMBOLIC 1 + ) + +if(NOT WIN32) + file(WRITE + "${CMAKE_BINARY_DIR}/ignored/${CMAKE_BINARY_DIR}/stage/include/ignored.h" + "#define IGNORED\n" + ) +endif() + +# Build and install the consumer. +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/ConsumerProject + COMMAND ${CMAKE_CTEST_COMMAND} ${NESTED_CONFIG_TYPE} + --build-and-test + ${CMAKE_SOURCE_DIR}/Consumer + ${CMAKE_BINARY_DIR}/ConsumerBuild + --build-noclean + --build-project Consumer + --build-target install + --build-generator ${CMAKE_GENERATOR} + --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}" + --build-options + "-DCMAKE_FIND_ROOT_PATH=${CMAKE_BINARY_DIR}/ignored" + "-DCMAKE_STAGING_PREFIX=${CMAKE_BINARY_DIR}/stage" + -DCMAKE_VERBOSE_MAKEFILE=1 + VERBATIM + ) +add_custom_target(ConsumerTarget ALL DEPENDS ${CMAKE_BINARY_DIR}/ConsumerProject) +add_dependencies(ConsumerTarget ProducerTarget) +set_property( + SOURCE ${CMAKE_BINARY_DIR}/ConsumerProject + PROPERTY SYMBOLIC 1 + ) + +add_executable(StagingPrefix main.cpp) +add_dependencies(StagingPrefix ConsumerTarget) diff --git a/Tests/StagingPrefix/Consumer/CMakeLists.txt b/Tests/StagingPrefix/Consumer/CMakeLists.txt new file mode 100644 index 0000000..a230441 --- /dev/null +++ b/Tests/StagingPrefix/Consumer/CMakeLists.txt @@ -0,0 +1,22 @@ + +cmake_minimum_required (VERSION 2.8.12) +project(Consumer) + + +add_executable(executable main.cpp) +find_package(Foo CONFIG REQUIRED) +target_link_libraries(executable Foo::foo) + +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +find_package(Bar MODULE REQUIRED) +include_directories(${Bar_INCLUDE_DIRS}) +target_link_libraries(executable ${Bar_LIBRARIES}) + +install(TARGETS executable DESTINATION bin) + +if(NOT WIN32) + find_path(IGNORED_INCLUDE_DIR ignored.h) + if (IGNORED_INCLUDE_DIR) + message(SEND_ERROR "Should not find this file. The search path should be excluded.") + endif() +endif() diff --git a/Tests/StagingPrefix/Consumer/cmake/FindBar.cmake b/Tests/StagingPrefix/Consumer/cmake/FindBar.cmake new file mode 100644 index 0000000..29e4478 --- /dev/null +++ b/Tests/StagingPrefix/Consumer/cmake/FindBar.cmake @@ -0,0 +1,6 @@ + +find_path(_inc_prefix bar.h PATH_SUFFIXES bar) +set(Bar_INCLUDE_DIRS ${_inc_prefix}) + +find_library(Bar_LIBRARY bar) +set(Bar_LIBRARIES ${Bar_LIBRARY}) diff --git a/Tests/StagingPrefix/Consumer/main.cpp b/Tests/StagingPrefix/Consumer/main.cpp new file mode 100644 index 0000000..612ee05 --- /dev/null +++ b/Tests/StagingPrefix/Consumer/main.cpp @@ -0,0 +1,10 @@ + +#include "foo.h" +#include "bar.h" + +int main(int, char **) +{ + Foo f; + Bar b; + return f.foo() + b.bar(); +} diff --git a/Tests/StagingPrefix/Producer/CMakeLists.txt b/Tests/StagingPrefix/Producer/CMakeLists.txt new file mode 100644 index 0000000..eb3d98f --- /dev/null +++ b/Tests/StagingPrefix/Producer/CMakeLists.txt @@ -0,0 +1,26 @@ + +cmake_minimum_required (VERSION 2.8.12) +project(Producer) + +add_library(foo SHARED foo.cpp) + +install(TARGETS foo EXPORT fooTargets + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + INCLUDES DESTINATION include/foo +) +install(FILES foo.h DESTINATION include/foo) +install(EXPORT fooTargets + FILE FooConfig.cmake + NAMESPACE Foo:: + DESTINATION lib/cmake/Foo +) + +add_library(bar SHARED bar.cpp) +install(TARGETS bar + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) +install(FILES bar.h DESTINATION include/bar) diff --git a/Tests/StagingPrefix/Producer/bar.cpp b/Tests/StagingPrefix/Producer/bar.cpp new file mode 100644 index 0000000..6bb8abe --- /dev/null +++ b/Tests/StagingPrefix/Producer/bar.cpp @@ -0,0 +1,7 @@ + +#include "bar.h" + +int Bar::bar() +{ + return 0; +} diff --git a/Tests/StagingPrefix/Producer/bar.h b/Tests/StagingPrefix/Producer/bar.h new file mode 100644 index 0000000..acd1fae --- /dev/null +++ b/Tests/StagingPrefix/Producer/bar.h @@ -0,0 +1,10 @@ + +class +#ifdef _WIN32 +__declspec(dllexport) +#endif +Bar +{ +public: + int bar(); +}; diff --git a/Tests/StagingPrefix/Producer/foo.cpp b/Tests/StagingPrefix/Producer/foo.cpp new file mode 100644 index 0000000..64ad7cd --- /dev/null +++ b/Tests/StagingPrefix/Producer/foo.cpp @@ -0,0 +1,7 @@ + +#include "foo.h" + +int Foo::foo() +{ + return 0; +} diff --git a/Tests/StagingPrefix/Producer/foo.h b/Tests/StagingPrefix/Producer/foo.h new file mode 100644 index 0000000..614093d --- /dev/null +++ b/Tests/StagingPrefix/Producer/foo.h @@ -0,0 +1,10 @@ + +class +#ifdef _WIN32 +__declspec(dllexport) +#endif +Foo +{ +public: + int foo(); +}; diff --git a/Tests/StagingPrefix/main.cpp b/Tests/StagingPrefix/main.cpp new file mode 100644 index 0000000..341aaaf --- /dev/null +++ b/Tests/StagingPrefix/main.cpp @@ -0,0 +1,5 @@ + +int main(int, char **) +{ + return 0; +} |