소스 검색

Introduce CMAKE_STAGING_PREFIX variable.

This variable can be useful in cross-compiling contexts where the
sysroot is read-only or where the sysroot should otherwise remain
pristine.

If the new CMAKE_STAGING_PREFIX variable is set, it is used instead
of CMAKE_INSTALL_PREFIX when generating the installation rules in
cmake_install.cmake.

This way, the CMAKE_INSTALL_PREFIX variable
always refers to the installation prefix on the target device, regardless
of whether host==target.

If any -rpath paths passed to the linker contain the CMAKE_STAGING_PREFIX,
the matching path fragments are replaced with the CMAKE_INSTALL_PREFIX.
Matching paths in the -rpath-link are not transformed.

The cross-prefix usr-move workaround is assumed not to require extension
regarding CMAKE_STAGING_PREFIX. The staging area is a single prefix, so
there is no scope for cross-prefix symlinks. The CMAKE_INSTALL_PREFIX
is still used to determine the workaround path, and that variable
remains the relevant one even if CMAKE_STAGING_PREFIX is used. If the
generated export files are deployed to the target, the workaround
will still be in place, and still be employed if required.
Stephen Kelly 12 년 전
부모
커밋
7521da2852

+ 5 - 3
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.

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

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

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

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

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

+ 11 - 0
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"

+ 20 - 0
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);

+ 6 - 1
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;
         }

+ 5 - 0
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;

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

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

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

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

+ 10 - 0
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();
+}

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

+ 7 - 0
Tests/StagingPrefix/Producer/bar.cpp

@@ -0,0 +1,7 @@
+
+#include "bar.h"
+
+int Bar::bar()
+{
+  return 0;
+}

+ 10 - 0
Tests/StagingPrefix/Producer/bar.h

@@ -0,0 +1,10 @@
+
+class
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+Bar
+{
+public:
+  int bar();
+};

+ 7 - 0
Tests/StagingPrefix/Producer/foo.cpp

@@ -0,0 +1,7 @@
+
+#include "foo.h"
+
+int Foo::foo()
+{
+  return 0;
+}

+ 10 - 0
Tests/StagingPrefix/Producer/foo.h

@@ -0,0 +1,10 @@
+
+class
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+Foo
+{
+public:
+  int foo();
+};

+ 5 - 0
Tests/StagingPrefix/main.cpp

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