From ffc06c12397e7cda7307afcfc8a79ebda4a786a6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 18 Feb 2015 10:54:45 -0500 Subject: [PATCH] Teach find_(library|file|path) to get prefixes from PATH (#15370) The find_package command already knows how to compute installation prefixes from PATH. Use the same approach to establish prefixes for find_library, find_file, and find_path to use to look in directories like "/lib[/]" and "/include" for libraries and headers. This will reduce the amount of configuration end users need to do to establish a work environment rooted under a specific prefix. --- Help/command/FIND_XXX.txt | 4 ++++ Help/command/find_file.rst | 5 ++++- Help/command/find_library.rst | 5 ++++- Help/command/find_path.rst | 5 ++++- .../dev/find-command-prefix-from-PATH.rst | 6 +++++ Source/cmFindBase.cxx | 1 + Source/cmSearchPath.cxx | 22 ++++++++++++++++++- Source/cmSearchPath.h | 2 +- Tests/RunCMake/CMakeLists.txt | 2 ++ Tests/RunCMake/find_file/CMakeLists.txt | 3 +++ .../find_file/PrefixInPATH-stdout.txt | 4 ++++ Tests/RunCMake/find_file/PrefixInPATH.cmake | 8 +++++++ Tests/RunCMake/find_file/RunCMakeTest.cmake | 3 +++ .../RunCMake/find_file/include/PrefixInPATH.h | 0 .../find_library/PrefixInPATH-stdout.txt | 4 ++++ .../RunCMake/find_library/PrefixInPATH.cmake | 11 ++++++++++ .../RunCMake/find_library/RunCMakeTest.cmake | 1 + .../find_library/lib/libPrefixInPATH.a | 0 Tests/RunCMake/find_path/CMakeLists.txt | 3 +++ .../find_path/PrefixInPATH-stdout.txt | 4 ++++ Tests/RunCMake/find_path/PrefixInPATH.cmake | 8 +++++++ Tests/RunCMake/find_path/RunCMakeTest.cmake | 3 +++ .../RunCMake/find_path/include/PrefixInPATH.h | 0 23 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 Help/release/dev/find-command-prefix-from-PATH.rst create mode 100644 Tests/RunCMake/find_file/CMakeLists.txt create mode 100644 Tests/RunCMake/find_file/PrefixInPATH-stdout.txt create mode 100644 Tests/RunCMake/find_file/PrefixInPATH.cmake create mode 100644 Tests/RunCMake/find_file/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/find_file/include/PrefixInPATH.h create mode 100644 Tests/RunCMake/find_library/PrefixInPATH-stdout.txt create mode 100644 Tests/RunCMake/find_library/PrefixInPATH.cmake create mode 100644 Tests/RunCMake/find_library/lib/libPrefixInPATH.a create mode 100644 Tests/RunCMake/find_path/CMakeLists.txt create mode 100644 Tests/RunCMake/find_path/PrefixInPATH-stdout.txt create mode 100644 Tests/RunCMake/find_path/PrefixInPATH.cmake create mode 100644 Tests/RunCMake/find_path/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/find_path/include/PrefixInPATH.h diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index 5889e9009..935832930 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -53,6 +53,10 @@ If NO_DEFAULT_PATH is not specified, the search process is as follows: .. |CMAKE_PREFIX_PATH_XXX_SUBDIR| replace:: /|XXX_SUBDIR| for each in CMAKE_PREFIX_PATH +.. |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR| replace:: + /|XXX_SUBDIR| for each /[s]bin in PATH, and + /|XXX_SUBDIR| for other entries in PATH + .. |CMAKE_SYSTEM_PREFIX_PATH_XXX_SUBDIR| replace:: /|XXX_SUBDIR| for each in CMAKE_SYSTEM_PREFIX_PATH diff --git a/Help/command/find_file.rst b/Help/command/find_file.rst index db7e1518e..be309a530 100644 --- a/Help/command/find_file.rst +++ b/Help/command/find_file.rst @@ -13,7 +13,10 @@ find_file .. |CMAKE_XXX_PATH| replace:: CMAKE_INCLUDE_PATH .. |CMAKE_XXX_MAC_PATH| replace:: CMAKE_FRAMEWORK_PATH -.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: PATH and INCLUDE +.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: Directories in INCLUDE, + /include/ if CMAKE_LIBRARY_ARCHITECTURE is set, and + |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|, + and the directories in PATH itself. .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace:: /include/ if CMAKE_LIBRARY_ARCHITECTURE is set, and diff --git a/Help/command/find_library.rst b/Help/command/find_library.rst index 91342bad3..09df6888f 100644 --- a/Help/command/find_library.rst +++ b/Help/command/find_library.rst @@ -13,7 +13,10 @@ find_library .. |CMAKE_XXX_PATH| replace:: CMAKE_LIBRARY_PATH .. |CMAKE_XXX_MAC_PATH| replace:: CMAKE_FRAMEWORK_PATH -.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: PATH and LIB +.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: Directories in LIB, + /lib/ if CMAKE_LIBRARY_ARCHITECTURE is set, and + |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|, + and the directories in PATH itself. .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace:: /lib/ if CMAKE_LIBRARY_ARCHITECTURE is set, and diff --git a/Help/command/find_path.rst b/Help/command/find_path.rst index 95d49e77a..b5a6e373f 100644 --- a/Help/command/find_path.rst +++ b/Help/command/find_path.rst @@ -13,7 +13,10 @@ find_path .. |CMAKE_XXX_PATH| replace:: CMAKE_INCLUDE_PATH .. |CMAKE_XXX_MAC_PATH| replace:: CMAKE_FRAMEWORK_PATH -.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: PATH and INCLUDE +.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: Directories in INCLUDE, + /include/ if CMAKE_LIBRARY_ARCHITECTURE is set, and + |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|, + and the directories in PATH itself. .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace:: /include/ if CMAKE_LIBRARY_ARCHITECTURE is set, and diff --git a/Help/release/dev/find-command-prefix-from-PATH.rst b/Help/release/dev/find-command-prefix-from-PATH.rst new file mode 100644 index 000000000..f9aae2a93 --- /dev/null +++ b/Help/release/dev/find-command-prefix-from-PATH.rst @@ -0,0 +1,6 @@ +find-command-prefix-from-PATH +----------------------------- + +* The :command:`find_library`, :command:`find_path`, and :command:`find_file` + commands now search in installation prefixes derived from the ``PATH`` + environment variable. diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 6e555333d..4336e1c71 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -275,6 +275,7 @@ void cmFindBase::FillSystemEnvironmentPath() if(!this->EnvironmentPath.empty()) { paths.AddEnvPath(this->EnvironmentPath); + paths.AddEnvPrefixPath("PATH", true); } // Add PATH paths.AddEnvPath("PATH"); diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index 861dbf178..1e777ab7a 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -136,10 +136,30 @@ void cmSearchPath::AddCMakePrefixPath(const std::string& variable) } //---------------------------------------------------------------------------- -void cmSearchPath::AddEnvPrefixPath(const std::string& variable) +static std::string cmSearchPathStripBin(std::string const& s) +{ + // If the path is a PREFIX/bin case then add its parent instead. + if((cmHasLiteralSuffix(s, "/bin")) || + (cmHasLiteralSuffix(s, "/sbin"))) + { + return cmSystemTools::GetFilenamePath(s); + } + else + { + return s; + } +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddEnvPrefixPath(const std::string& variable, bool stripBin) { std::vector expanded; cmSystemTools::GetPath(expanded, variable.c_str()); + if (stripBin) + { + std::transform(expanded.begin(), expanded.end(), expanded.begin(), + cmSearchPathStripBin); + } this->AddPrefixPaths(expanded); } diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h index 51a6149ea..41c680d14 100644 --- a/Source/cmSearchPath.h +++ b/Source/cmSearchPath.h @@ -42,7 +42,7 @@ public: void AddCMakePath(const std::string& variable); void AddEnvPath(const std::string& variable); void AddCMakePrefixPath(const std::string& variable); - void AddEnvPrefixPath(const std::string& variable); + void AddEnvPrefixPath(const std::string& variable, bool stripBin = false); void AddSuffixes(const std::vector& suffixes); protected: diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index f0426e5e7..fd01201a8 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -131,8 +131,10 @@ add_RunCMake_test(export) add_RunCMake_test(cmake_minimum_required) add_RunCMake_test(continue) add_RunCMake_test(file) +add_RunCMake_test(find_file) add_RunCMake_test(find_library) add_RunCMake_test(find_package) +add_RunCMake_test(find_path) add_RunCMake_test(get_filename_component) add_RunCMake_test(get_property) add_RunCMake_test(if) diff --git a/Tests/RunCMake/find_file/CMakeLists.txt b/Tests/RunCMake/find_file/CMakeLists.txt new file mode 100644 index 000000000..ef2163c29 --- /dev/null +++ b/Tests/RunCMake/find_file/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.1) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt b/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt new file mode 100644 index 000000000..d73bc1dfd --- /dev/null +++ b/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' diff --git a/Tests/RunCMake/find_file/PrefixInPATH.cmake b/Tests/RunCMake/find_file/PrefixInPATH.cmake new file mode 100644 index 000000000..1e33c08a6 --- /dev/null +++ b/Tests/RunCMake/find_file/PrefixInPATH.cmake @@ -0,0 +1,8 @@ +set(ENV_PATH "$ENV{PATH}") +foreach(path "/does_not_exist" "" "/bin" "/sbin") + unset(PrefixInPATH_INCLUDE_DIR CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_file(PrefixInPATH_INCLUDE_DIR NAMES PrefixInPATH.h) + message(STATUS "PrefixInPATH_INCLUDE_DIR='${PrefixInPATH_INCLUDE_DIR}'") +endforeach() +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake new file mode 100644 index 000000000..014f39734 --- /dev/null +++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(PrefixInPATH) diff --git a/Tests/RunCMake/find_file/include/PrefixInPATH.h b/Tests/RunCMake/find_file/include/PrefixInPATH.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt b/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt new file mode 100644 index 000000000..1ab884cb7 --- /dev/null +++ b/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' diff --git a/Tests/RunCMake/find_library/PrefixInPATH.cmake b/Tests/RunCMake/find_library/PrefixInPATH.cmake new file mode 100644 index 000000000..f1b8b187a --- /dev/null +++ b/Tests/RunCMake/find_library/PrefixInPATH.cmake @@ -0,0 +1,11 @@ +list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib) +list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a) + +set(ENV_PATH "$ENV{PATH}") +foreach(path "/does_not_exist" "" "/bin" "/sbin") + unset(PrefixInPATH_LIBRARY CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_library(PrefixInPATH_LIBRARY NAMES PrefixInPATH) + message(STATUS "PrefixInPATH_LIBRARY='${PrefixInPATH_LIBRARY}'") +endforeach() +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake index 40006799b..136031c63 100644 --- a/Tests/RunCMake/find_library/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake @@ -1,3 +1,4 @@ include(RunCMake) run_cmake(Created) +run_cmake(PrefixInPATH) diff --git a/Tests/RunCMake/find_library/lib/libPrefixInPATH.a b/Tests/RunCMake/find_library/lib/libPrefixInPATH.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_path/CMakeLists.txt b/Tests/RunCMake/find_path/CMakeLists.txt new file mode 100644 index 000000000..ef2163c29 --- /dev/null +++ b/Tests/RunCMake/find_path/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.1) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt b/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt new file mode 100644 index 000000000..bb2ceb725 --- /dev/null +++ b/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' diff --git a/Tests/RunCMake/find_path/PrefixInPATH.cmake b/Tests/RunCMake/find_path/PrefixInPATH.cmake new file mode 100644 index 000000000..614d64f1f --- /dev/null +++ b/Tests/RunCMake/find_path/PrefixInPATH.cmake @@ -0,0 +1,8 @@ +set(ENV_PATH "$ENV{PATH}") +foreach(path "/does_not_exist" "" "/bin" "/sbin") + unset(PrefixInPATH_INCLUDE_DIR CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_path(PrefixInPATH_INCLUDE_DIR NAMES PrefixInPATH.h) + message(STATUS "PrefixInPATH_INCLUDE_DIR='${PrefixInPATH_INCLUDE_DIR}'") +endforeach() +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake new file mode 100644 index 000000000..014f39734 --- /dev/null +++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(PrefixInPATH) diff --git a/Tests/RunCMake/find_path/include/PrefixInPATH.h b/Tests/RunCMake/find_path/include/PrefixInPATH.h new file mode 100644 index 000000000..e69de29bb