diff --git a/Help/command/cmake_language.rst b/Help/command/cmake_language.rst index 00eaa0e684..1090354d05 100644 --- a/Help/command/cmake_language.rst +++ b/Help/command/cmake_language.rst @@ -20,6 +20,16 @@ Synopsis cmake_language(`PRINT_TARGETS`_ ...) cmake_language(`PRINT_VARIABLES`_ [{ ALL [...] | NAMED ... }]) + cmake_language(PRINT_PROPERTIES + `TARGETS `__ ... + ... + [{ ALL [] | NAMED ... }]) + cmake_language(PRINT_PROPERTIES + { `SOURCES `__ ... | + `DIRECTORIES `__ ... | + `TESTS `__ ... | + `CACHE_ENTRIES `__ ... } + NAMED ...) Introduction ^^^^^^^^^^^^ @@ -683,3 +693,169 @@ Gives:: Variables in scope at '/path/to/CMakeLists.txt' matching name '^MY_' (case sensitive): MY_FLAG = "on" CACHE{MY_PATH}:FILEPATH = "/some/path" + +Printing Properties +^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 4.5 + +.. signature:: + cmake_language(PRINT_PROPERTIES + TARGETS ... ... + [{ ALL [] | NAMED ... }]) + :target: PRINT_PROPERTIES-TARGETS + + Prints the values of properties for the specified targets. + The set of properties to print may be specified by one of: + + ``ALL []`` (default) + Enumerates every property set on each named target, printing one entry + per property. + + The optional ```` may be one of: + + ``PROPERTY_NAME_REGEX `` + Print properties whose name matches the given regular expression. + ``PROPERTY_VALUE_REGEX `` + Print properties whose value matches the given regular expression. + + If no property survives the regex filters for a given target, a + ``CMake Warning`` is emitted in place of that target's block. + + ``NAMED ...`` + Prints exactly the named properties on each entity, in the order given. + A property that is not set prints as ````. + + The ``...`` are: + + ``DEFERRED`` + Defers the print to generation time rather than running during + configure. Useful when the properties of interest are populated by + later configure-time commands. On its own it does not change which + targets are visited - only the named targets are printed. + + ``FOLLOW_DEPENDENCIES`` + Implies ``DEFERRED``. When set, the walk visits every target reachable + from each named target through any linkage - ``PUBLIC``, ``INTERFACE``, + ``PRIVATE``, and :genex:`$` - and prints the requested + properties for each. + + .. note:: + ``FOLLOW_DEPENDENCIES`` does not turn on generator-expression + evaluation for the property *values* this command prints. + The only place generator expression evaluation happens is internal: + on each visited target's link list (the effective ``LINK_LIBRARIES`` / + ``INTERFACE_LINK_LIBRARIES``), evaluated solely to identify which + dependencies are reachable. Every printed property value, + including the link-list properties themselves, is emitted exactly + as stored, with generator expressions intact and unsubstituted. + This matches the behavior of :command:`get_target_property`. + +.. signature:: + cmake_language(PRINT_PROPERTIES SOURCES ... NAMED ...) + cmake_language(PRINT_PROPERTIES DIRECTORIES ... NAMED ...) + cmake_language(PRINT_PROPERTIES TESTS ... NAMED ...) + cmake_language(PRINT_PROPERTIES CACHE_ENTRIES ... NAMED ...) + :target: + PRINT_PROPERTIES-SOURCES + PRINT_PROPERTIES-DIRECTORIES + PRINT_PROPERTIES-TESTS + PRINT_PROPERTIES-CACHE_ENTRIES + + Prints the values of properties for the specified source files, directories, + tests, or cache entries. Exactly one scope keyword must be specified. + The set of properties to print must be specified by: + + ``NAMED ...`` + Prints exactly the named properties on each entity, in the order given. + A property that is not set prints as ````. + +Printing Properties Examples +"""""""""""""""""""""""""""" + +Printing the ``LOCATION`` and ``INTERFACE_INCLUDE_DIRECTORIES`` properties for +both targets ``foo`` and ``bar``: + +.. code-block:: cmake + + cmake_language( + PRINT_PROPERTIES + TARGETS foo bar + NAMED LOCATION INTERFACE_INCLUDE_DIRECTORIES + ) + +Gives:: + + -- Printing properties... + Properties for TARGET foo: + foo.LOCATION = "/usr/lib/libfoo.so" + foo.INTERFACE_INCLUDE_DIRECTORIES = "/usr/include;/usr/include/foo" + Properties for TARGET bar: + bar.LOCATION = "/usr/lib/libbar.so" + bar.INTERFACE_INCLUDE_DIRECTORIES = "/usr/include;/usr/include/bar" + +Printing all properties on a target, filtered to a couple of names: + +.. code-block:: cmake + + add_library(my_lib src.cpp) + + cmake_language( + PRINT_PROPERTIES + TARGETS my_lib + ALL + PROPERTY_NAME_REGEX "AUTOMOC" + PROPERTY_VALUE_REGEX "(ON|OFF)" + ) + +Gives:: + + -- Printing properties... + All properties for TARGET my_lib matching name 'AUTOMOC' and value '(ON|OFF)': + my_lib.AUTOMOC_COMPILER_PREDEFINES = "ON" + my_lib.AUTOMOC_PATH_PREFIX = "OFF" + +Deferring the print of one target's properties to generation time, without +visiting any dependencies: + +.. code-block:: cmake + + add_executable(myexe main.c) + + cmake_language( + PRINT_PROPERTIES + TARGETS myexe + DEFERRED + NAMED SOURCES + ) + +Gives:: + + -- Printing properties... + Properties for TARGET myexe: + myexe.SOURCES = "main.c" + +Printing a property on a target and every reachable dependency: + +.. code-block:: cmake + + add_library(leaflib STATIC src.c) + set_target_properties(leaflib PROPERTIES MY_PROP "leaf") + + add_library(mylib STATIC src.c) + target_link_libraries(mylib PRIVATE leaflib) + set_target_properties(mylib PROPERTIES MY_PROP "mylib") + + cmake_language( + PRINT_PROPERTIES + TARGETS mylib + FOLLOW_DEPENDENCIES + NAMED MY_PROP + ) + +Gives:: + + -- Printing properties... + Properties for TARGET mylib (and all reachable): + mylib.MY_PROP = "mylib" + leaflib.MY_PROP = "leaf" diff --git a/Help/release/dev/print_all_properties.rst b/Help/release/dev/print_all_properties.rst new file mode 100644 index 0000000000..329164f138 --- /dev/null +++ b/Help/release/dev/print_all_properties.rst @@ -0,0 +1,6 @@ +print_all_properties +-------------------- + +* The :command:`cmake_language(PRINT_PROPERTIES)` command was added + to print CMake entities' properties in human-readable form for + debugging. diff --git a/Source/cmCMakeLanguageCommand.cxx b/Source/cmCMakeLanguageCommand.cxx index 3a14472eab..63f96c964c 100644 --- a/Source/cmCMakeLanguageCommand.cxx +++ b/Source/cmCMakeLanguageCommand.cxx @@ -5,8 +5,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -23,10 +25,15 @@ #include "cmDependencyProvider.h" #include "cmExecutionStatus.h" #include "cmExperimental.h" +#include "cmGeneratorTarget.h" +#include "cmGetPropertyCommand.h" #include "cmGlobalGenerator.h" +#include "cmLinkItem.h" #include "cmListFileCache.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" // IWYU pragma: keep +#include "cmPropertyMap.h" #include "cmRange.h" #include "cmState.h" #include "cmStateSnapshot.h" @@ -34,6 +41,8 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmTargetPropertyComputer.h" +#include "cmTargetPropertyHelper.h" #include "cmValue.h" #include "cmake.h" @@ -785,8 +794,649 @@ bool cmCMakeLanguageCommandPRINT_VARIABLES( parsedArgs.CmakePrintVariables); return true; } +// Walks every target reachable from `root` through any linkage - PUBLIC, +// INTERFACE, PRIVATE, and `$`-wrapped deps. At each level we +// union the link implementation and link interface, each queried with both +// UseTo::Compile and UseTo::Link, so deps that only appear under LINK_ONLY +// (which evaluates to empty under UseTo::Compile) still come through. +std::vector CollectDependentTargets( + cmGeneratorTarget const* root, std::string const& config) +{ + std::vector deps; + std::set visited; + visited.insert(root); + std::vector queue; + queue.push_back(root); + while (!queue.empty()) { + cmGeneratorTarget const* cur = queue.back(); + queue.pop_back(); + auto visit = [&](std::vector const& libs) { + for (cmLinkItem const& item : libs) { + cmGeneratorTarget const* dep = item.Target; + if (!dep || !visited.insert(dep).second) { + continue; + } + deps.push_back(dep); + queue.push_back(dep); + } + }; + for (auto useTo : { cmGeneratorTarget::UseTo::Compile, + cmGeneratorTarget::UseTo::Link }) { + if (cmLinkImplementationLibraries const* impl = + cur->GetLinkImplementationLibraries(config, useTo)) { + visit(impl->Libraries); + } + if (cmLinkInterfaceLibraries const* iface = + cur->GetLinkInterfaceLibraries(config, root, useTo)) { + visit(iface->Libraries); + } + } + } + return deps; } +// Append one property line to `out`: +// " . = \"\"" +// A null `value` writes "" instead of "= \"...\"". +void WritePropertyLine(std::string& out, std::string const& entityName, + std::string const& propertyName, cmValue value) +{ + out += cmStrCat(" ", entityName, ".", propertyName); + if (value) { + out += cmStrCat(" = \"", *value, "\""); + } else { + out += " = "; + } + out += "\n"; +} + +enum class BlockKind +{ + Explicit, + All, +}; + +enum class HeaderSuffix +{ + None, + Reachable, +}; + +void EmitBlockHeader( + std::string& out, std::string const& entityName, + std::string const& entityType, BlockKind kind, HeaderSuffix suffix, + cm::optional const& nameRegexStr = cm::nullopt, + cm::optional const& valueRegexStr = cm::nullopt) +{ + out += + cmStrCat(" ", (kind == BlockKind::All ? "All properties" : "Properties"), + " for ", entityType, " ", entityName); + if (suffix == HeaderSuffix::Reachable) { + out += " (and all reachable)"; + } + if (kind == BlockKind::All && (nameRegexStr || valueRegexStr)) { + out += " matching"; + if (nameRegexStr) { + out += cmStrCat(" name '", *nameRegexStr, "'"); + } + if (nameRegexStr && valueRegexStr) { + out += " and"; + } + if (valueRegexStr) { + out += cmStrCat(" value '", *valueRegexStr, "'"); + } + } + out += ":\n"; +} + +// Build the "no properties matched" warning text used when the regex filter +// wipes everything out for a target's ALL block. Returned without any +// "Warning:" prefix - callers feed it to IssueMessage, which adds the +// standard "CMake Warning at :" framing. +std::string EmptyMatchWarningMessage( + std::string const& entityName, std::string const& entityType, + cm::optional const& nameRegexStr, + cm::optional const& valueRegexStr) +{ + std::string msg = + cmStrCat("No properties for ", entityType, " ", entityName, " matching"); + if (nameRegexStr) { + msg += cmStrCat(" name '", *nameRegexStr, "'"); + } + if (nameRegexStr && valueRegexStr) { + msg += " and"; + } + if (valueRegexStr) { + msg += cmStrCat(" value '", *valueRegexStr, "'"); + } + msg += " in cmake_language(PRINT_PROPERTIES ...)."; + return msg; +} + +// Entity kinds supported by cmake_language(PRINT_PROPERTIES). +enum class EntityKind +{ + Target, + Source, + Test, + Directory, + Cache +}; + +// Display name used in PRINT_PROPERTIES output ("TARGET", "SOURCE", etc.). +char const* EntityTypeName(EntityKind kind) +{ + switch (kind) { + case EntityKind::Target: + return "TARGET"; + case EntityKind::Source: + return "SOURCE"; + case EntityKind::Test: + return "TEST"; + case EntityKind::Directory: + return "DIRECTORY"; + case EntityKind::Cache: + return "CACHE"; + } + return ""; +} + +// Dispatch a property lookup to the appropriate per-entity helper. +bool GetPropertyHelper(cmExecutionStatus& status, EntityKind kind, + std::string const& name, + std::string const& propertyName, cmValue& out) +{ + switch (kind) { + case EntityKind::Target: + return GetPropertyCommand::LookupTargetProperty(status, name, + propertyName, out); + case EntityKind::Source: + return GetPropertyCommand::LookupSourceProperty(status, name, + propertyName, out); + case EntityKind::Test: + return GetPropertyCommand::LookupTestProperty(status, name, propertyName, + out); + case EntityKind::Directory: + return GetPropertyCommand::LookupDirectoryProperty(status, name, + propertyName, out); + case EntityKind::Cache: + return GetPropertyCommand::LookupCacheProperty(status, name, + propertyName, out); + } + return false; +} + +// Emit one ALL-mode block: prints all properties matching the specified +// regexes for a head target (`targets[0]`) and optionally any reachable +// dependencies (`targets[1]` and on). +bool EmitAllPropertiesBlock(std::string& out, std::string const& headerName, + std::vector const& targets, + HeaderSuffix suffix, + cm::optional& nameRegex, + cm::optional& valueRegex, + cm::optional const& nameRegexStr, + cm::optional const& valueRegexStr) +{ + std::string groupBuf; + bool groupEmitted = false; + for (cmTarget* t : targets) { + std::string const& rowName = + (t == targets.front()) ? headerName : t->GetName(); + for (auto const& kv : t->GetExtendedProperties().GetList()) { + if (nameRegex && !nameRegex->find(kv.first)) { + continue; + } + if (valueRegex && !valueRegex->find(kv.second)) { + continue; + } + WritePropertyLine(groupBuf, rowName, kv.first, cmValue(kv.second)); + groupEmitted = true; + } + } + if (!groupEmitted) { + return false; + } + EmitBlockHeader(out, headerName, "TARGET", BlockKind::All, suffix, + nameRegexStr, valueRegexStr); + out += groupBuf; + return true; +} + +// Outcome of emitting a NAMED-mode block. +enum class NamedBlockResult +{ + Failed, // a property lookup hard-failed + Emitted, // at least one property line was written + Empty, // every requested property was skipped; header suppressed +}; + +// Emit one block of user-specified properties for a head target (`targets[0]`) +// and optionally any reachable dependencies (`targets[1]` and on). +NamedBlockResult EmitNamedPropertiesBlock( + std::string& out, std::string const& headerName, + std::vector const& targets, + std::vector const& namedProperties, HeaderSuffix suffix, + cmMakefile& mf) +{ + bool headerWritten = false; + for (cmTarget* t : targets) { + std::string const& rowName = + (t == targets.front()) ? headerName : t->GetName(); + for (std::string const& propName : namedProperties) { + // A computed location property may not be read from a non-imported + // target; skip it with a warning rather than triggering the getter's + // fatal error. + if (!t->IsImported() && + cmTargetPropertyComputer::IsComputedLocationProperty(t->GetType(), + propName)) { + mf.IssueMessage( + MessageType::WARNING, + cmStrCat("The ", propName, + " property may not be read from non-imported target \"", + rowName, "\"; skipping.")); + continue; + } + cmValue v; + if (cmGetTargetProperty(rowName, t, propName, mf, v) != + cmGetTargetPropertyResult::Success) { + return NamedBlockResult::Failed; + } + if (!headerWritten) { + EmitBlockHeader(out, headerName, "TARGET", BlockKind::Explicit, + suffix); + headerWritten = true; + } + WritePropertyLine(out, rowName, propName, v); + } + } + return headerWritten ? NamedBlockResult::Emitted : NamedBlockResult::Empty; +} + +bool PrintPropertiesConfigureTime( + cmExecutionStatus& status, std::vector const& namedProperties, + bool all, std::vector const& entityNames, EntityKind kind, + cm::optional const& propertyNameRegexStr, + cm::optional const& propertyValueRegexStr, + cm::optional& propertyNameRegex, + cm::optional& propertyValueRegex, + std::string const& messagePrefix) +{ + cmMakefile& makefile = status.GetMakefile(); + bool const hasRegex = propertyNameRegexStr || propertyValueRegexStr; + std::string out = messagePrefix; + bool anyEmitted = false; + for (auto const& entityName : entityNames) { + if (kind == EntityKind::Target) { + cmTarget* target = makefile.FindTargetToUse(entityName); + if (!target) { + out += cmStrCat("\n No such TARGET \"", entityName, "\" !\n\n"); + anyEmitted = true; + continue; + } + if (all) { + bool const emitted = EmitAllPropertiesBlock( + out, entityName, { target }, HeaderSuffix::None, propertyNameRegex, + propertyValueRegex, propertyNameRegexStr, propertyValueRegexStr); + if (emitted) { + anyEmitted = true; + } else if (hasRegex) { + makefile.IssueMessage(MessageType::WARNING, + EmptyMatchWarningMessage( + entityName, "TARGET", propertyNameRegexStr, + propertyValueRegexStr)); + } + } else { + NamedBlockResult const result = EmitNamedPropertiesBlock( + out, entityName, { target }, namedProperties, HeaderSuffix::None, + makefile); + if (result == NamedBlockResult::Failed) { + status.SetError(cmStrCat( + "failed to retrieve properties for TARGET \"", entityName, "\"")); + return false; + } + if (result == NamedBlockResult::Emitted) { + anyEmitted = true; + } + } + } else { + EmitBlockHeader(out, entityName, EntityTypeName(kind), + BlockKind::Explicit, HeaderSuffix::None); + for (auto const& propertyName : namedProperties) { + cmValue v; + if (!GetPropertyHelper(status, kind, entityName, propertyName, v)) { + return false; + } + WritePropertyLine(out, entityName, propertyName, v); + } + anyEmitted = true; + } + } + if (anyEmitted) { + makefile.DisplayStatus(out, -1); + } + return true; +} + +bool PrintTargetPropertiesDeferred( + std::vector targetNames, + std::vector namedProperties, bool all, + cm::optional propertyNameRegexStr, + cm::optional propertyValueRegexStr, + cm::optional propertyNameRegex, + cm::optional propertyValueRegex, + bool followDependencies, std::string messagePrefix, + cmExecutionStatus& status) +{ + cmListFileBacktrace const bt = status.GetMakefile().GetBacktrace(); + status.GetMakefile().AddGeneratorAction( + [targetNames, namedProperties, all, propertyNameRegexStr, + propertyValueRegexStr, propertyNameRegex, propertyValueRegex, + followDependencies, messagePrefix, bt]( + cmLocalGenerator& lg, cmListFileBacktrace const& /*lambdaBt*/) mutable { + std::vector const configs = + lg.GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + std::string const config = + configs.empty() ? std::string() : configs.front(); + bool const hasRegex = propertyNameRegexStr || propertyValueRegexStr; + cmake* cmakeInst = lg.GetMakefile()->GetCMakeInstance(); + + std::string out = messagePrefix; + bool anyEmitted = false; + for (std::string const& name : targetNames) { + cmGeneratorTarget* root = lg.FindGeneratorTargetToUse(name); + if (!root) { + out += cmStrCat("\n No such TARGET \"", name, "\" !\n\n"); + anyEmitted = true; + continue; + } + std::vector targets; + targets.push_back(root->Target); + HeaderSuffix const suffix = + followDependencies ? HeaderSuffix::Reachable : HeaderSuffix::None; + if (followDependencies) { + for (cmGeneratorTarget const* dep : + CollectDependentTargets(root, config)) { + targets.push_back(dep->Target); + } + } + if (all) { + bool const emitted = EmitAllPropertiesBlock( + out, name, targets, suffix, propertyNameRegex, propertyValueRegex, + propertyNameRegexStr, propertyValueRegexStr); + if (emitted) { + anyEmitted = true; + } else if (hasRegex) { + cmakeInst->IssueMessage( + MessageType::WARNING, + EmptyMatchWarningMessage(name, "TARGET", propertyNameRegexStr, + propertyValueRegexStr), + bt); + } + } else { + NamedBlockResult const result = EmitNamedPropertiesBlock( + out, name, targets, namedProperties, suffix, *lg.GetMakefile()); + if (result == NamedBlockResult::Failed) { + cmakeInst->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("failed to retrieve properties for TARGET \"", name, + "\""), + bt); + return; + } + if (result == NamedBlockResult::Emitted) { + anyEmitted = true; + } + } + } + if (anyEmitted) { + lg.GetMakefile()->DisplayStatus(out, -1); + } + }, + cmMakefile::GeneratorActionWhen::AfterGeneratorTargets); + return true; +} + +bool cmCMakeLanguageCommandPRINT_PROPERTIES( + std::vector const& args, cmExecutionStatus& status) +{ + struct PrintPropertiesArg : public ArgumentParser::ParseResult + { + bool All = false; + ArgumentParser::NonEmpty> Named; + cm::optional PropertyNameRegex; + cm::optional PropertyValueRegex; + // Internal: set by the deprecated cmake_print_properties() module wrapper + // to select the historical leading-blank-line output instead of the + // banner. Not part of the public interface. + bool CmakePrintProperties = false; + }; + + auto ArgsParser = + cmArgumentParser() + .Bind("ALL"_s, &PrintPropertiesArg::All) + .Bind("NAMED"_s, &PrintPropertiesArg::Named) + .Bind("PROPERTY_NAME_REGEX"_s, &PrintPropertiesArg::PropertyNameRegex) + .Bind("PROPERTY_VALUE_REGEX"_s, &PrintPropertiesArg::PropertyValueRegex) + .Bind("__CMAKE_PRINT_PROPERTIES"_s, + &PrintPropertiesArg::CmakePrintProperties); + + std::vector unparsed; + auto parsedArgs = ArgsParser.Parse(args, &unparsed); + + if (unparsed.empty()) { + return FatalError(status, + cmStrCat("mode keyword missing in ", + "cmake_language(PRINT_PROPERTIES) call, ", + "there must be exactly one of TARGETS SOURCES " + "TESTS DIRECTORIES CACHE_ENTRIES")); + } + + if (parsedArgs.MaybeReportError(status.GetMakefile())) { + cmSystemTools::SetFatalErrorOccurred(); + return true; + } + + // Second parse args to get the mode + struct PrintPropertiesModesArgs : public ArgumentParser::ParseResult + { + ArgumentParser::MaybeEmpty> Targets; + ArgumentParser::MaybeEmpty> Sources; + ArgumentParser::MaybeEmpty> Tests; + ArgumentParser::MaybeEmpty> Directories; + ArgumentParser::MaybeEmpty> CacheEntries; + bool Deferred = false; + bool FollowDependencies = false; + }; + auto const ArgsParserMode = + cmArgumentParser() + .Bind("TARGETS"_s, &PrintPropertiesModesArgs::Targets) + .Bind("SOURCES"_s, &PrintPropertiesModesArgs::Sources) + .Bind("TESTS"_s, &PrintPropertiesModesArgs::Tests) + .Bind("DIRECTORIES"_s, &PrintPropertiesModesArgs::Directories) + .Bind("CACHE_ENTRIES"_s, &PrintPropertiesModesArgs::CacheEntries) + .Bind("DEFERRED"_s, &PrintPropertiesModesArgs::Deferred) + .Bind("FOLLOW_DEPENDENCIES"_s, + &PrintPropertiesModesArgs::FollowDependencies); + + std::vector modeArgs = unparsed; + unparsed.clear(); + auto parsedArgsMode = ArgsParserMode.Parse(modeArgs, &unparsed); + + if (!unparsed.empty()) { + return FatalError( + status, cmStrCat("Unknown keywords: \"", cmJoin(unparsed, " "), "\"")); + } + + if (parsedArgsMode.MaybeReportError(status.GetMakefile())) { + cmSystemTools::SetFatalErrorOccurred(); + return true; + } + std::vector modes; + std::vector items; + EntityKind kind = EntityKind::Target; + if (!parsedArgsMode.Targets.empty()) { + modes.push_back("TARGETS"); + items = parsedArgsMode.Targets; + kind = EntityKind::Target; + } + if (!parsedArgsMode.Sources.empty()) { + modes.push_back("SOURCES"); + items = parsedArgsMode.Sources; + kind = EntityKind::Source; + } + if (!parsedArgsMode.Tests.empty()) { + modes.push_back("TESTS"); + items = parsedArgsMode.Tests; + kind = EntityKind::Test; + } + if (!parsedArgsMode.Directories.empty()) { + modes.push_back("DIRECTORIES"); + items = parsedArgsMode.Directories; + kind = EntityKind::Directory; + } + if (!parsedArgsMode.CacheEntries.empty()) { + modes.push_back("CACHE_ENTRIES"); + items = parsedArgsMode.CacheEntries; + kind = EntityKind::Cache; + } + + if (modes.empty()) { + return FatalError(status, + cmStrCat("mode keyword missing in ", + "cmake_language(PRINT_PROPERTIES) call, ", + "there must be exactly one of TARGETS SOURCES " + "TESTS DIRECTORIES CACHE_ENTRIES")); + } + if (modes.size() > 1) { + return FatalError(status, + cmStrCat("multiple mode keywords used in ", + "cmake_language(PRINT_PROPERTIES) call, ", + "there must be exactly one of TARGETS SOURCES " + "TESTS DIRECTORIES CACHE_ENTRIES.")); + } + std::string const mode = modes[0]; + bool const isTargets = (mode == "TARGETS"); + bool const hasNamed = !parsedArgs.Named.empty(); + bool const hasRegex = + parsedArgs.PropertyNameRegex || parsedArgs.PropertyValueRegex; + + if (!isTargets) { + if (parsedArgs.All) { + return FatalError(status, + cmStrCat("ALL keyword in ", + "cmake_language(PRINT_PROPERTIES) call ", + "is only valid with the TARGETS scope.")); + } + if (hasRegex) { + return FatalError( + status, + cmStrCat("PROPERTY_NAME_REGEX and PROPERTY_VALUE_REGEX in ", + "cmake_language(PRINT_PROPERTIES) call ", + "are only valid with the TARGETS scope and ALL.")); + } + if (parsedArgsMode.Deferred) { + return FatalError(status, + cmStrCat("DEFERRED keyword in ", + "cmake_language(PRINT_PROPERTIES) call ", + "is only valid with the TARGETS scope.")); + } + if (parsedArgsMode.FollowDependencies) { + return FatalError(status, + cmStrCat("FOLLOW_DEPENDENCIES keyword in ", + "cmake_language(PRINT_PROPERTIES) call ", + "is only valid with the TARGETS scope.")); + } + if (!hasNamed) { + return FatalError(status, + cmStrCat("NAMED keyword missing in ", + "cmake_language(PRINT_PROPERTIES) call ", + "with ", mode, " scope.")); + } + } else { + // ALL and NAMED are mutually exclusive on TARGETS. + if (parsedArgs.All && hasNamed) { + return FatalError(status, + cmStrCat("ALL and NAMED keywords in ", + "cmake_language(PRINT_PROPERTIES) call ", + "are mutually exclusive.")); + } + // Regex filters require ALL - explicit or implicit. Combining regex + // with NAMED is an error. + if (hasNamed && hasRegex) { + return FatalError( + status, + cmStrCat("PROPERTY_NAME_REGEX and PROPERTY_VALUE_REGEX in ", + "cmake_language(PRINT_PROPERTIES) call ", + "are only valid with ALL, not NAMED.")); + } + } + + // FOLLOW_DEPENDENCIES implies DEFERRED. + if (parsedArgsMode.FollowDependencies) { + parsedArgsMode.Deferred = true; + } + + // Default to ALL when neither ALL nor NAMED is given (TARGETS only - the + // non-TARGETS path already rejected this combination above). + bool const all = parsedArgs.All || !hasNamed; + + // __CMAKE_PRINT_PROPERTIES marks the deprecated cmake_print_properties() + // wrapper, which is always NAMED; reject it in ALL enumeration mode. + if (all && parsedArgs.CmakePrintProperties) { + return FatalError(status, + cmStrCat("__CMAKE_PRINT_PROPERTIES in ", + "cmake_language(PRINT_PROPERTIES) call ", + "is only valid with NAMED.")); + } + + // Compile regexes once up front so syntax errors are reported here rather + // than from inside helpers (in particular, from the deferred lambda at + // generate time). + cm::optional propertyNameRegex; + cm::optional propertyValueRegex; + if (parsedArgs.PropertyNameRegex) { + cmsys::RegularExpression re; + if (!re.compile(*parsedArgs.PropertyNameRegex)) { + return FatalError(status, + cmStrCat("PROPERTY_NAME_REGEX regular expression \"", + *parsedArgs.PropertyNameRegex, + "\" cannot compile.")); + } + propertyNameRegex = std::move(re); + } + if (parsedArgs.PropertyValueRegex) { + cmsys::RegularExpression re; + if (!re.compile(*parsedArgs.PropertyValueRegex)) { + return FatalError(status, + cmStrCat("PROPERTY_VALUE_REGEX regular expression \"", + *parsedArgs.PropertyValueRegex, + "\" cannot compile.")); + } + propertyValueRegex = std::move(re); + } + + // The message opens with a leading banner line. The internal + // __CMAKE_PRINT_PROPERTIES marker (not part of the public interface) selects + // the legacy format instead; cmake_print_properties() sets it to reproduce + // its historical leading blank line. + std::string const messagePrefix = parsedArgs.CmakePrintProperties + ? std::string("\n") + : std::string("Printing properties...\n"); + + if (parsedArgsMode.Deferred) { + return PrintTargetPropertiesDeferred( + items, parsedArgs.Named, all, parsedArgs.PropertyNameRegex, + parsedArgs.PropertyValueRegex, std::move(propertyNameRegex), + std::move(propertyValueRegex), parsedArgsMode.FollowDependencies, + messagePrefix, status); + } + + return PrintPropertiesConfigureTime( + status, parsedArgs.Named, all, items, kind, parsedArgs.PropertyNameRegex, + parsedArgs.PropertyValueRegex, propertyNameRegex, propertyValueRegex, + messagePrefix); +} +} bool cmCMakeLanguageCommand(std::vector const& args, cmExecutionStatus& status) { @@ -1007,5 +1657,13 @@ bool cmCMakeLanguageCommand(std::vector const& args, FatalError(status, "TRACE OFF request without a corresponding TRACE ON"); } + if (expArgs[expArg] == "PRINT_PROPERTIES") { + ++expArg; + finishArgs(); + std::vector const printPropertyArgs(expArgs.begin() + expArg, + expArgs.end()); + return cmCMakeLanguageCommandPRINT_PROPERTIES(printPropertyArgs, status); + } + return FatalError(status, "called with unknown meta-operation"); } diff --git a/Source/cmDirectoryPropertyHelper.h b/Source/cmDirectoryPropertyHelper.h index 209683a378..b68a635c63 100644 --- a/Source/cmDirectoryPropertyHelper.h +++ b/Source/cmDirectoryPropertyHelper.h @@ -4,9 +4,8 @@ #include -#include "cmValue.h" - class cmMakefile; +class cmValue; enum class cmGetDirectoryPropertyResult { diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index e329b79a7d..6252893b5f 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -2,11 +2,6 @@ file LICENSE.rst or https://cmake.org/licensing for details. */ #include "cmGetPropertyCommand.h" -#include - -#include -#include - #include "cmDirectoryPropertyHelper.h" #include "cmExecutionStatus.h" #include "cmFileSet.h" @@ -510,6 +505,17 @@ bool LookupSourceProperty( return false; } +bool LookupSourceProperty(cmExecutionStatus& status, std::string const& name, + std::string const& propertyName, cmValue& out) +{ + std::vector noDirectories; + std::vector noTargetDirectories; + return LookupSourceProperty(status, name, propertyName, + /*sourceFileDirectoryOptionEnabled=*/false, + /*sourceFileTargetOptionEnabled=*/false, + noDirectories, noTargetDirectories, out); +} + bool LookupTestProperty(cmExecutionStatus& status, std::string const& name, std::string const& propertyName, bool testDirectoryOptionEnabled, @@ -532,6 +538,15 @@ bool LookupTestProperty(cmExecutionStatus& status, std::string const& name, return false; } +bool LookupTestProperty(cmExecutionStatus& status, std::string const& name, + std::string const& propertyName, cmValue& out) +{ + std::string noDirectory; + return LookupTestProperty(status, name, propertyName, + /*testDirectoryOptionEnabled=*/false, noDirectory, + out); +} + bool LookupCacheProperty(cmExecutionStatus& status, std::string const& name, std::string const& propertyName, cmValue& out) { diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h index 1f2a712f5f..d86215dda4 100644 --- a/Source/cmGetPropertyCommand.h +++ b/Source/cmGetPropertyCommand.h @@ -7,9 +7,8 @@ #include #include -#include "cmValue.h" - class cmExecutionStatus; +class cmValue; namespace GetPropertyCommand { @@ -33,11 +32,19 @@ bool LookupSourceProperty( std::vector& sourceFileDirectories, std::vector& sourceFileTargetDirectories, cmValue& out); +// Convenience overload: no DIRECTORY / TARGET_DIRECTORY scoping. +bool LookupSourceProperty(cmExecutionStatus& status, std::string const& name, + std::string const& propertyName, cmValue& out); + bool LookupTestProperty(cmExecutionStatus& status, std::string const& name, std::string const& propertyName, bool testDirectoryOptionEnabled, std::string& testDirectory, cmValue& out); +// Convenience overload: no DIRECTORY scoping. +bool LookupTestProperty(cmExecutionStatus& status, std::string const& name, + std::string const& propertyName, cmValue& out); + bool LookupCacheProperty(cmExecutionStatus& status, std::string const& name, std::string const& propertyName, cmValue& out); diff --git a/Source/cmSourceFilePropertyHelper.h b/Source/cmSourceFilePropertyHelper.h index 62e9bc5ba3..b5ac958475 100644 --- a/Source/cmSourceFilePropertyHelper.h +++ b/Source/cmSourceFilePropertyHelper.h @@ -5,9 +5,8 @@ #include #include -#include "cmValue.h" - class cmExecutionStatus; +class cmValue; enum class cmGetSourceFilePropertyResult { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index fe0027a5e6..54f1c4953a 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -163,6 +163,11 @@ struct FileSetType void AddFileSet(std::string const& name, cm::FileSetMetadata::Visibility vis, cmListFileBacktrace bt); + + // We recompute this every time since some of the property + // names depend on names of the file sets + cmPropertyMap GetProperties(cmTarget const* tgt, + cmTargetInternals const* impl) const; }; struct UsageRequirementProperty @@ -874,6 +879,43 @@ void FileSetType::AddFileSet(std::string const& name, } } +cmPropertyMap FileSetType::GetProperties(cmTarget const* tgt, + cmTargetInternals const* impl) const +{ + std::set propNames{ std::string(this->DefaultDirectoryProperty), + std::string(this->DefaultPathProperty), + std::string(this->SelfEntries.PropertyName), + std::string( + this->InterfaceEntries.PropertyName) }; + + for (auto const& entry : this->SelfEntries.Entries) { + std::string directoryPropertyName = + cmStrCat(this->DirectoryPrefix, entry.Value); + std::string pathPropertyName = cmStrCat(this->PathPrefix, entry.Value); + propNames.emplace(directoryPropertyName); + propNames.emplace(pathPropertyName); + } + + for (auto const& entry : this->InterfaceEntries.Entries) { + std::string directoryPropertyName = + cmStrCat(this->DirectoryPrefix, entry.Value); + std::string pathPropertyName = cmStrCat(this->PathPrefix, entry.Value); + propNames.emplace(directoryPropertyName); + propNames.emplace(pathPropertyName); + } + + cmPropertyMap propertyMap; + + for (std::string const& prop : propNames) { + auto value = this->ReadProperties(tgt, impl, prop); + if (value.first) { + propertyMap.SetProperty(prop, value.second); + } + } + + return propertyMap; +} + template bool UsageRequirementProperty::Write( cmTargetInternals const* impl, cm::optional const& bt, @@ -2669,13 +2711,7 @@ void cmTarget::CheckProperty(std::string const& prop, } } -cmValue cmTarget::GetComputedProperty(std::string const& prop, - cmMakefile& mf) const -{ - return cmTargetPropertyComputer::GetProperty(this, prop, mf); -} - -cmValue cmTarget::GetProperty(std::string const& prop) const +std::unordered_set const& cmTarget::GetSpecialPropertyNames() { static std::unordered_set const specialProps{ propC_STANDARD, @@ -2710,6 +2746,18 @@ cmValue cmTarget::GetProperty(std::string const& prop) const propIMPORTED_CXX_MODULES_COMPILE_OPTIONS, propIMPORTED_CXX_MODULES_LINK_LIBRARIES, }; + return specialProps; +} + +cmValue cmTarget::GetComputedProperty(std::string const& prop, + cmMakefile& mf) const +{ + return cmTargetPropertyComputer::GetProperty(this, prop, mf); +} + +cmValue cmTarget::GetProperty(std::string const& prop) const +{ + auto const& specialProps = cmTarget::GetSpecialPropertyNames(); if (specialProps.count(prop)) { if (prop == propC_STANDARD || prop == propCXX_STANDARD || prop == propCUDA_STANDARD || prop == propHIP_STANDARD || @@ -2867,6 +2915,33 @@ cmPropertyMap const& cmTarget::GetDirectProperties() const return this->impl->Properties; } +cmPropertyMap cmTarget::GetExtendedProperties() const +{ + // Get properties in the base property map + cmPropertyMap pm = this->impl->Properties; + + // Get special properties + auto const& specialProps = cmTarget::GetSpecialPropertyNames(); + for (auto const& propName : specialProps) { + cmValue propValue = this->GetProperty(propName); + if (propValue) { + pm.SetProperty(propName, propValue); + } + } + + // Get fileset properties + for (auto const& fileSetType : this->impl->FileSetTypes) { + cmPropertyMap fileSetProperties = + fileSetType.second.GetProperties(this, this->impl.get()); + auto fileSetPropertiesList = fileSetProperties.GetList(); + for (auto const& propPair : fileSetPropertiesList) { + pm.SetProperty(propPair.first, propPair.second); + } + } + + return pm; +} + bool cmTarget::IsDLLPlatform() const { return this->impl->IsDLLPlatform; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index e16fdedea2..0997fdef6f 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -232,9 +233,15 @@ public: std::string const& GetSafeProperty(std::string const& prop) const; bool GetPropertyAsBool(std::string const& prop) const; void CheckProperty(std::string const& prop, cmMakefile* context) const; + static std::unordered_set const& GetSpecialPropertyNames(); cmValue GetComputedProperty(std::string const& prop, cmMakefile& mf) const; //! Get properties set directly on this target (no special/computed/chained) cmPropertyMap const& GetDirectProperties() const; + /** + * Get the properties in the property map plus + * special properties, fileset properties, etc. + */ + cmPropertyMap GetExtendedProperties() const; //! Return whether or not the target is for a DLL platform. bool IsDLLPlatform() const; diff --git a/Source/cmTargetPropertyHelper.cxx b/Source/cmTargetPropertyHelper.cxx index 32f9376e97..07dcf2bf0d 100644 --- a/Source/cmTargetPropertyHelper.cxx +++ b/Source/cmTargetPropertyHelper.cxx @@ -2,8 +2,6 @@ file LICENSE.rst or https://cmake.org/licensing for details. */ #include "cmTargetPropertyHelper.h" -#include - #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmTarget.h" diff --git a/Source/cmTargetPropertyHelper.h b/Source/cmTargetPropertyHelper.h index 9adad86f1b..319c2625d4 100644 --- a/Source/cmTargetPropertyHelper.h +++ b/Source/cmTargetPropertyHelper.h @@ -4,8 +4,6 @@ #include -#include "cmValue.h" - class cmMakefile; class cmTarget; class cmValue; diff --git a/Source/cmTestPropertyHelper.h b/Source/cmTestPropertyHelper.h index 2a0ea17ca9..9e89b7288f 100644 --- a/Source/cmTestPropertyHelper.h +++ b/Source/cmTestPropertyHelper.h @@ -4,9 +4,8 @@ #include -#include "cmValue.h" - class cmExecutionStatus; +class cmValue; enum class cmGetTestPropertyResult { diff --git a/Tests/RunCMake/PrintHelpers/PrintPropertiesArgForwarding-stdout.txt b/Tests/RunCMake/PrintHelpers/PrintPropertiesArgForwarding-stdout.txt new file mode 100644 index 0000000000..03903e95dc --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/PrintPropertiesArgForwarding-stdout.txt @@ -0,0 +1,20 @@ +.*--.* + +Properties for TARGET mylib: + +mylib\.TYPE = "STATIC_LIBRARY" + +mylib\.NAME = "mylib" + +--.* + +Printing all properties for TARGET mylib matching name '\^MY_PROP_' and value '\^alpha\$': + +mylib\.MY_PROP_X = "alpha" + +-- Configuring done .* +--.* + +Printing all properties for TARGET mylib \(and all reachable\) matching name '\^MY_PROP_' and value '\^alpha\$': + +mylib\.MY_PROP_X = "alpha" + +mydep\.MY_PROP_X = "alpha" + +--.* + +Properties for TARGET mylib: + +mylib\.TYPE = "STATIC_LIBRARY" + +-- Generating done .* diff --git a/Tests/RunCMake/PrintHelpers/PrintPropertiesArgForwarding.cmake b/Tests/RunCMake/PrintHelpers/PrintPropertiesArgForwarding.cmake new file mode 100644 index 0000000000..2a0b36b0ad --- /dev/null +++ b/Tests/RunCMake/PrintHelpers/PrintPropertiesArgForwarding.cmake @@ -0,0 +1,49 @@ +include(CMakePrintHelpers) +enable_language(C) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/stub.c" "void stub(void) {}\n") + +add_library(mydep STATIC "${CMAKE_CURRENT_BINARY_DIR}/stub.c") +set_target_properties(mydep PROPERTIES + MY_PROP_X "alpha" + MY_PROP_Y "beta" + OTHER_PROP "alpha" +) + +add_library(mylib STATIC "${CMAKE_CURRENT_BINARY_DIR}/stub.c") +target_link_libraries(mylib PRIVATE mydep) +set_target_properties(mylib PROPERTIES + MY_PROP_X "alpha" + MY_PROP_Y "beta" + OTHER_PROP "alpha" +) + +# (1) configure-time, specific properties — exercises forwarding of TARGETS +# + PROPERTIES . +cmake_print_properties(TARGETS mylib PROPERTIES TYPE NAME) + +# (2) configure-time, ALL + both regex keywords — exercises forwarding of +# PROPERTY_NAME_REGEX and PROPERTY_VALUE_REGEX together. +cmake_print_properties( + TARGETS mylib + PROPERTIES ALL + PROPERTY_NAME_REGEX "^MY_PROP_" + PROPERTY_VALUE_REGEX "^alpha$" +) + +# (3) DEFERRED + FOLLOW_DEPENDENCIES + ALL + both regexes — exercises +# forwarding of every new keyword at once, and verifies the walker +# actually reaches the PRIVATE dep at generate time (mydep must appear +# in the output, not just mylib). +cmake_print_properties( + TARGETS mylib + DEFERRED + FOLLOW_DEPENDENCIES + PROPERTIES ALL + PROPERTY_NAME_REGEX "^MY_PROP_" + PROPERTY_VALUE_REGEX "^alpha$" +) + +# (4) DEFERRED alone + specific name — exercises DEFERRED forwarding by +# itself (no dependency walk; mydep must NOT appear). +cmake_print_properties(TARGETS mylib DEFERRED PROPERTIES TYPE) diff --git a/Tests/RunCMake/cmake_language/PrintProperties-stdout.txt b/Tests/RunCMake/cmake_language/PrintProperties-stdout.txt new file mode 100644 index 0000000000..1eb9baa82d --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintProperties-stdout.txt @@ -0,0 +1,15 @@ +-- Printing properties\.\.\. + +Properties for TARGET nothing: + +nothing\.LINKER_LANGUAGE = + +nothing\.TYPE = \"STATIC_LIBRARY\" + +Properties for TARGET something: + +something\.LINKER_LANGUAGE = + +something\.TYPE = \"EXECUTABLE\" + +-- Printing properties\.\.\. + +Properties for SOURCE nothing\.c: + +nothing\.c\.COMPILE_DEFINITIONS = + +nothing\.c\.LANGUAGE = \"C\" + +Properties for SOURCE something\.c: + +something\.c\.COMPILE_DEFINITIONS = \"SOMETHING=1\" + +something\.c\.LANGUAGE = \"C\" diff --git a/Tests/RunCMake/cmake_language/PrintProperties.cmake b/Tests/RunCMake/cmake_language/PrintProperties.cmake new file mode 100644 index 0000000000..82442ddfb5 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintProperties.cmake @@ -0,0 +1,26 @@ +enable_language(C) + +set_property(SOURCE nothing.c PROPERTY LANGUAGE C) +set_property(SOURCE something.c PROPERTY + COMPILE_DEFINITIONS SOMETHING=1) + +add_library(nothing STATIC nothing.c nothing.h) + +add_executable(something something.c something.h) +target_link_libraries(something PUBLIC nothing) + +cmake_language( + PRINT_PROPERTIES + TARGETS nothing something + NAMED + LINKER_LANGUAGE + TYPE +) + +cmake_language( + PRINT_PROPERTIES + SOURCES nothing.c something.c + NAMED + COMPILE_DEFINITIONS + LANGUAGE +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAll-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesAll-stdout.txt new file mode 100644 index 0000000000..9d762527f4 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAll-stdout.txt @@ -0,0 +1,14 @@ +-- Printing properties\.\.\. + +All properties for TARGET mylib: +.* +mylib.HEADER_DIRS = \"[^\"]*/Tests/RunCMake/cmake_language\" +.* +mylib.HEADER_DIRS_HEADERS = \"[^\"]*/Tests/RunCMake/cmake_language\" +.* +mylib.HEADER_SET = \"[^\"]*/Tests/RunCMake/cmake_language/nothing.h\" +.* +mylib.HEADER_SETS = \"HEADERS\" +.* +mylib.HEADER_SET_HEADERS = \"[^\"]*/Tests/RunCMake/cmake_language/nothing.h\" +.* +mylib.IMPORTED = \"FALSE\" +.* +mylib.INCLUDE_DIRECTORIES = \"\$\\" +.* +mylib.INTERFACE_HEADER_SETS = \"HEADERS\" +.* +mylib.INTERFACE_INCLUDE_DIRECTORIES = \"\$\\" +.* +mylib.NAME = \"mylib\" +.* +mylib.SOURCES = \"nothing.c\" +.* +mylib.TYPE = \"STATIC_LIBRARY\" diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAll.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesAll.cmake new file mode 100644 index 0000000000..d19ef0ef97 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAll.cmake @@ -0,0 +1,22 @@ +enable_language(C) + +add_library(mylib STATIC nothing.c) + +target_sources(mylib + PUBLIC + FILE_SET HEADERS + FILES nothing.h +) + +add_executable(something something.c something.h) + +target_link_libraries(something PUBLIC nothing) + +# Printing all for library. To reduce maintenance burden, we only pin a few +# properties in the expected output instead of listing every property reported +# by ALL. +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + ALL +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllAndNamed-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesAllAndNamed-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllAndNamed-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllAndNamed-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesAllAndNamed-stderr.txt new file mode 100644 index 0000000000..f9ade1d7e3 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllAndNamed-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at PrintPropertiesAllAndNamed\.cmake:[0-9]+ \(cmake_language\): + cmake_language ALL and NAMED keywords in cmake_language\(PRINT_PROPERTIES\) + call are mutually exclusive\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllAndNamed.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesAllAndNamed.cmake new file mode 100644 index 0000000000..a8d49ae7c9 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllAndNamed.cmake @@ -0,0 +1,10 @@ +enable_language(C) +add_library(mylib STATIC nothing.c) + +# ALL and NAMED are mutually exclusive. +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + ALL + NAMED MY_PROP +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowBothRegex-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowBothRegex-stdout.txt new file mode 100644 index 0000000000..0004508e97 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowBothRegex-stdout.txt @@ -0,0 +1,7 @@ +-- Configuring done .* +-- Printing properties\.\.\. + +All properties for TARGET mylib \(and all reachable\) matching name '\^MY_' and value 'alpha': + +mylib\.MY_PROP = "alpha-mylib" + +leaflib\.MY_PROP = "alpha-leaf" + +-- Generating done .* diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowBothRegex.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowBothRegex.cmake new file mode 100644 index 0000000000..8a222b305a --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowBothRegex.cmake @@ -0,0 +1,29 @@ +enable_language(C) + +add_library(leaflib STATIC nothing.c) +set_target_properties(leaflib PROPERTIES + MY_PROP "alpha-leaf" + MY_OTHER "beta-leaf" + OTHER_PROP "alpha-other" +) + +add_library(mylib STATIC nothing.c) +target_link_libraries(mylib PUBLIC leaflib) +set_target_properties(mylib PROPERTIES + MY_PROP "alpha-mylib" + MY_OTHER "beta-mylib" + OTHER_PROP "alpha-other" +) + +# Only properties whose name starts with MY_ AND whose value contains +# "alpha" should print: MY_PROP on both targets. +# MY_OTHER fails the value regex; OTHER_PROP fails the name regex. +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + DEFERRED + FOLLOW_DEPENDENCIES + ALL + PROPERTY_NAME_REGEX "^MY_" + PROPERTY_VALUE_REGEX "alpha" +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowDependencies-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowDependencies-stdout.txt new file mode 100644 index 0000000000..88d379e6d6 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowDependencies-stdout.txt @@ -0,0 +1,13 @@ +-- Configuring done .* +-- Printing properties\.\.\. + +All properties for TARGET mylib \(and all reachable\) matching name '\^MY_PROP': + +mylib\.MY_PROP = "mylib" + +mylib\.MY_PROP_2 = "mylib2" + +intermediate\.MY_PROP = "intermediate" + +intermediate\.MY_PROP_2 = "intermediate2" + +leaflib\.MY_PROP = "leaf" + +leaflib\.MY_PROP_2 = "leaf2" + +linkonlylib\.MY_PROP = "linkonly" + +linkonlylib\.MY_PROP_2 = "linkonly2" + +-- Generating done .* diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowDependencies.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowDependencies.cmake new file mode 100644 index 0000000000..aefd9b2aaf --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllFollowDependencies.cmake @@ -0,0 +1,42 @@ +enable_language(C) + +add_library(leaflib STATIC nothing.c) +set_target_properties(leaflib PROPERTIES + MY_PROP "leaf" + MY_PROP_2 "leaf2" +) + +add_library(linkonlylib STATIC nothing.c) +set_target_properties(linkonlylib PROPERTIES + MY_PROP "linkonly" + MY_PROP_2 "linkonly2" +) + +add_library(intermediate STATIC nothing.c) +target_link_libraries(intermediate + PRIVATE leaflib + INTERFACE $ +) +set_target_properties(intermediate PROPERTIES + MY_PROP "intermediate" + MY_PROP_2 "intermediate2" +) + +add_library(mylib STATIC nothing.c) +target_link_libraries(mylib PUBLIC intermediate) +set_target_properties(mylib PROPERTIES + MY_PROP "mylib" + MY_PROP_2 "mylib2" +) + +# ALL + FOLLOW_DEPENDENCIES with a tight name regex pins the unified +# printer's ALL branch: each reachable target's matching properties show +# up in walk order, covering PRIVATE and $ traversal. +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + DEFERRED + FOLLOW_DEPENDENCIES + ALL + PROPERTY_NAME_REGEX "^MY_PROP" +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllRequiresTargets-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesAllRequiresTargets-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllRequiresTargets-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllRequiresTargets-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesAllRequiresTargets-stderr.txt new file mode 100644 index 0000000000..31a54cf386 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllRequiresTargets-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at PrintPropertiesAllRequiresTargets\.cmake:[0-9]+ \(cmake_language\): + cmake_language ALL keyword in cmake_language\(PRINT_PROPERTIES\) call is only + valid with the TARGETS scope\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesAllRequiresTargets.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesAllRequiresTargets.cmake new file mode 100644 index 0000000000..2f3560576d --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesAllRequiresTargets.cmake @@ -0,0 +1,6 @@ +# ALL is only valid with the TARGETS scope. +cmake_language( + PRINT_PROPERTIES + SOURCES nothing.c + ALL +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesCacheEntries-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesCacheEntries-stdout.txt new file mode 100644 index 0000000000..cb674875d8 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesCacheEntries-stdout.txt @@ -0,0 +1,9 @@ +-- Printing properties\.\.\. + Properties for CACHE MY_CACHE_A: + MY_CACHE_A\.TYPE = "STRING" + MY_CACHE_A\.HELPSTRING = "help A" + MY_CACHE_A\.NOT_SET = + Properties for CACHE MY_CACHE_B: + MY_CACHE_B\.TYPE = "PATH" + MY_CACHE_B\.HELPSTRING = "help B" + MY_CACHE_B\.NOT_SET = diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesCacheEntries.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesCacheEntries.cmake new file mode 100644 index 0000000000..70de81e852 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesCacheEntries.cmake @@ -0,0 +1,11 @@ +set(MY_CACHE_A "a_val" CACHE STRING "help A") +set(MY_CACHE_B "b_val" CACHE PATH "help B") + +cmake_language( + PRINT_PROPERTIES + CACHE_ENTRIES MY_CACHE_A MY_CACHE_B + NAMED + TYPE + HELPSTRING + NOT_SET +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesConfigSpecific-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesConfigSpecific-stdout.txt new file mode 100644 index 0000000000..2167d5b66d --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesConfigSpecific-stdout.txt @@ -0,0 +1,7 @@ +-- Configuring done .* +-- Printing properties\.\.\. + +Properties for TARGET mylib \(and all reachable\): + +mylib\.MY_PROP = "mylib" + +debug_dep\.MY_PROP = "debug" + +-- Generating done .* diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesConfigSpecific.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesConfigSpecific.cmake new file mode 100644 index 0000000000..7740d55ae2 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesConfigSpecific.cmake @@ -0,0 +1,25 @@ +enable_language(C) + +add_library(debug_dep STATIC nothing.c) +set_target_properties(debug_dep PROPERTIES MY_PROP "debug") + +add_library(release_dep STATIC nothing.c) +set_target_properties(release_dep PROPERTIES MY_PROP "release") + +add_library(mylib STATIC nothing.c) +target_link_libraries(mylib PRIVATE + $<$:debug_dep> + $<$:release_dep> +) +set_target_properties(mylib PROPERTIES MY_PROP "mylib") + +# Driven with -DCMAKE_BUILD_TYPE=Debug - only debug_dep should be reached +# by the walker, since the $ arm evaluates to empty under +# Debug. +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + DEFERRED + FOLLOW_DEPENDENCIES + NAMED MY_PROP +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesDeferred-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesDeferred-stdout.txt new file mode 100644 index 0000000000..b16a485791 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesDeferred-stdout.txt @@ -0,0 +1,6 @@ +-- Configuring done .* +-- Printing properties\.\.\. + +Properties for TARGET mylib: + +mylib\.MY_PROP = "mylib_value" + +-- Generating done .* diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesDeferred.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesDeferred.cmake new file mode 100644 index 0000000000..917d279480 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesDeferred.cmake @@ -0,0 +1,11 @@ +enable_language(C) + +add_library(mylib STATIC nothing.c) +set_target_properties(mylib PROPERTIES MY_PROP "mylib_value") + +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + DEFERRED + NAMED MY_PROP +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesDeferredRequiresTargets-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesDeferredRequiresTargets-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesDeferredRequiresTargets-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesDeferredRequiresTargets-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesDeferredRequiresTargets-stderr.txt new file mode 100644 index 0000000000..665e6036d9 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesDeferredRequiresTargets-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at PrintPropertiesDeferredRequiresTargets\.cmake:[0-9]+ \(cmake_language\): + cmake_language DEFERRED keyword in cmake_language\(PRINT_PROPERTIES\) call is + only valid with the TARGETS scope\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesDeferredRequiresTargets.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesDeferredRequiresTargets.cmake new file mode 100644 index 0000000000..948348b870 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesDeferredRequiresTargets.cmake @@ -0,0 +1,8 @@ +# DEFERRED is only meaningful with TARGETS - pairing it with a non-TARGETS +# scope must produce a fatal error. +cmake_language( + PRINT_PROPERTIES + SOURCES nothing.c + DEFERRED + NAMED LANGUAGE +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesDirectories-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesDirectories-stdout.txt new file mode 100644 index 0000000000..269e79ad7b --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesDirectories-stdout.txt @@ -0,0 +1,9 @@ +-- Printing properties\.\.\. + Properties for DIRECTORY \.: + \.\.MY_PROP = "top_val" + \.\.LABELS = "top_label" + \.\.NOT_SET = + Properties for DIRECTORY PrintPropertiesDirectories-sub: + PrintPropertiesDirectories-sub\.MY_PROP = "sub_val" + PrintPropertiesDirectories-sub\.LABELS = "sub_label" + PrintPropertiesDirectories-sub\.NOT_SET = diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesDirectories-sub/CMakeLists.txt b/Tests/RunCMake/cmake_language/PrintPropertiesDirectories-sub/CMakeLists.txt new file mode 100644 index 0000000000..438e63c773 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesDirectories-sub/CMakeLists.txt @@ -0,0 +1 @@ +set_directory_properties(PROPERTIES MY_PROP "sub_val" LABELS "sub_label") diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesDirectories.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesDirectories.cmake new file mode 100644 index 0000000000..7255f0a889 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesDirectories.cmake @@ -0,0 +1,11 @@ +set_directory_properties(PROPERTIES MY_PROP "top_val" LABELS "top_label") +add_subdirectory(PrintPropertiesDirectories-sub) + +cmake_language( + PRINT_PROPERTIES + DIRECTORIES . PrintPropertiesDirectories-sub + NAMED + MY_PROP + LABELS + NOT_SET +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesEmptyMatch-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesEmptyMatch-stdout.txt new file mode 100644 index 0000000000..3b7d3c2d68 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesEmptyMatch-stdout.txt @@ -0,0 +1,16 @@ +-- Configuring done .* +CMake Warning at PrintPropertiesEmptyMatch\.cmake:[0-9]+ \(cmake_language\): + No properties for TARGET mylib matching name 'ZZZ_NO_SUCH_PROPERTY' in + cmake_language\(PRINT_PROPERTIES \.\.\.\)\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Warning at PrintPropertiesEmptyMatch\.cmake:[0-9]+ \(cmake_language\): + No properties for TARGET mylib matching value 'ZZZ_NO_SUCH_VALUE' in + cmake_language\(PRINT_PROPERTIES \.\.\.\)\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) + + +-- Generating done .* diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesEmptyMatch.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesEmptyMatch.cmake new file mode 100644 index 0000000000..4394693c2a --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesEmptyMatch.cmake @@ -0,0 +1,24 @@ +enable_language(C) + +add_library(libdep INTERFACE) +add_library(mylib STATIC nothing.c) +target_link_libraries(mylib PRIVATE libdep) + +# One call per regex so each warning text is short and won't wrap. +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + DEFERRED + FOLLOW_DEPENDENCIES + ALL + PROPERTY_NAME_REGEX "ZZZ_NO_SUCH_PROPERTY" +) + +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + DEFERRED + FOLLOW_DEPENDENCIES + ALL + PROPERTY_VALUE_REGEX "ZZZ_NO_SUCH_VALUE" +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesFiltering-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesFiltering-stdout.txt new file mode 100644 index 0000000000..8bc46ac186 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesFiltering-stdout.txt @@ -0,0 +1,15 @@ +-- Printing properties\.\.\. + +All properties for TARGET mylib matching name 'INTERFACE': + +mylib.INTERFACE_CXX_MODULE_SETS = \"\" + +mylib.INTERFACE_HEADER_SETS = \"HEADERS\" + +mylib.INTERFACE_INCLUDE_DIRECTORIES = \"\$\\" + +mylib.INTERFACE_SOURCE_SETS = \"\" + +-- Printing properties\.\.\. + +All properties for TARGET mylib matching value 'HEADERS': + +mylib.HEADER_SETS = \"HEADERS\" + +mylib.INTERFACE_HEADER_SETS = \"HEADERS\" + +-- Printing properties\.\.\. + +All properties for TARGET mylib matching name 'INTERFACE' and value 'HEADERS': + +mylib.INTERFACE_HEADER_SETS = \"HEADERS\" diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesFiltering.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesFiltering.cmake new file mode 100644 index 0000000000..292a0255d1 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesFiltering.cmake @@ -0,0 +1,38 @@ +enable_language(C) + +add_library(mylib STATIC nothing.c) + +target_sources(mylib + PUBLIC + FILE_SET HEADERS + FILES nothing.h +) + +# Add a property +set_target_properties(mylib + PROPERTIES + some_property some_value + another_property another_value +) + +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + ALL + PROPERTY_NAME_REGEX INTERFACE +) + +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + ALL + PROPERTY_VALUE_REGEX HEADERS +) + +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + ALL + PROPERTY_NAME_REGEX INTERFACE + PROPERTY_VALUE_REGEX HEADERS +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesFollowDependencies-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesFollowDependencies-stdout.txt new file mode 100644 index 0000000000..7947ae6a63 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesFollowDependencies-stdout.txt @@ -0,0 +1,13 @@ +-- Configuring done .* +-- Printing properties\.\.\. + +Properties for TARGET mylib \(and all reachable\): + +mylib\.MY_PROP = "mylib" + +mylib\.MY_PROP_2 = "mylib2" + +intermediate\.MY_PROP = "intermediate" + +intermediate\.MY_PROP_2 = "intermediate2" + +leaflib\.MY_PROP = "leaf" + +leaflib\.MY_PROP_2 = "leaf2" + +linkonlylib\.MY_PROP = "linkonly" + +linkonlylib\.MY_PROP_2 = "linkonly2" + +-- Generating done .* diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesFollowDependencies.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesFollowDependencies.cmake new file mode 100644 index 0000000000..2f6d820218 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesFollowDependencies.cmake @@ -0,0 +1,38 @@ +enable_language(C) + +add_library(leaflib STATIC nothing.c) +set_target_properties(leaflib PROPERTIES + MY_PROP "leaf" + MY_PROP_2 "leaf2" +) + +add_library(linkonlylib STATIC nothing.c) +set_target_properties(linkonlylib PROPERTIES + MY_PROP "linkonly" + MY_PROP_2 "linkonly2" +) + +add_library(intermediate STATIC nothing.c) +target_link_libraries(intermediate + PRIVATE leaflib + INTERFACE $ +) +set_target_properties(intermediate PROPERTIES + MY_PROP "intermediate" + MY_PROP_2 "intermediate2" +) + +add_library(mylib STATIC nothing.c) +target_link_libraries(mylib PUBLIC intermediate) +set_target_properties(mylib PROPERTIES + MY_PROP "mylib" + MY_PROP_2 "mylib2" +) + +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + DEFERRED + FOLLOW_DEPENDENCIES + NAMED MY_PROP MY_PROP_2 +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesFollowImpliesDeferred-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesFollowImpliesDeferred-stdout.txt new file mode 100644 index 0000000000..81e2ae7ea6 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesFollowImpliesDeferred-stdout.txt @@ -0,0 +1,7 @@ +-- Configuring done .* +-- Printing properties\.\.\. + +Properties for TARGET mylib \(and all reachable\): + +mylib\.MY_PROP = "mylib" + +leaflib\.MY_PROP = "leaf" + +-- Generating done .* diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesFollowImpliesDeferred.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesFollowImpliesDeferred.cmake new file mode 100644 index 0000000000..71b24156b6 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesFollowImpliesDeferred.cmake @@ -0,0 +1,15 @@ +enable_language(C) + +add_library(leaflib STATIC nothing.c) +set_target_properties(leaflib PROPERTIES MY_PROP "leaf") + +add_library(mylib STATIC nothing.c) +target_link_libraries(mylib PUBLIC leaflib) +set_target_properties(mylib PROPERTIES MY_PROP "mylib") + +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + FOLLOW_DEPENDENCIES + NAMED MY_PROP +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesFollowRequiresTargets-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesFollowRequiresTargets-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesFollowRequiresTargets-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesFollowRequiresTargets-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesFollowRequiresTargets-stderr.txt new file mode 100644 index 0000000000..7bfb5a05d3 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesFollowRequiresTargets-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at PrintPropertiesFollowRequiresTargets\.cmake:[0-9]+ \(cmake_language\): + cmake_language FOLLOW_DEPENDENCIES keyword in + cmake_language\(PRINT_PROPERTIES\) call is only valid with the TARGETS scope\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesFollowRequiresTargets.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesFollowRequiresTargets.cmake new file mode 100644 index 0000000000..d3193698aa --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesFollowRequiresTargets.cmake @@ -0,0 +1,7 @@ +# FOLLOW_DEPENDENCIES is only valid with the TARGETS scope. +cmake_language( + PRINT_PROPERTIES + SOURCES nothing.c + FOLLOW_DEPENDENCIES + NAMED LANGUAGE +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesImplicitAll-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesImplicitAll-stdout.txt new file mode 100644 index 0000000000..2add7b75a9 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesImplicitAll-stdout.txt @@ -0,0 +1,3 @@ +-- Printing properties\.\.\. + +All properties for TARGET mylib matching name '\^MY_MARKER\$': + +mylib\.MY_MARKER = "marker_value" diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesImplicitAll.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesImplicitAll.cmake new file mode 100644 index 0000000000..5442e2e681 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesImplicitAll.cmake @@ -0,0 +1,12 @@ +enable_language(C) + +add_library(mylib STATIC nothing.c) +set_target_properties(mylib PROPERTIES MY_MARKER "marker_value") + +# No ALL or NAMED keyword - ALL should be implied. Narrow with a regex so +# the output is deterministic across cmake builds. +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + PROPERTY_NAME_REGEX "^MY_MARKER$" +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLegacyFlagRequiresNamed-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesLegacyFlagRequiresNamed-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLegacyFlagRequiresNamed-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLegacyFlagRequiresNamed-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesLegacyFlagRequiresNamed-stderr.txt new file mode 100644 index 0000000000..9a20f9f5fe --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLegacyFlagRequiresNamed-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at PrintPropertiesLegacyFlagRequiresNamed\.cmake:[0-9]+ \(cmake_language\): + cmake_language __CMAKE_PRINT_PROPERTIES in cmake_language\(PRINT_PROPERTIES\) + call is only valid with NAMED\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLegacyFlagRequiresNamed.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesLegacyFlagRequiresNamed.cmake new file mode 100644 index 0000000000..b12dfcf2eb --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLegacyFlagRequiresNamed.cmake @@ -0,0 +1,3 @@ +# __CMAKE_PRINT_PROPERTIES marks the legacy cmake_print_properties() call, which +# is always NAMED; here no NAMED is given (implicit ALL), which rejects it. +cmake_language(PRINT_PROPERTIES TARGETS some_target __CMAKE_PRINT_PROPERTIES) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLocationImported-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesLocationImported-stdout.txt new file mode 100644 index 0000000000..78a5324902 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLocationImported-stdout.txt @@ -0,0 +1,3 @@ +-- Printing properties\.\.\. + +Properties for TARGET myimp: + +myimp\.LOCATION = "/imported/libmyimp\.so" diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLocationImported.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesLocationImported.cmake new file mode 100644 index 0000000000..770ad9d7e3 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLocationImported.cmake @@ -0,0 +1,5 @@ +add_library(myimp SHARED IMPORTED) +set_target_properties(myimp PROPERTIES IMPORTED_LOCATION "/imported/libmyimp.so") + +# Reading LOCATION from an imported target succeeds. +cmake_language(PRINT_PROPERTIES TARGETS myimp NAMED LOCATION) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLocationNonImported-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesLocationNonImported-stderr.txt new file mode 100644 index 0000000000..a7f67e5f86 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLocationNonImported-stderr.txt @@ -0,0 +1,19 @@ +CMake Warning at PrintPropertiesLocationNonImported\.cmake:[0-9]+ \(cmake_language\): + The LOCATION property may not be read from non-imported target "mylib"; + skipping\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Warning at PrintPropertiesLocationNonImported\.cmake:[0-9]+ \(cmake_language\): + The LOCATION_Debug property may not be read from non-imported target + "mylib"; skipping\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Warning at PrintPropertiesLocationNonImported\.cmake:[0-9]+ \(cmake_language\): + The Debug_LOCATION property may not be read from non-imported target + "mylib"; skipping\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLocationNonImported-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesLocationNonImported-stdout.txt new file mode 100644 index 0000000000..bc615d5ef7 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLocationNonImported-stdout.txt @@ -0,0 +1,4 @@ +-- Printing properties\.\.\. + +Properties for TARGET mylib: + +mylib\.TYPE = "STATIC_LIBRARY" + +mylib\.NAME = "mylib" diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLocationNonImported.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesLocationNonImported.cmake new file mode 100644 index 0000000000..5d15f780e6 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLocationNonImported.cmake @@ -0,0 +1,8 @@ +enable_language(C) +add_library(mylib STATIC nothing.c) + +# Reading a computed location property from a non-imported target +# is skipped with a warning instead of read. Any other requested properties +# should still be printed. +cmake_language(PRINT_PROPERTIES TARGETS mylib + NAMED TYPE LOCATION LOCATION_Debug Debug_LOCATION NAME) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLocationOnlySkipped-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesLocationOnlySkipped-stderr.txt new file mode 100644 index 0000000000..3004fa45dc --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLocationOnlySkipped-stderr.txt @@ -0,0 +1,19 @@ +CMake Warning at PrintPropertiesLocationOnlySkipped\.cmake:[0-9]+ \(cmake_language\): + The LOCATION property may not be read from non-imported target "mylib"; + skipping\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Warning at PrintPropertiesLocationOnlySkipped\.cmake:[0-9]+ \(cmake_language\): + The LOCATION_Debug property may not be read from non-imported target + "mylib"; skipping\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) + + +CMake Warning at PrintPropertiesLocationOnlySkipped\.cmake:[0-9]+ \(cmake_language\): + The Debug_LOCATION property may not be read from non-imported target + "mylib"; skipping\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesLocationOnlySkipped.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesLocationOnlySkipped.cmake new file mode 100644 index 0000000000..a54be3425a --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesLocationOnlySkipped.cmake @@ -0,0 +1,7 @@ +enable_language(C) +add_library(mylib STATIC nothing.c) + +# If we only read LOCATION based properties on a non-imported target, print just +# the warning and suppress the header. +cmake_language(PRINT_PROPERTIES TARGETS mylib + NAMED LOCATION LOCATION_Debug Debug_LOCATION) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesMissingTarget-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesMissingTarget-stdout.txt new file mode 100644 index 0000000000..51a594b218 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesMissingTarget-stdout.txt @@ -0,0 +1,12 @@ +-- Printing properties\.\.\. + + +No such TARGET "does_not_exist" ! + + +-- Configuring done .* +-- Printing properties\.\.\. + + +No such TARGET "does_not_exist" ! + + +-- Generating done .* diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesMissingTarget.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesMissingTarget.cmake new file mode 100644 index 0000000000..96c55ade2a --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesMissingTarget.cmake @@ -0,0 +1,14 @@ +# Configure-time: prints a status-line note and continues. +cmake_language( + PRINT_PROPERTIES + TARGETS does_not_exist + NAMED MY_PROP +) + +# Deferred: prints a status-line note at generate time and continues. +cmake_language( + PRINT_PROPERTIES + TARGETS does_not_exist + DEFERRED + NAMED MY_PROP +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesNameRegexError-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesNameRegexError-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesNameRegexError-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesNameRegexError-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesNameRegexError-stderr.txt new file mode 100644 index 0000000000..80c5cdfc27 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesNameRegexError-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at PrintPropertiesNameRegexError\.cmake:[0-9]+ \(cmake_language\): + cmake_language PROPERTY_NAME_REGEX regular expression "\[unbalanced" cannot + compile\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesNameRegexError.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesNameRegexError.cmake new file mode 100644 index 0000000000..729400b5d6 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesNameRegexError.cmake @@ -0,0 +1,10 @@ +enable_language(C) +add_library(mylib STATIC nothing.c) + +# Unbalanced bracket - regex compile must fail with a fatal error. +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + ALL + PROPERTY_NAME_REGEX "[unbalanced" +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesNamedRequired-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesNamedRequired-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesNamedRequired-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesNamedRequired-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesNamedRequired-stderr.txt new file mode 100644 index 0000000000..4ba90d32b7 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesNamedRequired-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at PrintPropertiesNamedRequired\.cmake:[0-9]+ \(cmake_language\): + cmake_language NAMED keyword missing in cmake_language\(PRINT_PROPERTIES\) + call with SOURCES scope\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesNamedRequired.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesNamedRequired.cmake new file mode 100644 index 0000000000..414f30f21d --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesNamedRequired.cmake @@ -0,0 +1,5 @@ +# Non-TARGETS scopes require NAMED. +cmake_language( + PRINT_PROPERTIES + SOURCES nothing.c +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesRegexRequiresTargets-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesRegexRequiresTargets-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesRegexRequiresTargets-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesRegexRequiresTargets-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesRegexRequiresTargets-stderr.txt new file mode 100644 index 0000000000..1811d89174 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesRegexRequiresTargets-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at PrintPropertiesRegexRequiresTargets\.cmake:[0-9]+ \(cmake_language\): + cmake_language PROPERTY_NAME_REGEX and PROPERTY_VALUE_REGEX in + cmake_language\(PRINT_PROPERTIES\) call are only valid with the TARGETS scope + and ALL\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesRegexRequiresTargets.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesRegexRequiresTargets.cmake new file mode 100644 index 0000000000..198568da19 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesRegexRequiresTargets.cmake @@ -0,0 +1,7 @@ +# Regex filters are only valid with the TARGETS scope and ALL. +cmake_language( + PRINT_PROPERTIES + SOURCES nothing.c + NAMED LANGUAGE + PROPERTY_NAME_REGEX "LANG" +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesRegexWithNamed-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesRegexWithNamed-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesRegexWithNamed-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesRegexWithNamed-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesRegexWithNamed-stderr.txt new file mode 100644 index 0000000000..e0a626dfab --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesRegexWithNamed-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at PrintPropertiesRegexWithNamed\.cmake:[0-9]+ \(cmake_language\): + cmake_language PROPERTY_NAME_REGEX and PROPERTY_VALUE_REGEX in + cmake_language\(PRINT_PROPERTIES\) call are only valid with ALL, not NAMED\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesRegexWithNamed.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesRegexWithNamed.cmake new file mode 100644 index 0000000000..ba46252823 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesRegexWithNamed.cmake @@ -0,0 +1,10 @@ +enable_language(C) +add_library(mylib STATIC nothing.c) + +# Regex filters require ALL; combining with NAMED is an error. +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + NAMED MY_PROP + PROPERTY_NAME_REGEX "MY_" +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesSources-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesSources-stdout.txt new file mode 100644 index 0000000000..b11fd189f4 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesSources-stdout.txt @@ -0,0 +1,9 @@ +-- Printing properties\.\.\. + +Properties for TARGET rot13: + +rot13.SOURCES = \"rot13.c;rot13.h\" + +rot13.POSITION_INDEPENDENT_CODE = \"True\" + +-- Printing properties\.\.\. + +Properties for SOURCE rot13.c: + +rot13.c.LOCATION = \"[^\"]*/cmake_language/rot13.c\" + +rot13.c.LANGUAGE = \"C\" diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesSources.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesSources.cmake new file mode 100644 index 0000000000..f6cdca84b0 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesSources.cmake @@ -0,0 +1,21 @@ +enable_language(C) + +set_property(SOURCE rot13.c PROPERTY LANGUAGE C) + +add_library(rot13 SHARED rot13.c rot13.h) + +cmake_language( + PRINT_PROPERTIES + TARGETS rot13 + NAMED + SOURCES + POSITION_INDEPENDENT_CODE +) + +cmake_language( + PRINT_PROPERTIES + SOURCES rot13.c + NAMED + LOCATION + LANGUAGE +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesTests-stdout.txt b/Tests/RunCMake/cmake_language/PrintPropertiesTests-stdout.txt new file mode 100644 index 0000000000..c650be875f --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesTests-stdout.txt @@ -0,0 +1,9 @@ +-- Printing properties\.\.\. + Properties for TEST test_a: + test_a\.MY_PROP = "a_val" + test_a\.TIMEOUT = "30" + test_a\.NOT_SET = + Properties for TEST test_b: + test_b\.MY_PROP = "b_val" + test_b\.TIMEOUT = "60" + test_b\.NOT_SET = diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesTests.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesTests.cmake new file mode 100644 index 0000000000..6dab3ebe3a --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesTests.cmake @@ -0,0 +1,14 @@ +enable_testing() +add_test(NAME test_a COMMAND "${CMAKE_COMMAND}" -E true) +add_test(NAME test_b COMMAND "${CMAKE_COMMAND}" -E true) +set_tests_properties(test_a PROPERTIES MY_PROP "a_val" TIMEOUT 30) +set_tests_properties(test_b PROPERTIES MY_PROP "b_val" TIMEOUT 60) + +cmake_language( + PRINT_PROPERTIES + TESTS test_a test_b + NAMED + MY_PROP + TIMEOUT + NOT_SET +) diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesValueRegexError-result.txt b/Tests/RunCMake/cmake_language/PrintPropertiesValueRegexError-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesValueRegexError-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesValueRegexError-stderr.txt b/Tests/RunCMake/cmake_language/PrintPropertiesValueRegexError-stderr.txt new file mode 100644 index 0000000000..bec3590d57 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesValueRegexError-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at PrintPropertiesValueRegexError\.cmake:[0-9]+ \(cmake_language\): + cmake_language PROPERTY_VALUE_REGEX regular expression "\[unbalanced" cannot + compile\. diff --git a/Tests/RunCMake/cmake_language/PrintPropertiesValueRegexError.cmake b/Tests/RunCMake/cmake_language/PrintPropertiesValueRegexError.cmake new file mode 100644 index 0000000000..52ab128311 --- /dev/null +++ b/Tests/RunCMake/cmake_language/PrintPropertiesValueRegexError.cmake @@ -0,0 +1,10 @@ +enable_language(C) +add_library(mylib STATIC nothing.c) + + +cmake_language( + PRINT_PROPERTIES + TARGETS mylib + ALL + PROPERTY_VALUE_REGEX "[unbalanced" +) diff --git a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake index 1b8b7dc7ec..e5cccbe496 100644 --- a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake @@ -167,6 +167,47 @@ run_cmake(Experimental/ExportPackageDependencies-wrong) run_cmake(Experimental/ExportPackageDependencies-quiet) run_cmake(Experimental/Unknown) +run_cmake(PrintProperties) +run_cmake(PrintPropertiesSources) +run_cmake(PrintPropertiesDirectories) +run_cmake(PrintPropertiesTests) +run_cmake(PrintPropertiesCacheEntries) +run_cmake(PrintPropertiesLegacyFlagRequiresNamed) +run_cmake(PrintPropertiesAll) +run_cmake(PrintPropertiesImplicitAll) +run_cmake(PrintPropertiesFiltering) +run_cmake(PrintPropertiesDeferred) +run_cmake(PrintPropertiesFollowDependencies) +# Merge stdout+stderr so the expected output can assert that warnings / +# generator-time messages fall between "Configuring done" and +# "Generating done" - i.e. from the generator-action lambda. +block() + set(RunCMake_TEST_OUTPUT_MERGE 1) + run_cmake(PrintPropertiesAllFollowDependencies) + run_cmake(PrintPropertiesAllFollowBothRegex) + run_cmake(PrintPropertiesFollowImpliesDeferred) + run_cmake(PrintPropertiesEmptyMatch) + run_cmake(PrintPropertiesMissingTarget) + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + run_cmake(PrintPropertiesConfigSpecific) +endblock() +run_cmake(PrintPropertiesAllAndNamed) +run_cmake(PrintPropertiesRegexWithNamed) +run_cmake(PrintPropertiesNamedRequired) +run_cmake(PrintPropertiesAllRequiresTargets) +run_cmake(PrintPropertiesRegexRequiresTargets) +run_cmake(PrintPropertiesDeferredRequiresTargets) +run_cmake(PrintPropertiesFollowRequiresTargets) +run_cmake(PrintPropertiesNameRegexError) +run_cmake(PrintPropertiesValueRegexError) +run_cmake(PrintPropertiesLocationNonImported) +run_cmake(PrintPropertiesLocationImported) +block() + # All requested properties are skipped, so no block header is emitted. + set(RunCMake_TEST_NOT_EXPECT_stdout "Properties for TARGET") + run_cmake(PrintPropertiesLocationOnlySkipped) +endblock() + run_cmake(trace) run_cmake(trace_seq) run_cmake(trace_expand) diff --git a/Tests/RunCMake/cmake_language/nothing.c b/Tests/RunCMake/cmake_language/nothing.c new file mode 100644 index 0000000000..1d11f3365a --- /dev/null +++ b/Tests/RunCMake/cmake_language/nothing.c @@ -0,0 +1,6 @@ +#include "nothing.h" + +void nothing(void) +{ + (void*)0; +} diff --git a/Tests/RunCMake/cmake_language/nothing.h b/Tests/RunCMake/cmake_language/nothing.h new file mode 100644 index 0000000000..ae86667598 --- /dev/null +++ b/Tests/RunCMake/cmake_language/nothing.h @@ -0,0 +1,8 @@ +#ifndef NOTHING_H +#define NOTHING_H + +#include + +void nothing(); + +#endif diff --git a/Tests/RunCMake/cmake_language/rot13.c b/Tests/RunCMake/cmake_language/rot13.c new file mode 100644 index 0000000000..053bebdbe7 --- /dev/null +++ b/Tests/RunCMake/cmake_language/rot13.c @@ -0,0 +1,15 @@ +#include "rot13.h" + +void rot13(char* in) +{ + char* end = in + strlen(in); + for (char* c = in; c < end; c++) { + if (*c >= 'a' && *c <= 'z') { + *c += (*c < 'n') ? 13 : -13; + continue; + } + if (*c >= 'A' && *c <= 'Z') { + *c += (*c < 'N') ? 13 : -13; + } + } +} diff --git a/Tests/RunCMake/cmake_language/rot13.h b/Tests/RunCMake/cmake_language/rot13.h new file mode 100644 index 0000000000..9afea5f49e --- /dev/null +++ b/Tests/RunCMake/cmake_language/rot13.h @@ -0,0 +1,9 @@ +#ifndef ROT13_H +#define ROT13_H + +#include +#include + +void rot13(char* in); + +#endif diff --git a/Tests/RunCMake/cmake_language/something.c b/Tests/RunCMake/cmake_language/something.c new file mode 100644 index 0000000000..90482c9f25 --- /dev/null +++ b/Tests/RunCMake/cmake_language/something.c @@ -0,0 +1,7 @@ +#include "something.h" + +int main(void) +{ + nothing(); + return 0; +} diff --git a/Tests/RunCMake/cmake_language/something.h b/Tests/RunCMake/cmake_language/something.h new file mode 100644 index 0000000000..667ee99c2f --- /dev/null +++ b/Tests/RunCMake/cmake_language/something.h @@ -0,0 +1,8 @@ +#ifndef SOMETHING_H +#define SOMETHING_H + +#include + +#include "nothing.h" + +#endif