From 9e84c7c5e8e243624858692bddb6f13485f46774 Mon Sep 17 00:00:00 2001 From: Dennis Klein Date: Mon, 27 May 2019 22:00:43 +0200 Subject: cmInstallTargetGenerator: Introduce CMP0095 Escape coincidental CMake syntax in RPATH entries when generating the intermediary cmake_install.cmake script. Fixes #19225 --- Help/manual/cmake-policies.7.rst | 1 + Help/policy/CMP0095.rst | 30 +++++++++ Help/release/dev/CMP0095.rst | 5 ++ Source/cmInstallTargetGenerator.cxx | 76 +++++++++++++++++++--- Source/cmInstallTargetGenerator.h | 1 + Source/cmPolicies.h | 9 ++- .../RunCMake/TargetPolicies/PolicyList-stderr.txt | 1 + ...le-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake | 3 +- .../file-GET_RUNTIME_DEPENDENCIES-linux.cmake | 9 +-- 9 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 Help/policy/CMP0095.rst create mode 100644 Help/release/dev/CMP0095.rst diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 1d023cb..bac1c6c 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.15 .. toctree:: :maxdepth: 1 + CMP0095: RPATH entries are properly escaped in the intermediary CMake install script. CMP0094: FindPython3, FindPython2 and FindPython use LOCATION for lookup strategy. CMP0093: FindBoost reports Boost_VERSION in x.y.z format. CMP0092: MSVC warning flags are not in CMAKE_{C,CXX}_FLAGS by default. diff --git a/Help/policy/CMP0095.rst b/Help/policy/CMP0095.rst new file mode 100644 index 0000000..4c56a05 --- /dev/null +++ b/Help/policy/CMP0095.rst @@ -0,0 +1,30 @@ +CMP0095 +------- + +``RPATH`` entries are properly escaped in the intermediary CMake install script. + +In CMake 3.15 and earlier, ``RPATH`` entries set via +:variable:`CMAKE_INSTALL_RPATH` or via :prop_tgt:`INSTALL_RPATH` have not been +escaped before being inserted into the ``cmake_install.cmake`` script. Dynamic +linkers on ELF-based systems (e.g. Linux and FreeBSD) allow certain keywords in +``RPATH`` entries, such as ``${ORIGIN}`` (More details are available in the +``ld.so`` man pages on those systems). The syntax of these keywords can match +CMake's variable syntax. In order to not be substituted (usually to an empty +string) already by the intermediary ``cmake_install.cmake`` script, the user had +to double-escape such ``RPATH`` keywords, e.g. +``set(CMAKE_INSTALL_RPATH "\\\${ORIGIN}/../lib")``. Since the intermediary +``cmake_install.cmake`` script is an implementation detail of CMake, CMake 3.16 +and later will make sure ``RPATH`` entries are inserted literally by escaping +any coincidental CMake syntax. + +The ``OLD`` behavior of this policy is to not escape ``RPATH`` entries in the +intermediary ``cmake_install.cmake`` script. The ``NEW`` behavior is to properly +escape coincidental CMake syntax in ``RPATH`` entries when generating the +intermediary ``cmake_install.cmake`` script. + +This policy was introduced in CMake version 3.16. CMake version |release| warns +when the policy is not set and detected usage of CMake-like syntax and uses +``OLD`` behavior. Use the :command:`cmake_policy` command to set it to ``OLD`` +or ``NEW`` explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/CMP0095.rst b/Help/release/dev/CMP0095.rst new file mode 100644 index 0000000..21d0550 --- /dev/null +++ b/Help/release/dev/CMP0095.rst @@ -0,0 +1,5 @@ +CMP0095 +------- + +* ``RPATH`` entries are properly escaped in the intermediary CMake install script. + See policy :policy:`CMP0095`. diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 7c5a55b..0e2f9c5 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -16,6 +16,8 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmOutputConverter.h" +#include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -632,17 +634,34 @@ void cmInstallTargetGenerator::AddRPathCheckRule( return; } - // Get the install RPATH from the link information. - std::string newRpath = cli->GetChrpathString(); - // Write a rule to remove the installed file if its rpath is not the // new rpath. This is needed for existing build/install trees when // the installed rpath changes but the file is not rebuilt. - /* clang-format off */ os << indent << "file(RPATH_CHECK\n" - << indent << " FILE \"" << toDestDirPath << "\"\n" - << indent << " RPATH \"" << newRpath << "\")\n"; - /* clang-format on */ + << indent << " FILE \"" << toDestDirPath << "\"\n"; + + // CMP0095: ``RPATH`` entries are properly escaped in the intermediary + // CMake install script. + switch (this->Target->GetPolicyStatusCMP0095()) { + case cmPolicies::WARN: + // No author warning needed here, we warn later in + // cmInstallTargetGenerator::AddChrpathPatchRule(). + CM_FALLTHROUGH; + case cmPolicies::OLD: { + // Get the install RPATH from the link information. + std::string newRpath = cli->GetChrpathString(); + os << indent << " RPATH \"" << newRpath << "\")\n"; + break; + } + default: { + // Get the install RPATH from the link information and + // escape any CMake syntax in the install RPATH. + std::string escapedNewRpath = + cmOutputConverter::EscapeForCMake(cli->GetChrpathString()); + os << indent << " RPATH " << escapedNewRpath << ")\n"; + break; + } + } } void cmInstallTargetGenerator::AddChrpathPatchRule( @@ -731,11 +750,27 @@ void cmInstallTargetGenerator::AddChrpathPatchRule( return; } + // Escape any CMake syntax in the install RPATH. + std::string escapedNewRpath = cmOutputConverter::EscapeForCMake(newRpath); + // Write a rule to run chrpath to set the install-tree RPATH os << indent << "file(RPATH_CHANGE\n" << indent << " FILE \"" << toDestDirPath << "\"\n" - << indent << " OLD_RPATH \"" << oldRpath << "\"\n" - << indent << " NEW_RPATH \"" << newRpath << "\")\n"; + << indent << " OLD_RPATH \"" << oldRpath << "\"\n"; + + // CMP0095: ``RPATH`` entries are properly escaped in the intermediary + // CMake install script. + switch (this->Target->GetPolicyStatusCMP0095()) { + case cmPolicies::WARN: + this->IssueCMP0095Warning(newRpath); + CM_FALLTHROUGH; + case cmPolicies::OLD: + os << indent << " NEW_RPATH \"" << newRpath << "\")\n"; + break; + default: + os << indent << " NEW_RPATH " << escapedNewRpath << ")\n"; + break; + } } } @@ -838,3 +873,26 @@ void cmInstallTargetGenerator::AddUniversalInstallRule( << "\"" << this->Target->Target->GetName() << "\" " << "\"" << toDestDirPath << "\")\n"; } + +void cmInstallTargetGenerator::IssueCMP0095Warning( + const std::string& unescapedRpath) +{ + // Reduce warning noise to cases where used RPATHs may actually be affected + // by CMP0095. This filter is meant to skip warnings in cases when + // non-curly-braces syntax (e.g. $ORIGIN) or no keyword is used which has + // worked already before CMP0095. We intend to issue a warning in all cases + // with curly-braces syntax, even if the workaround of double-escaping is in + // place, since we deprecate the need for it with CMP0095. + const bool potentially_affected(unescapedRpath.find("${") != + std::string::npos); + + if (potentially_affected) { + std::ostringstream w; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0095) << "\n"; + w << "RPATH entries for target '" << this->Target->GetName() << "' " + << "will not be escaped in the intermediary " + << "cmake_install.cmake script."; + this->Target->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( + MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace()); + } +} diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index ed3ab52..9ccad63 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -104,6 +104,7 @@ protected: const std::string& toDestDirPath); void AddUniversalInstallRule(std::ostream& os, Indent indent, const std::string& toDestDirPath); + void IssueCMP0095Warning(const std::string& unescapedRpath); std::string TargetName; cmGeneratorTarget* Target; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index b705119..c16a46f 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -279,7 +279,11 @@ class cmMakefile; SELECT(POLICY, CMP0094, \ "FindPython3, FindPython2 and FindPyton use " \ "LOCATION for lookup strategy.", \ - 3, 15, 0, cmPolicies::WARN) + 3, 15, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0095, \ + "RPATH entries are properly escaped in the intermediary CMake " \ + "install script.", \ + 3, 16, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -307,7 +311,8 @@ class cmMakefile; F(CMP0073) \ F(CMP0076) \ F(CMP0081) \ - F(CMP0083) + F(CMP0083) \ + F(CMP0095) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt index 0bcf886..6d72fac 100644 --- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -27,6 +27,7 @@ \* CMP0076 \* CMP0081 \* CMP0083 + \* CMP0095 Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake index 6e718f8..6567438 100644 --- a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake @@ -1,4 +1,5 @@ enable_language(C) +cmake_policy(SET CMP0095 NEW) file(WRITE "${CMAKE_BINARY_DIR}/test.c" "void test(void) {}\n") file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[extern void test(void); @@ -13,7 +14,7 @@ int main(void) add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c") add_executable(exe "${CMAKE_BINARY_DIR}/main.c") target_link_libraries(exe PRIVATE test) -set_property(TARGET exe PROPERTY INSTALL_RPATH "\\\${ORIGIN}/../lib") +set_property(TARGET exe PROPERTY INSTALL_RPATH "\${ORIGIN}/../lib") install(TARGETS exe DESTINATION bin) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake index 433dd3b..bd0f9f1 100644 --- a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake @@ -1,4 +1,5 @@ enable_language(C) +cmake_policy(SET CMP0095 NEW) set(test_rpath_names preexcluded @@ -52,8 +53,8 @@ target_link_libraries(test_rpath PRIVATE ${test_rpath_names}) set_property(TARGET test_rpath PROPERTY INSTALL_RPATH "${CMAKE_BINARY_DIR}/root-all/lib/rpath_postexcluded" "${CMAKE_BINARY_DIR}/root-all/lib/rpath" - "\\\$ORIGIN/rpath_origin_postexcluded" - "\\\${ORIGIN}/rpath_origin" # This must be double-escaped because of issue #19225. + "\$ORIGIN/rpath_origin_postexcluded" + "\${ORIGIN}/rpath_origin" "${CMAKE_BINARY_DIR}/root-all/lib/conflict" ) target_link_options(test_rpath PRIVATE -Wl,--disable-new-dtags) @@ -88,8 +89,8 @@ set_property(TARGET test_runpath PROPERTY INSTALL_RPATH "${CMAKE_BINARY_DIR}/root-all/lib/runpath/../rpath" # Ensure that files that don't conflict are treated correctly "${CMAKE_BINARY_DIR}/root-all/lib/runpath_postexcluded" "${CMAKE_BINARY_DIR}/root-all/lib/runpath" - "\\\${ORIGIN}/runpath_origin_postexcluded" # This must be double-escaped because of issue #19225. - "\\\$ORIGIN/runpath_origin" + "\${ORIGIN}/runpath_origin_postexcluded" + "\$ORIGIN/runpath_origin" "${CMAKE_BINARY_DIR}/root-all/lib/conflict2" ) target_link_options(test_runpath PRIVATE -Wl,--enable-new-dtags) -- cgit v0.12 From 749ce48eb5b2876b347115a857839fdf9c24a221 Mon Sep 17 00:00:00 2001 From: Dennis Klein Date: Fri, 31 May 2019 16:43:24 +0200 Subject: cmInstallTargetGenerator: Escape generated OLD_RPATH argument On some platforms, e.g. most ELF-based ones, RPATHs may contain keywords that match CMake's variable syntax. To prevent them from being falsely substituted when running the cmake_install.cmake script CMake syntax needs to be escaped. --- Source/cmInstallTargetGenerator.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 0e2f9c5..0774436 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -750,13 +750,14 @@ void cmInstallTargetGenerator::AddChrpathPatchRule( return; } - // Escape any CMake syntax in the install RPATH. + // Escape any CMake syntax in the RPATHs. + std::string escapedOldRpath = cmOutputConverter::EscapeForCMake(oldRpath); std::string escapedNewRpath = cmOutputConverter::EscapeForCMake(newRpath); // Write a rule to run chrpath to set the install-tree RPATH os << indent << "file(RPATH_CHANGE\n" << indent << " FILE \"" << toDestDirPath << "\"\n" - << indent << " OLD_RPATH \"" << oldRpath << "\"\n"; + << indent << " OLD_RPATH " << escapedOldRpath << "\n"; // CMP0095: ``RPATH`` entries are properly escaped in the intermediary // CMake install script. -- cgit v0.12 From 4caefbb42369cf652df920edd07ee9e81eb95577 Mon Sep 17 00:00:00 2001 From: Dennis Klein Date: Thu, 13 Jun 2019 16:40:01 +0200 Subject: cmInstallTargetGenerator: Add tests for the RPATH_CHANGE rule --- Tests/RunCMake/CMakeLists.txt | 7 ++- Tests/RunCMake/install/RunCMakeTest.cmake | 16 +++++ .../TARGETS-FILE_RPATH_CHANGE-check-common.cmake | 30 +++++++++ ...TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake | 63 +++++++++++++++++++ .../TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt | 23 +++++++ .../TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake | 72 ++++++++++++++++++++++ ...TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake | 15 +++++ .../TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake | 18 ++++++ 8 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake create mode 100644 Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake create mode 100644 Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake create mode 100644 Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake create mode 100644 Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 075676a..d5ac7e0 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -408,7 +408,12 @@ else() set(NO_NAMELINK 0) endif() -add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) +add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} + -DCMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN=${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN} + -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} + -DCMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG=${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG} + -DCMAKE_EXECUTABLE_FORMAT=${CMAKE_EXECUTABLE_FORMAT}) + add_RunCMake_test(CPackCommandLine) add_RunCMake_test(CPackConfig) add_RunCMake_test(CPackInstallProperties) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 026148e..21c320b 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -48,6 +48,22 @@ in directory: endif() endfunction() +# Wrapper for run_cmake() that skips platforms that are non-ELF or have no RPATH support +function(run_cmake_ELFRPATH_only case) + if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + run_cmake(${case}) + else() + # Sanity check against a platform known to be ELF-based + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(FATAL_ERROR "Expected platform Linux to advertize itself as ELF-based, but it did not.") + else() + message(STATUS "${case} - SKIPPED (No ELF-based platform found)") + endif() + endif() +endfunction() + +run_cmake(TARGETS-FILE_RPATH_CHANGE-old_rpath) +run_cmake_ELFRPATH_only(TARGETS-FILE_RPATH_CHANGE-new_rpath) run_cmake(DIRECTORY-MESSAGE_NEVER) run_cmake(DIRECTORY-PATTERN-MESSAGE_NEVER) run_cmake(DIRECTORY-message) diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake new file mode 100644 index 0000000..673fdde --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake @@ -0,0 +1,30 @@ +file(READ ${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake install_script) +#message(STATUS ${install_script}) + +set(wsnl " *[\n\r]+ *") # whitespace + single newline + whitespace +set(wssl " *[\n\r]+[^\n\r]*[\n\r]+ *") # ws nl skipline nl ws +string(CONCAT prefix [[file\(RPATH_CHANGE]]) +set(_msg "cmake_install.cmake does not match ") + +macro(check) + if(NOT install_script MATCHES "${regex}") + message(STATUS "${test} - check \"${target}\" - FAILED:") + string(CONCAT RunCMake_TEST_FAILED "${_msg}" ">>>${regex}<<<") + return() + else() + message(STATUS "${test} - check \"${target}\" - PASSED") + endif() +endmacro() + +macro(skip_without_rpath_change_rule) +# Not all platforms generate a file(RPATH_CHANGE) rule + if(NOT install_script MATCHES [[file\(RPATH_CHANGE]]) + # Sanity check against a platform known to generate a file(RPATH_CHANGE) rule + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(FATAL_ERROR "Expected generated file(RPATH_CHANGE) rule on platform Linux.") + else() + message(STATUS "${test} - All checks skipped. No file(RPATH_CHANGE) rule found on this platform.") + return() + endif() + endif() +endmacro() diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake new file mode 100644 index 0000000..930ef70 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake @@ -0,0 +1,63 @@ +include(${RunCMake_SOURCE_DIR}/TARGETS-FILE_RPATH_CHANGE-check-common.cmake) +skip_without_rpath_change_rule() +string(APPEND prefix "${wsnl}" [[FILE "[^"]*/]]) + +set(target "exe1_cmp0095_old") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar]]) +check() + +set(target "exe1_cmp0095_warn") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar]]) +check() + +set(target "exe1_cmp0095_new") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar]]) +check() + +set(target "exe2_cmp0095_old") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\$ORIGIN/../lib]]) +check() + +set(target "exe2_cmp0095_warn") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\$ORIGIN/../lib]]) +check() + +set(target "exe2_cmp0095_new") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\\\$ORIGIN/../lib]]) +check() + +set(target "exe3_cmp0095_old") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\${ORIGIN}/../lib]]) +check() + +set(target "exe3_cmp0095_warn") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\${ORIGIN}/../lib]]) +check() + +set(target "exe3_cmp0095_new") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\\\${ORIGIN}/../lib]]) +check() + +set(target "exe4_cmp0095_old") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar/\${PLATFORM}]]) +check() + +set(target "exe4_cmp0095_warn") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar/\${PLATFORM}]]) +check() + +set(target "exe4_cmp0095_new") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar/\\\${PLATFORM}]]) +check() diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt new file mode 100644 index 0000000..1e123f6 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt @@ -0,0 +1,23 @@ +^CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\): + Policy CMP0095 is not set: RPATH entries are properly escaped in the + intermediary CMake install script\. Run "cmake --help-policy CMP0095" for + policy details\. Use the cmake_policy command to set the policy and + suppress this warning\. + + RPATH entries for target 'exe3_cmp0095_warn' will not be escaped in the + intermediary cmake_install\.cmake script\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\): + Policy CMP0095 is not set: RPATH entries are properly escaped in the + intermediary CMake install script\. Run "cmake --help-policy CMP0095" for + policy details\. Use the cmake_policy command to set the policy and + suppress this warning\. + + RPATH entries for target 'exe4_cmp0095_warn' will not be escaped in the + intermediary cmake_install\.cmake script\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake new file mode 100644 index 0000000..cba04b2 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake @@ -0,0 +1,72 @@ +cmake_minimum_required(VERSION 3.14) +enable_language(C) + +# test matrix +# +# A := +# | no cmake syntax | cmake syntax | +# -----------------------+-----------------+--------------+ +# absolute install RPATH | exe1 | exe4 | +# relative install RPATH | exe2 | exe3 | +# +# all := A * CMP005_OLD + A * CMP0095_WARN + A * CMP0095_NEW + +add_library(utils SHARED obj1.c) +set(targets utils) + +set(exe1_install_rpath "/foo/bar") +set(exe2_install_rpath "\$ORIGIN/../lib") +set(exe3_install_rpath "\${ORIGIN}/../lib") +set(exe4_install_rpath "/foo/bar/\${PLATFORM}") + +macro(A_CMP0095 policy_value) + cmake_policy(PUSH) + if(NOT "x${policy_value}x" STREQUAL "xWARNx") + cmake_policy(SET CMP0095 ${policy_value}) + endif() + string(TOLOWER "${policy_value}" p) + + # exe1: absolute install RPATH, no cmake syntax + set(case "exe1") + set(target "${case}_cmp0095_${p}") + list(APPEND targets ${target}) + add_executable(${target} main.c) + target_link_libraries(${target} PRIVATE utils) + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "${${case}_install_rpath}") + + # exe2: relative install RPATH, no cmake syntax + set(case "exe2") + set(target "${case}_cmp0095_${p}") + list(APPEND targets ${target}) + add_executable(${target} main.c) + target_link_libraries(${target} PRIVATE utils) + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "${${case}_install_rpath}") + + # exe3: relative install RPATH, cmake syntax + set(case "exe3") + set(target "${case}_cmp0095_${p}") + list(APPEND targets ${target}) + add_executable(${target} main.c) + target_link_libraries(${target} PRIVATE utils) + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "${${case}_install_rpath}") + + # exe4: absolute install RPATH, cmake syntax + set(case "exe4") + set(target "${case}_cmp0095_${p}") + list(APPEND targets ${target}) + add_executable(${target} main.c) + target_link_libraries(${target} PRIVATE utils) + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "${${case}_install_rpath}") + + cmake_policy(POP) +endmacro() + +A_CMP0095("OLD") +A_CMP0095("WARN") # exe3 and exe4 are expected to issue an author warning +A_CMP0095("NEW") + +install(TARGETS ${targets}) diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake new file mode 100644 index 0000000..814f405 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake @@ -0,0 +1,15 @@ +include(${RunCMake_SOURCE_DIR}/TARGETS-FILE_RPATH_CHANGE-check-common.cmake) +skip_without_rpath_change_rule() +string(APPEND prefix "${wsnl}" [[FILE "[^"]*/]]) + +set(target "exe1") +string(CONCAT regex "${prefix}${target}\"${wsnl}" + [[OLD_RPATH "]] "${RunCMake_BINARY_DIR}") +check() + +if("x${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN}" STREQUAL "x\$ORIGIN") + set(target "exe2") + string(CONCAT regex "${prefix}${target}\"${wsnl}" + [[OLD_RPATH "\\\$ORIGIN]]) + check() +endif() diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake new file mode 100644 index 0000000..43ae787 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.14) +enable_language(C) + +add_library(utils SHARED obj1.c) + +# exe1: absolute build RPATH, no cmake syntax +set(CMAKE_BUILD_RPATH_USE_ORIGIN OFF) +set(CMAKE_INSTALL_RPATH "/foo/bar") +add_executable(exe1 main.c) +target_link_libraries(exe1 PRIVATE utils) + +# exe2: relative build RPATH, no cmake syntax +set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) +set(CMAKE_INSTALL_RPATH "/foo/bar") +add_executable(exe2 main.c) +target_link_libraries(exe2 PRIVATE utils) + +install(TARGETS utils exe1 exe2) -- cgit v0.12