diff options
author | Ben Boeckel <ben.boeckel@kitware.com> | 2023-01-15 04:58:28 (GMT) |
---|---|---|
committer | Robert Maynard <rmaynard@nvidia.com> | 2023-04-12 14:43:48 (GMT) |
commit | 0fb923c46041d67110c8e0907afdf66b3b25f25a (patch) | |
tree | 471126bf0dcb9ef4481716d38524b57a01ca2973 /Source | |
parent | 6c11f7e4a8805189835c04a398864f96081b3183 (diff) | |
download | CMake-0fb923c46041d67110c8e0907afdf66b3b25f25a.zip CMake-0fb923c46041d67110c8e0907afdf66b3b25f25a.tar.gz CMake-0fb923c46041d67110c8e0907afdf66b3b25f25a.tar.bz2 |
cmGeneratorExpressionNode: implement `COMPILE_ONLY` genex
This generator expression is the inverse of `LINK_ONLY` and only coveys
usage requirements for the purposes of compilation. Its intended use is
to avoid needing to export targets that do not have link usage
requirements (e.g., header-only libraries) when used by another target.
It will also be used to represent private usage requirements on exported
C++ module-containing targets in the future.
Eventually there should be logic to collapse nesting of
`$<COMPILE_ONLY>` and `$<LINK_ONLY>` when generating instances of
either. A TODO is left in the code for this case.
See: #15415
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 16 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 25 | ||||
-rw-r--r-- | Source/cmTargetLinkLibrariesCommand.cxx | 1 |
3 files changed, 42 insertions, 0 deletions
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 6e7ef4e..e997158 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -734,6 +734,22 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( lastPos = nameStartPos + libName.size() + 1; } + while (errorString.empty() && + (pos = input.find("$<COMPILE_ONLY:", lastPos)) != std::string::npos) { + std::string::size_type nameStartPos = pos + cmStrLen("$<COMPILE_ONLY:"); + std::string::size_type endPos = input.find('>', nameStartPos); + if (endPos == std::string::npos) { + errorString = "$<COMPILE_ONLY:...> expression incomplete"; + break; + } + std::string libName = input.substr(nameStartPos, endPos - nameStartPos); + if (cmGeneratorExpression::IsValidTargetName(libName) && + this->AddTargetNamespace(libName, target, lg)) { + input.replace(nameStartPos, endPos - nameStartPos, libName); + } + lastPos = nameStartPos + libName.size() + 1; + } + this->ReplaceInstallPrefix(input); if (!errorString.empty()) { diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index a47366b..a221498 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1351,6 +1351,29 @@ static const VersionNode<cmSystemTools::OP_LESS> versionLessNode; static const VersionNode<cmSystemTools::OP_LESS_EQUAL> versionLessEqNode; static const VersionNode<cmSystemTools::OP_EQUAL> versionEqualNode; +static const struct CompileOnlyNode : public cmGeneratorExpressionNode +{ + CompileOnlyNode() {} // NOLINT(modernize-use-equals-default) + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!dagChecker) { + reportError(context, content->GetOriginalExpression(), + "$<COMPILE_ONLY:...> may only be used via linking"); + return std::string(); + } + // Linking checks for the inverse, so compiling is the opposite. + if (dagChecker->GetTransitivePropertiesOnly()) { + return parameters.front(); + } + return std::string(); + } +} compileOnlyNode; + static const struct LinkOnlyNode : public cmGeneratorExpressionNode { LinkOnlyNode() {} // NOLINT(modernize-use-equals-default) @@ -1366,6 +1389,7 @@ static const struct LinkOnlyNode : public cmGeneratorExpressionNode "$<LINK_ONLY:...> may only be used for linking"); return std::string(); } + // Compile-only checks for the inverse, so linking is the opposite. if (!dagChecker->GetTransitivePropertiesOnly()) { return parameters.front(); } @@ -3805,6 +3829,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "BUILD_LOCAL_INTERFACE", &buildLocalInterfaceNode }, { "INSTALL_PREFIX", &installPrefixNode }, { "JOIN", &joinNode }, + { "COMPILE_ONLY", &compileOnlyNode }, { "LINK_ONLY", &linkOnlyNode }, { "COMPILE_LANG_AND_ID", &languageAndIdNode }, { "COMPILE_LANGUAGE", &languageNode }, diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 0b123b2..03d7c9f 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -552,6 +552,7 @@ bool TLL::HandleLibrary(ProcessingState currentProcessingState, currentProcessingState == ProcessingPlainPrivateInterface) { if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY || this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { + // TODO: Detect and no-op `$<COMPILE_ONLY>` genexes here. std::string configLib = this->Target->GetDebugGeneratorExpressions(lib, llt); if (cmGeneratorExpression::IsValidTargetName(lib) || |