diff --git a/Help/command/find_program.rst b/Help/command/find_program.rst index 2a5ce9a8d..d3430c054 100644 --- a/Help/command/find_program.rst +++ b/Help/command/find_program.rst @@ -2,7 +2,7 @@ find_program ------------ .. |FIND_XXX| replace:: find_program -.. |NAMES| replace:: NAMES name1 [name2 ...] +.. |NAMES| replace:: NAMES name1 [name2 ...] [NAMES_PER_DIR] .. |SEARCH_XXX| replace:: program .. |SEARCH_XXX_DESC| replace:: program .. |prefix_XXX_SUBDIR| replace:: ``/[s]bin`` @@ -26,3 +26,8 @@ find_program :variable:`CMAKE_FIND_ROOT_PATH_MODE_PROGRAM` .. include:: FIND_XXX.txt + +When more than one value is given to the ``NAMES`` option this command by +default will consider one name at a time and search every directory +for it. The ``NAMES_PER_DIR`` option tells this command to consider one +directory at a time and search for all names in it. diff --git a/Help/release/dev/find_program-NAMES_PER_DIR.rst b/Help/release/dev/find_program-NAMES_PER_DIR.rst new file mode 100644 index 000000000..04cd17045 --- /dev/null +++ b/Help/release/dev/find_program-NAMES_PER_DIR.rst @@ -0,0 +1,6 @@ +find_program-NAMES_PER_DIR +-------------------------- + +* The :command:`find_program` command learned a ``NAMES_PER_DIR`` + option to consdier all given ``NAMES`` in each directory before + moving on to the next directory. diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index c9bc56ded..e64ed87f2 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -85,6 +85,11 @@ struct cmFindProgramHelper } }; +cmFindProgramCommand::cmFindProgramCommand() +{ + this->NamesPerDirAllowed = true; +} + // cmFindProgramCommand bool cmFindProgramCommand ::InitialPass(std::vector const& argsIn, cmExecutionStatus &) @@ -150,6 +155,42 @@ std::string cmFindProgramCommand::FindProgram() //---------------------------------------------------------------------------- std::string cmFindProgramCommand::FindNormalProgram() +{ + if(this->NamesPerDir) + { + return this->FindNormalProgramNamesPerDir(); + } + else + { + return this->FindNormalProgramDirsPerName(); + } +} + +//---------------------------------------------------------------------------- +std::string cmFindProgramCommand::FindNormalProgramNamesPerDir() +{ + // Search for all names in each directory. + cmFindProgramHelper helper; + for (std::vector::const_iterator ni = this->Names.begin(); + ni != this->Names.end() ; ++ni) + { + helper.AddName(*ni); + } + // Search every directory. + for (std::vector::const_iterator + p = this->SearchPaths.begin(); p != this->SearchPaths.end(); ++p) + { + if(helper.CheckDirectory(*p)) + { + return helper.BestPath; + } + } + // Couldn't find the program. + return ""; +} + +//---------------------------------------------------------------------------- +std::string cmFindProgramCommand::FindNormalProgramDirsPerName() { // Search the entire path for each name. cmFindProgramHelper helper; diff --git a/Source/cmFindProgramCommand.h b/Source/cmFindProgramCommand.h index df39b14bd..f88186b92 100644 --- a/Source/cmFindProgramCommand.h +++ b/Source/cmFindProgramCommand.h @@ -25,6 +25,7 @@ class cmFindProgramCommand : public cmFindBase { public: + cmFindProgramCommand(); /** * This is a virtual constructor for the command. */ @@ -55,6 +56,8 @@ public: private: std::string FindProgram(); std::string FindNormalProgram(); + std::string FindNormalProgramDirsPerName(); + std::string FindNormalProgramNamesPerDir(); std::string FindAppBundle(); std::string GetBundleExecutable(std::string bundlePath); diff --git a/Tests/RunCMake/find_program/NamesPerDir-stdout.txt b/Tests/RunCMake/find_program/NamesPerDir-stdout.txt new file mode 100644 index 000000000..964e25971 --- /dev/null +++ b/Tests/RunCMake/find_program/NamesPerDir-stdout.txt @@ -0,0 +1 @@ +-- PROG='[^']*/Tests/RunCMake/find_program/A/testA' diff --git a/Tests/RunCMake/find_program/NamesPerDir.cmake b/Tests/RunCMake/find_program/NamesPerDir.cmake new file mode 100644 index 000000000..49ce49d84 --- /dev/null +++ b/Tests/RunCMake/find_program/NamesPerDir.cmake @@ -0,0 +1,6 @@ +find_program(PROG + NAMES testB testA NAMES_PER_DIR + PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B + NO_DEFAULT_PATH + ) +message(STATUS "PROG='${PROG}'") diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake index 1a99f0a20..2adec1100 100644 --- a/Tests/RunCMake/find_program/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake @@ -1,6 +1,7 @@ include(RunCMake) run_cmake(DirsPerName) +run_cmake(NamesPerDir) if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN)$") run_cmake(WindowsCom)