diff options
author | Brad King <brad.king@kitware.com> | 2020-07-20 17:19:26 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2020-08-07 12:46:32 (GMT) |
commit | 439191313363caea225a508634495c50d4cc60dd (patch) | |
tree | eb1156c1fbf93b4a9ea23ec812ba49ef7a195846 /Source | |
parent | afb998704e67d3d3ce5b24c112cb06e770fca78d (diff) | |
download | CMake-439191313363caea225a508634495c50d4cc60dd.zip CMake-439191313363caea225a508634495c50d4cc60dd.tar.gz CMake-439191313363caea225a508634495c50d4cc60dd.tar.bz2 |
Add INTERFACE libraries to generated buildsystem if they have SOURCES
INTERFACE libraries were created with the intention of collecting usage
requirements for use by other targets via `target_link_libraries`.
Therefore they were not allowed to have SOURCES and were not included in
the generated buildsystem. In practice, this has become limiting:
* Header-only libraries do have sources, they just do not compile.
Developers should be able to edit those sources (the header files)
in their IDE.
* Header-only libraries may need to generate some of their header
files via custom commands.
Some projects work around these limitations by pairing each interface
library with an `add_custom_target` that makes the header files and
custom commands appear in the generated buildsystem and in IDEs.
Lift such limitations by allowing INTERFACE libraries to have SOURCES.
For those with sources, add a corresponding build target to the
generated buildsystem.
Fixes: #19145
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmAddLibraryCommand.cxx | 26 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 13 | ||||
-rw-r--r-- | Source/cmGlobalNinjaGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 3 | ||||
-rw-r--r-- | Source/cmLocalVisualStudio7Generator.cxx | 10 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 1 | ||||
-rw-r--r-- | Source/cmNinjaTargetGenerator.cxx | 1 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 41 | ||||
-rw-r--r-- | Source/cmTargetPropCommandBase.cxx | 2 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 11 |
10 files changed, 47 insertions, 63 deletions
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 3e5d764..f262fac 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddLibraryCommand.h" -#include <cmext/algorithm> - #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -111,20 +109,10 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, "INTERFACE library specified with conflicting ALIAS type."); return false; } - if (excludeFromAll) { - status.SetError( - "INTERFACE library may not be used with EXCLUDE_FROM_ALL."); - return false; - } ++s; type = cmStateEnums::INTERFACE_LIBRARY; haveSpecifiedType = true; } else if (*s == "EXCLUDE_FROM_ALL") { - if (type == cmStateEnums::INTERFACE_LIBRARY) { - status.SetError( - "INTERFACE library may not be used with EXCLUDE_FROM_ALL."); - return false; - } ++s; excludeFromAll = true; } else if (*s == "IMPORTED") { @@ -143,10 +131,6 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, } if (type == cmStateEnums::INTERFACE_LIBRARY) { - if (s != args.end()) { - status.SetError("INTERFACE library requires no source arguments."); - return false; - } if (importGlobal && !importTarget) { status.SetError( "INTERFACE library specified as GLOBAL, but not as IMPORTED."); @@ -302,8 +286,6 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, } } - std::vector<std::string> srclists; - if (type == cmStateEnums::INTERFACE_LIBRARY) { if (!cmGeneratorExpression::IsValidTargetName(libName) || libName.find("::") != std::string::npos) { @@ -311,14 +293,10 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, cmStrCat("Invalid name for INTERFACE library target: ", libName)); return false; } - - mf.AddLibrary(libName, type, srclists, excludeFromAll); - return true; } - cm::append(srclists, s, args.end()); - - mf.AddLibrary(libName, type, srclists, excludeFromAll); + std::vector<std::string> srcs(s, args.end()); + mf.AddLibrary(libName, type, srcs, excludeFromAll); return true; } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index d39c493..06c32fe 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1099,6 +1099,10 @@ bool cmGeneratorTarget::IsInBuildSystem() const case cmStateEnums::GLOBAL_TARGET: return true; case cmStateEnums::INTERFACE_LIBRARY: + // An INTERFACE library is in the build system if it has SOURCES. + if (!this->SourceEntries.empty()) { + return true; + } case cmStateEnums::UNKNOWN_LIBRARY: break; } @@ -1543,7 +1547,6 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( std::string const& config) const { std::vector<BT<std::string>> files; - assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY); if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) { // At configure-time, this method can be called as part of getting the @@ -1735,9 +1738,11 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); if (sf->GetCustomCommand()) { kind = SourceKindCustomCommand; - // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 - // NOLINTNEXTLINE(bugprone-branch-clone) - } else if (this->Target->GetType() == cmStateEnums::UTILITY) { + } else if (this->Target->GetType() == cmStateEnums::UTILITY || + this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY + // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 + // NOLINTNEXTLINE(bugprone-branch-clone) + ) { kind = SourceKindExtra; } else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) { kind = SourceKindUnityBatched; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 2ef202d..f0fa1f4 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1093,6 +1093,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( } // FALLTHROUGH case cmStateEnums::GLOBAL_TARGET: + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::UTILITY: { std::string path = cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', @@ -1105,7 +1106,6 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( break; } - case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::UNKNOWN_LIBRARY: break; } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 574e0f5..793f6f7 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1204,6 +1204,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( } if (gtgt->GetType() == cmStateEnums::UTILITY || + gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY || gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { cmXCodeObject* t = this->CreateUtilityTarget(gtgt); if (!t) { @@ -2536,7 +2537,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( this->XCodeObjectMap[gtgt] = target; // Add source files without build rules for editing convenience. - if (gtgt->GetType() == cmStateEnums::UTILITY && + if (gtgt->GetType() != cmStateEnums::GLOBAL_TARGET && gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { std::vector<cmSourceFile*> sources; if (!gtgt->GetConfigCommonSourceFiles(sources)) { diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index fec6a9d..50ffe8d 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -629,9 +629,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( break; case cmStateEnums::UTILITY: case cmStateEnums::GLOBAL_TARGET: + case cmStateEnums::INTERFACE_LIBRARY: configType = "10"; CM_FALLTHROUGH; - default: + case cmStateEnums::UNKNOWN_LIBRARY: targetBuilds = false; break; } @@ -1638,7 +1639,8 @@ bool cmLocalVisualStudio7Generator::WriteGroup( std::string source = sf->GetFullPath(); if (source != libName || target->GetType() == cmStateEnums::UTILITY || - target->GetType() == cmStateEnums::GLOBAL_TARGET) { + target->GetType() == cmStateEnums::GLOBAL_TARGET || + target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { // Look up the source kind and configs. std::map<cmSourceFile const*, size_t>::const_iterator map_it = sources.Index.find(sf); @@ -1937,6 +1939,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran( const char* keyword = p ? p->c_str() : "Console Application"; const char* projectType = 0; switch (target->GetType()) { + case cmStateEnums::OBJECT_LIBRARY: case cmStateEnums::STATIC_LIBRARY: projectType = "typeStaticLibrary"; if (keyword) { @@ -1958,7 +1961,8 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran( break; case cmStateEnums::UTILITY: case cmStateEnums::GLOBAL_TARGET: - default: + case cmStateEnums::INTERFACE_LIBRARY: + case cmStateEnums::UNKNOWN_LIBRARY: break; } if (projectType) { diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 13c2fe9..fae1d76 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -71,6 +71,7 @@ std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New( case cmStateEnums::OBJECT_LIBRARY: result = cm::make_unique<cmMakefileLibraryTargetGenerator>(tgt); break; + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::UTILITY: result = cm::make_unique<cmMakefileUtilityTargetGenerator>(tgt); break; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 048dbb6..57f526e 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -51,6 +51,7 @@ std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New( return cm::make_unique<cmNinjaNormalTargetGenerator>(target); case cmStateEnums::UTILITY: + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::GLOBAL_TARGET: return cm::make_unique<cmNinjaUtilityTargetGenerator>(target); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 67d7451..51b4e9e 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -401,12 +401,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, #endif } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - initProp("FOLDER"); + initProp("FOLDER"); - if (this->GetGlobalGenerator()->IsXcode()) { - initProp("XCODE_GENERATE_SCHEME"); - } + if (this->GetGlobalGenerator()->IsXcode()) { + initProp("XCODE_GENERATE_SCHEME"); } // Setup per-configuration property default values. @@ -521,24 +519,21 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("DOTNET_TARGET_FRAMEWORK_VERSION"); } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - - // check for "CMAKE_VS_GLOBALS" variable and set up target properties - // if any - const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS"); - if (globals) { - const std::string genName = mf->GetGlobalGenerator()->GetName(); - if (cmHasLiteralPrefix(genName, "Visual Studio")) { - std::vector<std::string> props = cmExpandedList(globals); - const std::string vsGlobal = "VS_GLOBAL_"; - for (const std::string& i : props) { - // split NAME=VALUE - const std::string::size_type assignment = i.find('='); - if (assignment != std::string::npos) { - const std::string propName = vsGlobal + i.substr(0, assignment); - const std::string propValue = i.substr(assignment + 1); - initPropValue(propName, propValue.c_str()); - } + // check for "CMAKE_VS_GLOBALS" variable and set up target properties + // if any + const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS"); + if (globals) { + const std::string genName = mf->GetGlobalGenerator()->GetName(); + if (cmHasLiteralPrefix(genName, "Visual Studio")) { + std::vector<std::string> props = cmExpandedList(globals); + const std::string vsGlobal = "VS_GLOBAL_"; + for (const std::string& i : props) { + // split NAME=VALUE + const std::string::size_type assignment = i.find('='); + if (assignment != std::string::npos) { + const std::string propName = vsGlobal + i.substr(0, assignment); + const std::string propValue = i.substr(assignment + 1); + initPropValue(propName, propValue.c_str()); } } } diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index e714720..9e30136 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -123,7 +123,7 @@ bool cmTargetPropCommandBase::ProcessContentArgs( } if (!content.empty()) { if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && - scope != "INTERFACE") { + scope != "INTERFACE" && this->Property != "SOURCES") { this->SetError("may only set INTERFACE properties on INTERFACE targets"); return false; } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 6369c1f..db9dc53 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -315,8 +315,7 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( void cmVisualStudio10TargetGenerator::Generate() { // do not generate external ms projects - if (this->GeneratorTarget->GetType() == cmStateEnums::INTERFACE_LIBRARY || - this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) { + if (this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) { return; } const std::string ProjectFileExtension = @@ -437,7 +436,7 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element("ProjectGuid", "{" + this->GUID + "}"); if ((this->MSTools || this->Android) && - this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) { + this->GeneratorTarget->IsInBuildSystem()) { this->WriteApplicationTypeSettings(e1); this->VerifyNecessaryFiles(); } @@ -605,11 +604,11 @@ void cmVisualStudio10TargetGenerator::Generate() } break; case cmStateEnums::UTILITY: + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::GLOBAL_TARGET: outputType = "Utility"; break; case cmStateEnums::UNKNOWN_LIBRARY: - case cmStateEnums::INTERFACE_LIBRARY: break; } e1.Element("OutputType", outputType); @@ -1157,6 +1156,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) } break; case cmStateEnums::UTILITY: + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::GLOBAL_TARGET: if (this->NsightTegra) { // Tegra-Android platform does not understand "Utility". @@ -1166,7 +1166,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0) } break; case cmStateEnums::UNKNOWN_LIBRARY: - case cmStateEnums::INTERFACE_LIBRARY: break; } } @@ -2152,7 +2151,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) { - if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) { + if (this->GeneratorTarget->GetType() == cmStateEnums::GLOBAL_TARGET) { return; } |