summaryrefslogtreecommitdiffstats
path: root/Source/cmCMakeLanguageCommand.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmCMakeLanguageCommand.cxx')
-rw-r--r--Source/cmCMakeLanguageCommand.cxx93
1 files changed, 93 insertions, 0 deletions
diff --git a/Source/cmCMakeLanguageCommand.cxx b/Source/cmCMakeLanguageCommand.cxx
index 27d8cb8..7d05e88 100644
--- a/Source/cmCMakeLanguageCommand.cxx
+++ b/Source/cmCMakeLanguageCommand.cxx
@@ -13,11 +13,14 @@
#include <cm/string_view>
#include <cmext/string_view>
+#include "cmArgumentParser.h"
+#include "cmDependencyProvider.h"
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmRange.h"
+#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -215,6 +218,91 @@ bool cmCMakeLanguageCommandEVAL(std::vector<cmListFileArgument> const& args,
return makefile.ReadListFileAsString(
code, cmStrCat(context.FilePath, ":", context.Line, ":EVAL"));
}
+
+bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER(
+ std::vector<std::string> const& args, cmExecutionStatus& status)
+{
+ cmState* state = status.GetMakefile().GetState();
+ if (!state->InTopLevelIncludes()) {
+ return FatalError(
+ status,
+ "Dependency providers can only be set as part of the first call to "
+ "project(). More specifically, cmake_language(SET_DEPENDENCY_PROVIDER) "
+ "can only be called while the first project() command processes files "
+ "listed in CMAKE_PROJECT_TOP_LEVEL_INCLUDES.");
+ }
+
+ struct SetProviderArgs
+ {
+ std::string Command;
+ std::vector<std::string> Methods;
+ };
+
+ auto const ArgsParser =
+ cmArgumentParser<SetProviderArgs>()
+ .Bind("SET_DEPENDENCY_PROVIDER"_s, &SetProviderArgs::Command)
+ .Bind("SUPPORTED_METHODS"_s, &SetProviderArgs::Methods);
+
+ std::vector<std::string> unparsed;
+ auto parsedArgs = ArgsParser.Parse(args, &unparsed);
+
+ if (!unparsed.empty()) {
+ return FatalError(
+ status, cmStrCat("Unrecognized keyword: \"", unparsed.front(), "\""));
+ }
+
+ // We store the command that FetchContent_MakeAvailable() can call in a
+ // global (but considered internal) property. If the provider doesn't
+ // support this method, we set this property to an empty string instead.
+ // This simplifies the logic in FetchContent_MakeAvailable() and doesn't
+ // require us to define a new internal command or sub-command.
+ std::string fcmasProperty = "__FETCHCONTENT_MAKEAVAILABLE_SERIAL_PROVIDER";
+
+ if (parsedArgs.Command.empty()) {
+ if (!parsedArgs.Methods.empty()) {
+ return FatalError(status,
+ "Must specify a non-empty command name when provider "
+ "methods are given");
+ }
+ state->ClearDependencyProvider();
+ state->SetGlobalProperty(fcmasProperty, "");
+ return true;
+ }
+
+ cmState::Command command = state->GetCommand(parsedArgs.Command);
+ if (!command) {
+ return FatalError(status,
+ cmStrCat("Command \"", parsedArgs.Command,
+ "\" is not a defined command"));
+ }
+
+ if (parsedArgs.Methods.empty()) {
+ return FatalError(status, "Must specify at least one provider method");
+ }
+
+ bool supportsFetchContentMakeAvailableSerial = false;
+ std::vector<cmDependencyProvider::Method> methods;
+ for (auto const& method : parsedArgs.Methods) {
+ if (method == "FIND_PACKAGE") {
+ methods.emplace_back(cmDependencyProvider::Method::FindPackage);
+ } else if (method == "FETCHCONTENT_MAKEAVAILABLE_SERIAL") {
+ supportsFetchContentMakeAvailableSerial = true;
+ methods.emplace_back(
+ cmDependencyProvider::Method::FetchContentMakeAvailableSerial);
+ } else {
+ return FatalError(
+ status,
+ cmStrCat("Unknown dependency provider method \"", method, "\""));
+ }
+ }
+
+ state->SetDependencyProvider({ parsedArgs.Command, methods });
+ state->SetGlobalProperty(
+ fcmasProperty,
+ supportsFetchContentMakeAvailableSerial ? parsedArgs.Command.c_str() : "");
+
+ return true;
+}
}
bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
@@ -246,6 +334,11 @@ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
return FatalError(status, "called with incorrect number of arguments");
}
+ if (expArgs[expArg] == "SET_DEPENDENCY_PROVIDER"_s) {
+ finishArgs();
+ return cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER(expArgs, status);
+ }
+
cm::optional<Defer> maybeDefer;
if (expArgs[expArg] == "DEFER"_s) {
++expArg; // Consume "DEFER".