From 85a945a607d5c417e780afed98868366fcfd8fae Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 2 Jul 2020 06:49:52 -0400 Subject: Restore handling of build directory inside a symlinked path In commit dd8365b3f1 (Merge branch 'upstream-KWSys' into update-kwsys, 2020-04-06, v3.18.0-rc1~397^2) we imported KWSys commit `019afb6ea` (SystemTools: Drop GetCurrentWorkingDirectory 'collapse' argument, 2020-04-03). That caused `GetCurrentWorkingDirectory` to no longer send paths through the KWSys translation map and broke CMake's detection of the absolute path to a build directory containing a symbolic link. Add our own `cmSystemTools::GetCurrentWorkingDirectory` wrapper around the KWSys method in order to restore that mapping. Test-case-by: Ben Boeckel Issue: #16228 Fixes: #20900 --- Source/CPack/cpack.cxx | 2 +- Source/cmSystemTools.cxx | 6 ++++ Source/cmSystemTools.h | 3 ++ Tests/RunCMake/CMakeLists.txt | 4 +++ Tests/RunCMake/SymlinkTrees/CMakeLists.txt | 3 ++ Tests/RunCMake/SymlinkTrees/PrintTrees.cmake | 6 ++++ Tests/RunCMake/SymlinkTrees/RunCMakeTest.cmake | 34 ++++++++++++++++++++++ .../SymlinkTrees/common_symlinks-stdout.txt | 4 +++ Tests/RunCMake/SymlinkTrees/common_symlinks.cmake | 1 + 9 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/SymlinkTrees/CMakeLists.txt create mode 100644 Tests/RunCMake/SymlinkTrees/PrintTrees.cmake create mode 100644 Tests/RunCMake/SymlinkTrees/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/SymlinkTrees/common_symlinks-stdout.txt create mode 100644 Tests/RunCMake/SymlinkTrees/common_symlinks.cmake diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 2e5bde2..3a400b7 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -312,7 +312,7 @@ int main(int argc, char const* const* argv) // The value has not been set on the command line else { // get a default value (current working directory) - cpackProjectDirectory = cmsys::SystemTools::GetCurrentWorkingDirectory(); + cpackProjectDirectory = cmSystemTools::GetCurrentWorkingDirectory(); // use default value if no value has been provided by the config file if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) { globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index be799b0..39de13f 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2080,6 +2080,12 @@ std::string const& cmSystemTools::GetCMakeRoot() return cmSystemToolsCMakeRoot; } +std::string cmSystemTools::GetCurrentWorkingDirectory() +{ + return cmSystemTools::CollapseFullPath( + cmsys::SystemTools::GetCurrentWorkingDirectory()); +} + void cmSystemTools::MakefileColorEcho(int color, const char* message, bool newline, bool enabled) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index ee149a0..b886c58 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -390,6 +390,9 @@ public: static std::string const& GetCMClDepsCommand(); static std::string const& GetCMakeRoot(); + /** Get the CWD mapped through the KWSys translation map. */ + static std::string GetCurrentWorkingDirectory(); + /** Echo a message in color using KWSys's Terminal cprintf. */ static void MakefileColorEcho(int color, const char* message, bool newLine, bool enabled); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 830566e..36409d8 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -436,6 +436,10 @@ else() message(STATUS "Could not find ctresalloc") endif() +if(NOT WIN32) + add_RunCMake_test(SymlinkTrees) +endif () + find_package(Qt4 QUIET) find_package(Qt5Core QUIET) if (QT4_FOUND AND Qt5Core_FOUND AND NOT Qt5Core_VERSION VERSION_LESS 5.1.0) diff --git a/Tests/RunCMake/SymlinkTrees/CMakeLists.txt b/Tests/RunCMake/SymlinkTrees/CMakeLists.txt new file mode 100644 index 0000000..d6fea2c --- /dev/null +++ b/Tests/RunCMake/SymlinkTrees/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.12) +project(${RunCMake_TEST} NONE) +include("${include_dir}/${RunCMake_TEST}.cmake") diff --git a/Tests/RunCMake/SymlinkTrees/PrintTrees.cmake b/Tests/RunCMake/SymlinkTrees/PrintTrees.cmake new file mode 100644 index 0000000..aa99127 --- /dev/null +++ b/Tests/RunCMake/SymlinkTrees/PrintTrees.cmake @@ -0,0 +1,6 @@ +message(STATUS "source: '${CMAKE_SOURCE_DIR}'") +message(STATUS "binary: '${CMAKE_BINARY_DIR}'") +get_filename_component(real_source "${CMAKE_SOURCE_DIR}" REALPATH) +get_filename_component(real_binary "${CMAKE_BINARY_DIR}" REALPATH) +message(STATUS "real source: '${real_source}'") +message(STATUS "real binary: '${real_binary}'") diff --git a/Tests/RunCMake/SymlinkTrees/RunCMakeTest.cmake b/Tests/RunCMake/SymlinkTrees/RunCMakeTest.cmake new file mode 100644 index 0000000..e5f1f7f --- /dev/null +++ b/Tests/RunCMake/SymlinkTrees/RunCMakeTest.cmake @@ -0,0 +1,34 @@ +include(RunCMake) + +# This function assumes that ``${RunCMake_BINARY_DIR}/${name}/source`` and +# ``${RunCMake_BINARY_DIR}/${name}/binary`` are set up properly prior to +# calling it. +function (run_symlink_test name) + set(RunCMake_TEST_NO_CLEAN TRUE) + configure_file( + "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt" + "${RunCMake_BINARY_DIR}/${name}/source/CMakeLists.txt" + COPYONLY) + set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}/source") + set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${name}/binary") + # Emulate a shell using this directory. + set(ENV{PWD} "${RunCMake_TEST_BINARY_DIR}") + set(RunCMake_TEST_OPTIONS + "-Dinclude_dir:PATH=${CMAKE_CURRENT_LIST_DIR}") + run_cmake("${name}_symlinks") +endfunction () + +# Create the following structure: +# +# .../common_real/source +# .../common_real/binary +# .../common -> common_real +# +# In this case, CMake should act as if .../common *is* .../common_real for all +# computations except ``REALPATH``. This supports the case where a system has +# a stable *symlink*, but not a stable target for that symlink. +file(REMOVE_RECURSE "${RunCMake_BINARY_DIR}/common_real") +file(REMOVE "${RunCMake_BINARY_DIR}/common") +file(MAKE_DIRECTORY "${RunCMake_BINARY_DIR}/common_real/source") +file(CREATE_LINK "common_real" "${RunCMake_BINARY_DIR}/common" SYMBOLIC) +run_symlink_test(common) diff --git a/Tests/RunCMake/SymlinkTrees/common_symlinks-stdout.txt b/Tests/RunCMake/SymlinkTrees/common_symlinks-stdout.txt new file mode 100644 index 0000000..bb04450 --- /dev/null +++ b/Tests/RunCMake/SymlinkTrees/common_symlinks-stdout.txt @@ -0,0 +1,4 @@ +-- source: '[^']*/Tests/RunCMake/SymlinkTrees/common/source' +-- binary: '[^']*/Tests/RunCMake/SymlinkTrees/common/binary' +-- real source: '[^']*/Tests/RunCMake/SymlinkTrees/common_real/source' +-- real binary: '[^']*/Tests/RunCMake/SymlinkTrees/common_real/binary' diff --git a/Tests/RunCMake/SymlinkTrees/common_symlinks.cmake b/Tests/RunCMake/SymlinkTrees/common_symlinks.cmake new file mode 100644 index 0000000..5eafe26 --- /dev/null +++ b/Tests/RunCMake/SymlinkTrees/common_symlinks.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/PrintTrees.cmake") -- cgit v0.12