find_*: Add support for REQUIRED keyword

In the same spirit as the REQUIRED keyword on find_package, this will
stop cmake execution with an error on a failed find_program, find_file,
find_path or find_library.
This commit is contained in:
Sylvain Joubert 2020-03-06 14:30:01 +01:00
parent cc070e66cd
commit dc00809596
27 changed files with 121 additions and 2 deletions

View File

@ -15,6 +15,7 @@ The general signature is:
[PATHS path1 [path2 ... ENV var]]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[DOC "cache documentation string"]
[REQUIRED]
[NO_DEFAULT_PATH]
[NO_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
@ -31,8 +32,9 @@ A cache entry named by ``<VAR>`` is created to store the result
of this command.
If the |SEARCH_XXX| is found the result is stored in the variable
and the search will not be repeated unless the variable is cleared.
If nothing is found, the result will be
``<VAR>-NOTFOUND``, and the search will be attempted again the
If nothing is found, the result will be ``<VAR>-NOTFOUND``.
The ``REQUIRED`` option stops processing with an error message if nothing
is found, otherwise the search will be attempted again the
next time |FIND_XXX| is invoked with the same variable.
Options include:
@ -57,6 +59,9 @@ Options include:
``DOC``
Specify the documentation string for the ``<VAR>`` cache entry.
``REQUIRED``
Stop processing with an error message if nothing is found.
If ``NO_DEFAULT_PATH`` is specified, then no additional paths are
added to the search.
If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:

View File

@ -0,0 +1,6 @@
required_find_commands
----------------------
* The :command:`find_program`, :command:`find_library`, :command:`find_path`
and :command:`find_file` commands gained a new ``REQUIRED`` option that will
stop processing with an error message if nothing is found.

View File

@ -111,6 +111,10 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
} else if (args[j] == "NO_SYSTEM_PATH") {
doing = DoingNone;
this->NoDefaultPath = true;
} else if (args[j] == "REQUIRED") {
doing = DoingNone;
this->Required = true;
newStyle = true;
} else if (this->CheckCommonArgument(args[j])) {
doing = DoingNone;
} else {

View File

@ -53,6 +53,8 @@ protected:
bool AlreadyInCache = false;
bool AlreadyInCacheWithoutMetaInfo = false;
bool Required = false;
private:
// Add pieces of the search.
void FillPackageRootPath();

View File

@ -12,6 +12,7 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@ -84,6 +85,13 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
this->Makefile->AddCacheDefinition(this->VariableName, notfound.c_str(),
this->VariableDocumentation.c_str(),
cmStateEnums::FILEPATH);
if (this->Required) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"Could not find " + this->VariableName +
" using the following names: " + cmJoin(this->Names, ", "));
cmSystemTools::SetFatalErrorOccured();
}
return true;
}

View File

@ -5,6 +5,7 @@
#include "cmsys/Glob.hxx"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@ -51,6 +52,13 @@ bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
this->VariableName, (this->VariableName + "-NOTFOUND").c_str(),
this->VariableDocumentation.c_str(),
(this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH);
if (this->Required) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"Could not find " + this->VariableName +
" using the following files: " + cmJoin(this->Names, ", "));
cmSystemTools::SetFatalErrorOccured();
}
return true;
}

View File

@ -3,6 +3,7 @@
#include "cmFindProgramCommand.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@ -136,6 +137,13 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn)
this->Makefile->AddCacheDefinition(
this->VariableName, (this->VariableName + "-NOTFOUND").c_str(),
this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH);
if (this->Required) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
"Could not find " + this->VariableName +
" using the following names: " + cmJoin(this->Names, ", "));
cmSystemTools::SetFatalErrorOccured();
}
return true;
}

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at Required.cmake:9 \(find_file\):
Could not find FILE_doNotExists using the following files: doNotExists.h
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1 @@
-- FILE_exists='[^']*/Tests/RunCMake/find_file/include/PrefixInPATH.h'

View File

@ -0,0 +1,12 @@
find_file(FILE_exists
NAMES PrefixInPATH.h
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
NO_DEFAULT_PATH
REQUIRED
)
message(STATUS "FILE_exists='${FILE_exists}'")
find_file(FILE_doNotExists
NAMES doNotExists.h
REQUIRED
)

View File

@ -3,3 +3,4 @@ include(RunCMake)
run_cmake(FromPATHEnv)
run_cmake(FromPrefixPath)
run_cmake(PrefixInPATH)
run_cmake(Required)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at Required.cmake:11 \(find_library\):
Could not find LIB_doNotExists using the following names: doNotExists
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1 @@
-- LIB_exists='[^']*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'

View File

@ -0,0 +1,14 @@
list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib)
list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a)
find_library(LIB_exists
NAMES PrefixInPATH
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
NO_DEFAULT_PATH
REQUIRED
)
message(STATUS "LIB_exists='${LIB_exists}'")
find_library(LIB_doNotExists
NAMES doNotExists
REQUIRED
)

View File

@ -7,3 +7,4 @@ if(CMAKE_HOST_UNIX)
run_cmake(LibArchLink)
endif()
run_cmake(PrefixInPATH)
run_cmake(Required)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at Required.cmake:9 \(find_path\):
Could not find PATH_doNotExists using the following files: doNotExists.h
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1 @@
-- PATH_exists='[^']*/Tests/RunCMake/find_path/include'

View File

@ -0,0 +1,12 @@
find_path(PATH_exists
NAMES PrefixInPATH.h
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
NO_DEFAULT_PATH
REQUIRED
)
message(STATUS "PATH_exists='${PATH_exists}'")
find_path(PATH_doNotExists
NAMES doNotExists.h
REQUIRED
)

View File

@ -3,6 +3,7 @@ include(RunCMake)
run_cmake(EmptyOldStyle)
run_cmake(FromPATHEnv)
run_cmake(PrefixInPATH)
run_cmake(Required)
if(APPLE)
run_cmake(FrameworksWithSubdirs)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at Required.cmake:9 \(find_program\):
Could not find PROG_AandB using the following names: testAandB
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1 @@
-- PROG_A='[^']*/Tests/RunCMake/find_program/A/testA'

View File

@ -0,0 +1,12 @@
find_program(PROG_A
NAMES testA
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
NO_DEFAULT_PATH
REQUIRED
)
message(STATUS "PROG_A='${PROG_A}'")
find_program(PROG_AandB
NAMES testAandB
REQUIRED
)

View File

@ -4,6 +4,7 @@ run_cmake(EnvAndHints)
run_cmake(DirsPerName)
run_cmake(NamesPerDir)
run_cmake(RelAndAbsPath)
run_cmake(Required)
if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN)$")
run_cmake(WindowsCom)