1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmDefinePropertyCommand.h"
8 #include <cmext/string_view>
10 #include "cmArgumentParser.h"
11 #include "cmArgumentParserTypes.h"
12 #include "cmExecutionStatus.h"
13 #include "cmMakefile.h"
14 #include "cmProperty.h"
17 #include "cmStringAlgorithms.h"
19 bool cmDefinePropertyCommand(std::vector<std::string> const& args,
20 cmExecutionStatus& status)
23 status.SetError("called with incorrect number of arguments");
27 // Get the scope in which to define the property.
28 cmProperty::ScopeType scope;
29 std::string const& scope_arg = args[0];
31 if (scope_arg == "GLOBAL") {
32 scope = cmProperty::GLOBAL;
33 } else if (scope_arg == "DIRECTORY") {
34 scope = cmProperty::DIRECTORY;
35 } else if (scope_arg == "TARGET") {
36 scope = cmProperty::TARGET;
37 } else if (scope_arg == "SOURCE") {
38 scope = cmProperty::SOURCE_FILE;
39 } else if (scope_arg == "TEST") {
40 scope = cmProperty::TEST;
41 } else if (scope_arg == "VARIABLE") {
42 scope = cmProperty::VARIABLE;
43 } else if (scope_arg == "CACHED_VARIABLE") {
44 scope = cmProperty::CACHED_VARIABLE;
46 status.SetError(cmStrCat("given invalid scope ", scope_arg,
47 ". Valid scopes are GLOBAL, DIRECTORY, TARGET, "
48 "SOURCE, TEST, VARIABLE, CACHED_VARIABLE."));
52 // Parse remaining arguments.
53 bool inherited = false;
54 std::string PropertyName;
55 ArgumentParser::NonEmpty<std::vector<std::string>> BriefDocs;
56 ArgumentParser::NonEmpty<std::vector<std::string>> FullDocs;
57 std::string initializeFromVariable;
59 cmArgumentParser<void> parser;
60 parser.Bind("PROPERTY"_s, PropertyName);
61 parser.Bind("BRIEF_DOCS"_s, BriefDocs);
62 parser.Bind("FULL_DOCS"_s, FullDocs);
63 parser.Bind("INHERITED"_s, inherited);
64 parser.Bind("INITIALIZE_FROM_VARIABLE"_s, initializeFromVariable);
65 std::vector<std::string> invalidArgs;
67 parser.Parse(cmMakeRange(args).advance(1), &invalidArgs);
68 if (!invalidArgs.empty()) {
70 cmStrCat("given invalid argument \"", invalidArgs.front(), "\"."));
74 // Make sure a property name was found.
75 if (PropertyName.empty()) {
76 status.SetError("not given a PROPERTY <name> argument.");
80 if (!initializeFromVariable.empty()) {
81 // Make sure property scope is TARGET.
82 if (scope != cmProperty::TARGET) {
84 "Scope must be TARGET if INITIALIZE_FROM_VARIABLE is specified");
88 // Make sure the variable has the property name as a suffix.
89 if (!cmHasSuffix(initializeFromVariable, PropertyName)) {
90 status.SetError(cmStrCat("Variable name \"", initializeFromVariable,
91 "\" does not end with property name \"",
95 if (PropertyName.find('_') == std::string::npos) {
96 status.SetError(cmStrCat("Property name \"", PropertyName,
97 "\" defined with INITIALIZE_FROM_VARIABLE does "
98 "not contain underscore"));
102 // Make sure the variable is not reserved.
103 static constexpr const char* reservedPrefixes[] = {
107 if (std::any_of(std::begin(reservedPrefixes), std::end(reservedPrefixes),
108 [&initializeFromVariable](const char* prefix) {
109 return cmHasPrefix(initializeFromVariable, prefix);
111 status.SetError(cmStrCat("variable name \"", initializeFromVariable,
117 // Actually define the property.
118 status.GetMakefile().GetState()->DefineProperty(
119 PropertyName, scope, cmJoin(BriefDocs, ""), cmJoin(FullDocs, ""),
120 inherited, initializeFromVariable);