From e7edba2bafc7eb187a05c20acf4e859e500c7c5b Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 28 Jul 2020 11:01:30 -0400 Subject: Makefiles: Use IsInBuildSystem in global generator target type checks Follow up from commit 422d9a0ab2 (Factor out generator checks for filtering out interface libraries, 2020-07-20) with more uses of `IsInBuildSystem`. --- Source/cmGlobalUnixMakefileGenerator3.cxx | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index ebc90b6..37a77fa 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -387,12 +387,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules( cm::static_reference_cast(lGenerator); // for all of out targets for (const auto& tgt : lg.GetGeneratorTargets()) { - if ((tgt->GetType() == cmStateEnums::EXECUTABLE) || - (tgt->GetType() == cmStateEnums::STATIC_LIBRARY) || - (tgt->GetType() == cmStateEnums::SHARED_LIBRARY) || - (tgt->GetType() == cmStateEnums::MODULE_LIBRARY) || - (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) || - (tgt->GetType() == cmStateEnums::UTILITY)) { + if (tgt->IsInBuildSystem() && + tgt->GetType() != cmStateEnums::GLOBAL_TARGET) { std::string tname = cmStrCat(lg.GetRelativeTargetDirectory(tgt.get()), "/DependInfo.cmake"); cmSystemTools::ConvertToUnixSlashes(tname); @@ -635,17 +631,12 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( for (const auto& gtarget : lg.GetGeneratorTargets()) { // Don't emit the same rule twice (e.g. two targets with the same // simple name) - int type = gtarget->GetType(); std::string name = gtarget->GetName(); if (!name.empty() && emitted.insert(name).second && // Handle user targets here. Global targets are handled in // the local generator on a per-directory basis. - ((type == cmStateEnums::EXECUTABLE) || - (type == cmStateEnums::STATIC_LIBRARY) || - (type == cmStateEnums::SHARED_LIBRARY) || - (type == cmStateEnums::MODULE_LIBRARY) || - (type == cmStateEnums::OBJECT_LIBRARY) || - (type == cmStateEnums::UTILITY))) { + (gtarget->IsInBuildSystem() && + gtarget->GetType() != cmStateEnums::GLOBAL_TARGET)) { // Add a rule to build the target by name. lg.WriteDivider(ruleFileStream); ruleFileStream << "# Target rules for targets named " << name @@ -709,15 +700,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( // for each target Generate the rule files for each target. for (const auto& gtarget : lg.GetGeneratorTargets()) { - int type = gtarget->GetType(); std::string name = gtarget->GetName(); if (!name.empty() && - ((type == cmStateEnums::EXECUTABLE) || - (type == cmStateEnums::STATIC_LIBRARY) || - (type == cmStateEnums::SHARED_LIBRARY) || - (type == cmStateEnums::MODULE_LIBRARY) || - (type == cmStateEnums::OBJECT_LIBRARY) || - (type == cmStateEnums::UTILITY))) { + (gtarget->IsInBuildSystem() && + gtarget->GetType() != cmStateEnums::GLOBAL_TARGET)) { std::string makefileName; // Add a rule to build the target by name. localName = lg.GetRelativeTargetDirectory(gtarget.get()); @@ -985,7 +971,9 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule( (type == cmStateEnums::STATIC_LIBRARY) || (type == cmStateEnums::SHARED_LIBRARY) || (type == cmStateEnums::MODULE_LIBRARY) || - (type == cmStateEnums::OBJECT_LIBRARY)) { + (type == cmStateEnums::OBJECT_LIBRARY) || + (type == cmStateEnums::INTERFACE_LIBRARY && + target->IsInBuildSystem())) { project_targets.insert(target->GetName()); } else if (type == cmStateEnums::GLOBAL_TARGET) { globals_targets.insert(target->GetName()); -- cgit v0.12 From afb998704e67d3d3ce5b24c112cb06e770fca78d Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 14 Jul 2020 13:55:38 -0400 Subject: Remove filtering of allowed INTERFACE library properties Previously we disallowed use of arbitrary properties on INTERFACE libraries. The goal was to future-proof projects using them by not allowing properties to be set that may affect their future inclusion in the generated buildsystem. In order to prepare to actually include INTERFACE libraries in the generated buildsystem, drop the filter and allow arbitrary properties to be set. Issue: #19145 --- Help/manual/cmake-buildsystem.7.rst | 13 ---- Source/cmGeneratorTarget.cxx | 5 -- Source/cmGetPropertyCommand.cxx | 10 +--- Source/cmGetTargetPropertyCommand.cxx | 10 +--- Source/cmTarget.cxx | 10 ---- Source/cmTargetPropertyComputer.cxx | 69 ---------------------- Source/cmTargetPropertyComputer.h | 6 -- Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake | 1 - .../RunCMake/InterfaceLibrary/whitelist-result.txt | 1 - .../RunCMake/InterfaceLibrary/whitelist-stderr.txt | 19 ------ Tests/RunCMake/InterfaceLibrary/whitelist.cmake | 25 -------- 11 files changed, 6 insertions(+), 163 deletions(-) delete mode 100644 Tests/RunCMake/InterfaceLibrary/whitelist-result.txt delete mode 100644 Tests/RunCMake/InterfaceLibrary/whitelist-stderr.txt delete mode 100644 Tests/RunCMake/InterfaceLibrary/whitelist.cmake diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index d8142a2..6eea191 100644 --- a/Help/manual/cmake-buildsystem.7.rst +++ b/Help/manual/cmake-buildsystem.7.rst @@ -975,19 +975,6 @@ This way, the build specification of ``exe1`` is expressed entirely as linked targets, and the complexity of compiler-specific flags is encapsulated in an ``INTERFACE`` library target. -The properties permitted to be set on or read from an ``INTERFACE`` library -are: - -* Properties matching ``INTERFACE_*`` -* Built-in properties matching ``COMPATIBLE_INTERFACE_*`` -* ``EXPORT_NAME`` -* ``EXPORT_PROPERTIES`` -* ``IMPORTED`` -* ``MANUALLY_ADDED_DEPENDENCIES`` -* ``NAME`` -* Properties matching ``IMPORTED_LIBNAME_*`` -* Properties matching ``MAP_IMPORTED_CONFIG_*`` - ``INTERFACE`` libraries may be installed and exported. Any content they refer to must be installed separately: diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 41cff01..d39c493 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -380,11 +380,6 @@ std::string cmGeneratorTarget::GetExportName() const cmProp cmGeneratorTarget::GetProperty(const std::string& prop) const { - if (!cmTargetPropertyComputer::PassesWhitelist( - this->GetType(), prop, this->Makefile->GetMessenger(), - this->GetBacktrace())) { - return nullptr; - } if (cmProp result = cmTargetPropertyComputer::GetProperty( this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) { return result; diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index cba7704..cdfd8c8 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -17,7 +17,6 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include "cmTargetPropertyComputer.h" #include "cmTest.h" #include "cmake.h" @@ -364,12 +363,9 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, cmProp prop_cstr = nullptr; cmListFileBacktrace bt = status.GetMakefile().GetBacktrace(); cmMessenger* messenger = status.GetMakefile().GetMessenger(); - if (cmTargetPropertyComputer::PassesWhitelist( - target->GetType(), propertyName, messenger, bt)) { - prop_cstr = target->GetComputedProperty(propertyName, messenger, bt); - if (!prop_cstr) { - prop_cstr = target->GetProperty(propertyName); - } + prop_cstr = target->GetComputedProperty(propertyName, messenger, bt); + if (!prop_cstr) { + prop_cstr = target->GetProperty(propertyName); } return StoreResult(infoType, status.GetMakefile(), variable, prop_cstr ? prop_cstr->c_str() : nullptr); diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index 8a304be..78a17d2 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -12,7 +12,6 @@ #include "cmPolicies.h" #include "cmProperty.h" #include "cmTarget.h" -#include "cmTargetPropertyComputer.h" class cmMessenger; @@ -46,12 +45,9 @@ bool cmGetTargetPropertyCommand(std::vector const& args, cmProp prop_cstr = nullptr; cmListFileBacktrace bt = mf.GetBacktrace(); cmMessenger* messenger = mf.GetMessenger(); - if (cmTargetPropertyComputer::PassesWhitelist(tgt->GetType(), args[2], - messenger, bt)) { - prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt); - if (!prop_cstr) { - prop_cstr = tgt->GetProperty(args[2]); - } + prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt); + if (!prop_cstr) { + prop_cstr = tgt->GetProperty(args[2]); } if (prop_cstr) { prop = *prop_cstr; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 0e5dfef..67d7451 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1144,11 +1144,6 @@ cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const void cmTarget::SetProperty(const std::string& prop, const char* value) { - if (!cmTargetPropertyComputer::PassesWhitelist( - this->GetType(), prop, impl->Makefile->GetMessenger(), - impl->Makefile->GetBacktrace())) { - return; - } #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP MAKE_STATIC_PROP(C_STANDARD); MAKE_STATIC_PROP(CXX_STANDARD); @@ -1355,11 +1350,6 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) void cmTarget::AppendProperty(const std::string& prop, const std::string& value, bool asString) { - if (!cmTargetPropertyComputer::PassesWhitelist( - this->GetType(), prop, impl->Makefile->GetMessenger(), - impl->Makefile->GetBacktrace())) { - return; - } if (prop == "NAME") { impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, "NAME property is read-only\n"); diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index f37995c..b9c9365 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -3,15 +3,12 @@ #include "cmTargetPropertyComputer.h" -#include #include -#include #include "cmMessageType.h" #include "cmMessenger.h" #include "cmPolicies.h" #include "cmStateSnapshot.h" -#include "cmStringAlgorithms.h" bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( std::string const& tgtName, cmMessenger* messenger, @@ -44,69 +41,3 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( return messageType != MessageType::FATAL_ERROR; } - -bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( - const std::string& prop) -{ - if (cmHasLiteralPrefix(prop, "INTERFACE_")) { - return true; - } - if (cmHasLiteralPrefix(prop, "_")) { - return true; - } - if (std::islower(prop[0])) { - return true; - } - static std::unordered_set const builtIns{ - "COMPATIBLE_INTERFACE_BOOL", - "COMPATIBLE_INTERFACE_NUMBER_MAX", - "COMPATIBLE_INTERFACE_NUMBER_MIN", - "COMPATIBLE_INTERFACE_STRING", - "DEPRECATION", - "EXPORT_NAME", - "EXPORT_PROPERTIES", - "IMPORTED", - "IMPORTED_GLOBAL", - "MANUALLY_ADDED_DEPENDENCIES", - "NAME", - "PRIVATE_HEADER", - "PUBLIC_HEADER", - "TYPE" - }; - - if (builtIns.count(prop)) { - return true; - } - - if (prop == "IMPORTED_CONFIGURATIONS" || prop == "IMPORTED_LIBNAME" || - cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME_") || - cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_")) { - return true; - } - - // This property should not be allowed but was incorrectly added in - // CMake 3.8. We can't remove it from the whitelist without breaking - // projects that try to set it. One day we could warn about this, but - // for now silently accept it. - if (prop == "NO_SYSTEM_FROM_IMPORTED") { - return true; - } - - return false; -} - -bool cmTargetPropertyComputer::PassesWhitelist( - cmStateEnums::TargetType tgtType, std::string const& prop, - cmMessenger* messenger, cmListFileBacktrace const& context) -{ - if (tgtType == cmStateEnums::INTERFACE_LIBRARY && - !WhiteListedInterfaceProperty(prop)) { - std::ostringstream e; - e << "INTERFACE_LIBRARY targets may only have whitelisted properties. " - "The property \"" - << prop << "\" is not allowed."; - messenger->IssueMessage(MessageType::FATAL_ERROR, e.str(), context); - return false; - } - return true; -} diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index f87b7c2..bafa43b 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -35,12 +35,6 @@ public: return nullptr; } - static bool WhiteListedInterfaceProperty(const std::string& prop); - - static bool PassesWhitelist(cmStateEnums::TargetType tgtType, - std::string const& prop, cmMessenger* messenger, - cmListFileBacktrace const& context); - private: static bool HandleLocationPropertyPolicy(std::string const& tgtName, cmMessenger* messenger, diff --git a/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake b/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake index 5a6af1d..b84bc33 100644 --- a/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake @@ -3,7 +3,6 @@ include(RunCMake) run_cmake(invalid_name) run_cmake(target_commands) run_cmake(no_shared_libs) -run_cmake(whitelist) run_cmake(invalid_signature) run_cmake(global-interface) run_cmake(genex_link) diff --git a/Tests/RunCMake/InterfaceLibrary/whitelist-result.txt b/Tests/RunCMake/InterfaceLibrary/whitelist-result.txt deleted file mode 100644 index d00491f..0000000 --- a/Tests/RunCMake/InterfaceLibrary/whitelist-result.txt +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/Tests/RunCMake/InterfaceLibrary/whitelist-stderr.txt b/Tests/RunCMake/InterfaceLibrary/whitelist-stderr.txt deleted file mode 100644 index 577c0cc..0000000 --- a/Tests/RunCMake/InterfaceLibrary/whitelist-stderr.txt +++ /dev/null @@ -1,19 +0,0 @@ -CMake Error at whitelist.cmake:4 \(set_property\): - INTERFACE_LIBRARY targets may only have whitelisted properties. The - property "OUTPUT_NAME" is not allowed. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) - - -CMake Error at whitelist.cmake:5 \(set_property\): - INTERFACE_LIBRARY targets may only have whitelisted properties. The - property "OUTPUT_NAME" is not allowed. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) - - -CMake Error at whitelist.cmake:6 \(get_target_property\): - INTERFACE_LIBRARY targets may only have whitelisted properties. The - property "OUTPUT_NAME" is not allowed. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/InterfaceLibrary/whitelist.cmake b/Tests/RunCMake/InterfaceLibrary/whitelist.cmake deleted file mode 100644 index 0db6375..0000000 --- a/Tests/RunCMake/InterfaceLibrary/whitelist.cmake +++ /dev/null @@ -1,25 +0,0 @@ - -add_library(iface INTERFACE) - -set_property(TARGET iface PROPERTY OUTPUT_NAME output) -set_property(TARGET iface APPEND PROPERTY OUTPUT_NAME append) -get_target_property(outname iface OUTPUT_NAME) - -# Properties starting with `_` are allowed. -set_property(TARGET iface PROPERTY "_custom_property" output) -set_property(TARGET iface APPEND PROPERTY "_custom_property" append) -get_target_property(outname iface "_custom_property") - -# Properties starting with a lowercase letter are allowed. -set_property(TARGET iface PROPERTY "custom_property" output) -set_property(TARGET iface APPEND PROPERTY "custom_property" append) -get_target_property(outname iface "custom_property") - -# PUBLIC_HEADER / PRIVATE_HEADER properties are allowed -set_property(TARGET iface PROPERTY PUBLIC_HEADER foo.h) -set_property(TARGET iface APPEND PROPERTY PUBLIC_HEADER bar.h) -get_target_property(outname iface PUBLIC_HEADER) - -set_property(TARGET iface PROPERTY PRIVATE_HEADER foo.h) -set_property(TARGET iface APPEND PROPERTY PRIVATE_HEADER bar.h) -get_target_property(outname iface PRIVATE_HEADER) -- cgit v0.12 From 439191313363caea225a508634495c50d4cc60dd Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 20 Jul 2020 13:19:26 -0400 Subject: 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 --- Help/command/add_library.rst | 31 ++++++++++++++-- Help/manual/cmake-buildsystem.7.rst | 29 ++++++++++----- Help/prop_tgt/EXPORT_PROPERTIES.rst | 8 +++++ Help/release/dev/build-interface-targets.rst | 6 ++++ Source/cmAddLibraryCommand.cxx | 26 ++------------ Source/cmGeneratorTarget.cxx | 13 ++++--- Source/cmGlobalNinjaGenerator.cxx | 2 +- Source/cmGlobalXCodeGenerator.cxx | 3 +- Source/cmLocalVisualStudio7Generator.cxx | 10 ++++-- Source/cmMakefileTargetGenerator.cxx | 1 + Source/cmNinjaTargetGenerator.cxx | 1 + Source/cmTarget.cxx | 41 ++++++++++------------ Source/cmTargetPropCommandBase.cxx | 2 +- Source/cmVisualStudio10TargetGenerator.cxx | 11 +++--- Tests/ExportImport/Export/Interface/CMakeLists.txt | 26 ++++++++++++-- Tests/ExportImport/Export/Interface/headergen.h.in | 1 + Tests/ExportImport/Import/Interface/CMakeLists.txt | 6 ++++ .../Import/Interface/headergentest.cpp | 11 ++++++ Tests/InterfaceLibrary/CMakeLists.txt | 1 + Tests/InterfaceLibrary/definetestexe.cpp | 6 ++++ Tests/InterfaceLibrary/headerdir/CMakeLists.txt | 9 +++++ .../headerdir/iface_genheader.h.in | 1 + .../RunCMake/InterfaceLibrary/ConfigSources.cmake | 2 ++ .../EmptySources-build2-result.txt | 1 + .../EmptySources-build2-stdout.txt | 1 + Tests/RunCMake/InterfaceLibrary/EmptySources.cmake | 8 +++++ .../ExcludeFromAll-build1-check.cmake | 4 +++ .../ExcludeFromAll-build2-check.cmake | 4 +++ .../ExcludeFromAll-build3-result.txt | 1 + .../ExcludeFromAll-build3-stdout.txt | 1 + .../RunCMake/InterfaceLibrary/ExcludeFromAll.cmake | 7 ++++ .../PublicSources-build3-result.txt | 1 + .../PublicSources-build3-stdout.txt | 1 + .../RunCMake/InterfaceLibrary/PublicSources.cmake | 20 +++++++++++ Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake | 24 +++++++++++++ Tests/RunCMake/InterfaceLibrary/iface.c | 4 +++ Tests/RunCMake/InterfaceLibrary/iface_broken.c | 1 + .../InterfaceLibrary/invalid_signature-stderr.txt | 15 -------- .../InterfaceLibrary/invalid_signature.cmake | 6 ++-- Tests/RunCMake/InterfaceLibrary/use_iface.c | 6 ++++ .../VS10Project/InterfaceLibSources-check.cmake | 25 +++++++++++++ .../RunCMake/VS10Project/InterfaceLibSources.cmake | 1 + Tests/RunCMake/VS10Project/RunCMakeTest.cmake | 1 + Tests/RunCMake/VS10Project/iface.h | 0 .../XcodeProject/InterfaceLibSources-check.cmake | 16 +++++++++ .../XcodeProject/InterfaceLibSources.cmake | 1 + Tests/RunCMake/XcodeProject/RunCMakeTest.cmake | 1 + Tests/RunCMake/XcodeProject/iface.h | 0 48 files changed, 303 insertions(+), 94 deletions(-) create mode 100644 Help/release/dev/build-interface-targets.rst create mode 100644 Tests/ExportImport/Export/Interface/headergen.h.in create mode 100644 Tests/ExportImport/Import/Interface/headergentest.cpp create mode 100644 Tests/InterfaceLibrary/headerdir/iface_genheader.h.in create mode 100644 Tests/RunCMake/InterfaceLibrary/ConfigSources.cmake create mode 100644 Tests/RunCMake/InterfaceLibrary/EmptySources-build2-result.txt create mode 100644 Tests/RunCMake/InterfaceLibrary/EmptySources-build2-stdout.txt create mode 100644 Tests/RunCMake/InterfaceLibrary/EmptySources.cmake create mode 100644 Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build1-check.cmake create mode 100644 Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build2-check.cmake create mode 100644 Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build3-result.txt create mode 100644 Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build3-stdout.txt create mode 100644 Tests/RunCMake/InterfaceLibrary/ExcludeFromAll.cmake create mode 100644 Tests/RunCMake/InterfaceLibrary/PublicSources-build3-result.txt create mode 100644 Tests/RunCMake/InterfaceLibrary/PublicSources-build3-stdout.txt create mode 100644 Tests/RunCMake/InterfaceLibrary/PublicSources.cmake create mode 100644 Tests/RunCMake/InterfaceLibrary/iface.c create mode 100644 Tests/RunCMake/InterfaceLibrary/iface_broken.c create mode 100644 Tests/RunCMake/InterfaceLibrary/use_iface.c create mode 100644 Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake create mode 100644 Tests/RunCMake/VS10Project/InterfaceLibSources.cmake create mode 100644 Tests/RunCMake/VS10Project/iface.h create mode 100644 Tests/RunCMake/XcodeProject/InterfaceLibSources-check.cmake create mode 100644 Tests/RunCMake/XcodeProject/InterfaceLibSources.cmake create mode 100644 Tests/RunCMake/XcodeProject/iface.h diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst index ed8447e..f7e6792 100644 --- a/Help/command/add_library.rst +++ b/Help/command/add_library.rst @@ -118,8 +118,35 @@ target using the commands: and then it is used as an argument to :command:`target_link_libraries` like any other target. -An interface library has no source files itself and is not included -as a target in the generated buildsystem. +An interface library created with the above signature has no source files +itself and is not included as a target in the generated buildsystem. + +Since CMake 3.19, an interface library target may be created with +source files: + +.. code-block:: cmake + + add_library( INTERFACE [...] [EXCLUDE_FROM_ALL]) + +Source files may be listed directly in the ``add_library`` call or added +later by calls to :command:`target_sources` with the ``PRIVATE`` or +``PUBLIC`` keywords. + +If an interface library has source files (i.e. the :prop_tgt:`SOURCES` +target property is set), it will appear in the generated buildsystem +as a build target much like a target defined by the +:command:`add_custom_target` command. It does not compile any sources, +but does contain build rules for custom commands created by the +:command:`add_custom_command` command. + +.. note:: + In most command signatures where the ``INTERFACE`` keyword appears, + the items listed after it only become part of that target's usage + requirements and are not part of the target's own settings. However, + in this signature of ``add_library``, the ``INTERFACE`` keyword refers + to the library type only. Sources listed after it in the ``add_library`` + call are ``PRIVATE`` to the interface library and do not appear in its + :prop_tgt:`INTERFACE_SOURCES` target property. Imported Libraries ^^^^^^^^^^^^^^^^^^ diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index 6eea191..cd27316 100644 --- a/Help/manual/cmake-buildsystem.7.rst +++ b/Help/manual/cmake-buildsystem.7.rst @@ -922,8 +922,8 @@ property from it: Interface Libraries ------------------- -An ``INTERFACE`` target has no :prop_tgt:`LOCATION` and is mutable, but is -otherwise similar to an :prop_tgt:`IMPORTED` target. +An ``INTERFACE`` library target does not compile sources and does not +produce a library artifact on disk, so it has no :prop_tgt:`LOCATION`. It may specify usage requirements such as :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`, @@ -937,11 +937,22 @@ Only the ``INTERFACE`` modes of the :command:`target_include_directories`, :command:`target_sources`, and :command:`target_link_libraries` commands may be used with ``INTERFACE`` libraries. +Since CMake 3.19, an ``INTERFACE`` library target may optionally contain +source files. An interface library that contains source files will be +included as a build target in the generated buildsystem. It does not +compile sources, but may contain custom commands to generate other sources. +Additionally, IDEs will show the source files as part of the target for +interactive reading and editing. + A primary use-case for ``INTERFACE`` libraries is header-only libraries. .. code-block:: cmake - add_library(Eigen INTERFACE) + add_library(Eigen INTERFACE + src/eigen.h + src/vector.h + src/matrix.h + ) target_include_directories(Eigen INTERFACE $ $ @@ -980,7 +991,12 @@ to must be installed separately: .. code-block:: cmake - add_library(Eigen INTERFACE) + set(Eigen_headers + src/eigen.h + src/vector.h + src/matrix.h + ) + add_library(Eigen INTERFACE ${Eigen_headers}) target_include_directories(Eigen INTERFACE $ $ @@ -990,9 +1006,6 @@ to must be installed separately: install(EXPORT eigenExport NAMESPACE Upstream:: DESTINATION lib/cmake/Eigen ) - install(FILES - ${CMAKE_CURRENT_SOURCE_DIR}/src/eigen.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/vector.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/matrix.h + install(FILES ${Eigen_headers} DESTINATION include/Eigen ) diff --git a/Help/prop_tgt/EXPORT_PROPERTIES.rst b/Help/prop_tgt/EXPORT_PROPERTIES.rst index 34c054f..2d54f8b 100644 --- a/Help/prop_tgt/EXPORT_PROPERTIES.rst +++ b/Help/prop_tgt/EXPORT_PROPERTIES.rst @@ -14,3 +14,11 @@ Properties starting with ``INTERFACE_`` or ``IMPORTED_`` are not allowed as they are reserved for internal CMake use. Properties containing generator expressions are also not allowed. + +.. note:: + + Since CMake 3.19, :ref:`Interface Libraries` may have arbitrary + target properties. If a project exports an interface library + with custom properties, the resulting package may not work with + dependents configured by older versions of CMake that reject the + custom properties. diff --git a/Help/release/dev/build-interface-targets.rst b/Help/release/dev/build-interface-targets.rst new file mode 100644 index 0000000..37bded4 --- /dev/null +++ b/Help/release/dev/build-interface-targets.rst @@ -0,0 +1,6 @@ +build-interface-targets +----------------------- + +* :ref:`Interface Libraries` may now have source files added via + :command:`add_library` or :command:`target_sources`. Those + with sources will be generated as part of the build system. 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 - #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -111,20 +109,10 @@ bool cmAddLibraryCommand(std::vector 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 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 const& args, } } - std::vector srclists; - if (type == cmStateEnums::INTERFACE_LIBRARY) { if (!cmGeneratorExpression::IsValidTargetName(libName) || libName.find("::") != std::string::npos) { @@ -311,14 +293,10 @@ bool cmAddLibraryCommand(std::vector 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 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> cmGeneratorTarget::GetSourceFilePaths( std::string const& config) const { std::vector> 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 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::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::New( case cmStateEnums::OBJECT_LIBRARY: result = cm::make_unique(tgt); break; + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::UTILITY: result = cm::make_unique(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::New( return cm::make_unique(target); case cmStateEnums::UTILITY: + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::GLOBAL_TARGET: return cm::make_unique(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 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 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; } diff --git a/Tests/ExportImport/Export/Interface/CMakeLists.txt b/Tests/ExportImport/Export/Interface/CMakeLists.txt index 43b7217..ba2164b 100644 --- a/Tests/ExportImport/Export/Interface/CMakeLists.txt +++ b/Tests/ExportImport/Export/Interface/CMakeLists.txt @@ -1,11 +1,26 @@ - -add_library(headeronly INTERFACE) +set(headeronly_headers headeronly/headeronly.h) +add_library(headeronly INTERFACE ${headeronly_headers}) set_property(TARGET headeronly PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$" "$" ) set_property(TARGET headeronly PROPERTY INTERFACE_COMPILE_DEFINITIONS "HEADERONLY_DEFINE") +add_custom_command(OUTPUT headergen/headergen.h + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/headergen.h.in + ${CMAKE_CURRENT_BINARY_DIR}/headergen/headergen.h + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/headergen.h.in + VERBATIM) + +add_library(headergen INTERFACE headergen/headergen.h) +set_property(TARGET headergen PROPERTY INTERFACE_INCLUDE_DIRECTORIES + "$" +) +set_property(TARGET headergen PROPERTY PUBLIC_HEADER + ${CMAKE_CURRENT_BINARY_DIR}/headergen/headergen.h) + add_library(pch_iface INTERFACE) target_precompile_headers(pch_iface INTERFACE "$" @@ -54,6 +69,11 @@ install(TARGETS headeronly sharediface use_auto_type use_c_restrict source_targe pch_iface cmakeonly EXPORT expInterface ) +install(TARGETS headergen + EXPORT expInterface + PUBLIC_HEADER DESTINATION include/headergen + INCLUDES DESTINATION include/headergen +) install(TARGETS sharedlib EXPORT expInterface RUNTIME DESTINATION bin @@ -63,7 +83,7 @@ install(TARGETS sharedlib BUNDLE DESTINATION Applications ) install(FILES - headeronly/headeronly.h + ${headeronly_headers} DESTINATION include/headeronly ) install(FILES diff --git a/Tests/ExportImport/Export/Interface/headergen.h.in b/Tests/ExportImport/Export/Interface/headergen.h.in new file mode 100644 index 0000000..bda2b81 --- /dev/null +++ b/Tests/ExportImport/Export/Interface/headergen.h.in @@ -0,0 +1 @@ +#define HEADERGEN_H diff --git a/Tests/ExportImport/Import/Interface/CMakeLists.txt b/Tests/ExportImport/Import/Interface/CMakeLists.txt index ef666b1..202c23e 100644 --- a/Tests/ExportImport/Import/Interface/CMakeLists.txt +++ b/Tests/ExportImport/Import/Interface/CMakeLists.txt @@ -12,6 +12,9 @@ set_property(TARGET define_iface PROPERTY add_executable(headeronlytest_bld headeronlytest.cpp) target_link_libraries(headeronlytest_bld bld::headeronly) +add_executable(headergentest_bld headergentest.cpp) +target_link_libraries(headergentest_bld bld::headergen) + set_property(TARGET bld::sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface) add_executable(interfacetest_bld interfacetest.cpp) @@ -93,6 +96,9 @@ target_compile_definitions(source_target_test_exp PRIVATE USE_FROM_INSTALL_DIR) add_executable(headeronlytest_exp headeronlytest.cpp) target_link_libraries(headeronlytest_exp exp::headeronly) +add_executable(headergentest_exp headergentest.cpp) +target_link_libraries(headergentest_exp exp::headergen) + set_property(TARGET exp::sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface) add_executable(interfacetest_exp interfacetest.cpp) diff --git a/Tests/ExportImport/Import/Interface/headergentest.cpp b/Tests/ExportImport/Import/Interface/headergentest.cpp new file mode 100644 index 0000000..88ff7f1 --- /dev/null +++ b/Tests/ExportImport/Import/Interface/headergentest.cpp @@ -0,0 +1,11 @@ + +#include "headergen.h" + +#ifndef HEADERGEN_H +# error Expected HEADERGEN_H +#endif + +int main() +{ + return 0; +} diff --git a/Tests/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt index 311ca2a..ec0a604 100644 --- a/Tests/InterfaceLibrary/CMakeLists.txt +++ b/Tests/InterfaceLibrary/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable(InterfaceLibrary definetestexe.cpp) target_link_libraries(InterfaceLibrary iface_nodepends headeriface + iface_genheader subiface intermediate diff --git a/Tests/InterfaceLibrary/definetestexe.cpp b/Tests/InterfaceLibrary/definetestexe.cpp index 9156426..6c53840 100644 --- a/Tests/InterfaceLibrary/definetestexe.cpp +++ b/Tests/InterfaceLibrary/definetestexe.cpp @@ -15,6 +15,12 @@ # error Expected IFACE_HEADER_BUILDDIR #endif +#include "iface_genheader.h" + +#ifndef IFACE_GENHEADER +# error Expected IFACE_GENHEADER +#endif + extern int obj(); extern int sub(); extern int item(); diff --git a/Tests/InterfaceLibrary/headerdir/CMakeLists.txt b/Tests/InterfaceLibrary/headerdir/CMakeLists.txt index 826a9ed..ae030d7 100644 --- a/Tests/InterfaceLibrary/headerdir/CMakeLists.txt +++ b/Tests/InterfaceLibrary/headerdir/CMakeLists.txt @@ -11,3 +11,12 @@ add_custom_target(headeriface_gen VERBATIM ) add_dependencies(headeriface headeriface_gen) + +add_custom_command(OUTPUT iface_genheader.h + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/iface_genheader.h.in + ${CMAKE_CURRENT_BINARY_DIR}/iface_genheader.h + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/iface_genheader.h.in + VERBATIM) +add_library(iface_genheader INTERFACE iface_genheader.h) diff --git a/Tests/InterfaceLibrary/headerdir/iface_genheader.h.in b/Tests/InterfaceLibrary/headerdir/iface_genheader.h.in new file mode 100644 index 0000000..0a21b62 --- /dev/null +++ b/Tests/InterfaceLibrary/headerdir/iface_genheader.h.in @@ -0,0 +1 @@ +#define IFACE_GENHEADER diff --git a/Tests/RunCMake/InterfaceLibrary/ConfigSources.cmake b/Tests/RunCMake/InterfaceLibrary/ConfigSources.cmake new file mode 100644 index 0000000..631a845 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/ConfigSources.cmake @@ -0,0 +1,2 @@ +# Test an interface library added to the build system by a per-config source. +add_library(iface INTERFACE $<$:${CMAKE_CURRENT_SOURCE_DIR}/iface.c>) diff --git a/Tests/RunCMake/InterfaceLibrary/EmptySources-build2-result.txt b/Tests/RunCMake/InterfaceLibrary/EmptySources-build2-result.txt new file mode 100644 index 0000000..d197c91 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/EmptySources-build2-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/InterfaceLibrary/EmptySources-build2-stdout.txt b/Tests/RunCMake/InterfaceLibrary/EmptySources-build2-stdout.txt new file mode 100644 index 0000000..aac9172 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/EmptySources-build2-stdout.txt @@ -0,0 +1 @@ +iface2|Invalid project diff --git a/Tests/RunCMake/InterfaceLibrary/EmptySources.cmake b/Tests/RunCMake/InterfaceLibrary/EmptySources.cmake new file mode 100644 index 0000000..f452394 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/EmptySources.cmake @@ -0,0 +1,8 @@ +# Test an interface library added to the build system by empty SOURCES. +add_library(iface INTERFACE) +set_property(TARGET iface PROPERTY SOURCES "") + +# ...but not added by unset SOURCES. +add_library(iface2 INTERFACE) +set_property(TARGET iface2 PROPERTY SOURCES "") +set_property(TARGET iface2 PROPERTY SOURCES) diff --git a/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build1-check.cmake b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build1-check.cmake new file mode 100644 index 0000000..6500e48 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build1-check.cmake @@ -0,0 +1,4 @@ +if(EXISTS "${RunCMake_TEST_BINARY_DIR}/iface.txt") + set(RunCMake_TEST_FAILED "iface target built as part of 'all'") + return() +endif() diff --git a/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build2-check.cmake b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build2-check.cmake new file mode 100644 index 0000000..0977c24 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build2-check.cmake @@ -0,0 +1,4 @@ +if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/iface.txt") + set(RunCMake_TEST_FAILED "iface target not built") + return() +endif() diff --git a/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build3-result.txt b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build3-result.txt new file mode 100644 index 0000000..d197c91 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build3-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build3-stdout.txt b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build3-stdout.txt new file mode 100644 index 0000000..aac9172 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll-build3-stdout.txt @@ -0,0 +1 @@ +iface2|Invalid project diff --git a/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll.cmake b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll.cmake new file mode 100644 index 0000000..714161d --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/ExcludeFromAll.cmake @@ -0,0 +1,7 @@ +# Test an interface library with a custom command, but excluded from all. +add_custom_command(OUTPUT iface.txt COMMAND ${CMAKE_COMMAND} -E touch iface.txt) +add_library(iface INTERFACE EXCLUDE_FROM_ALL iface.txt) + +# Test that EXCLUDE_FROM_ALL is allowed even if the interface library has +# no sources, and does not cause it to appear in the build system. +add_library(iface2 INTERFACE EXCLUDE_FROM_ALL) diff --git a/Tests/RunCMake/InterfaceLibrary/PublicSources-build3-result.txt b/Tests/RunCMake/InterfaceLibrary/PublicSources-build3-result.txt new file mode 100644 index 0000000..d197c91 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/PublicSources-build3-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/InterfaceLibrary/PublicSources-build3-stdout.txt b/Tests/RunCMake/InterfaceLibrary/PublicSources-build3-stdout.txt new file mode 100644 index 0000000..aac9172 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/PublicSources-build3-stdout.txt @@ -0,0 +1 @@ +iface2|Invalid project diff --git a/Tests/RunCMake/InterfaceLibrary/PublicSources.cmake b/Tests/RunCMake/InterfaceLibrary/PublicSources.cmake new file mode 100644 index 0000000..24785bb --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/PublicSources.cmake @@ -0,0 +1,20 @@ +cmake_policy(SET CMP0076 NEW) +enable_language(C) + +# Test that an interface library can have PUBLIC sources. +# This causes the target to appear in the build system +# *and* causes consumers to use the source. +add_library(iface INTERFACE) +target_sources(iface + PUBLIC iface.c + # Private sources do not compile here or propagate. + PRIVATE iface_broken.c + ) + +# Test that an intermediate interface library does not get the +# sources and does not appear in the build system. +add_library(iface2 INTERFACE) +target_link_libraries(iface2 INTERFACE iface) + +add_executable(use_iface use_iface.c) +target_link_libraries(use_iface PRIVATE iface2) diff --git a/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake b/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake index b84bc33..834b3c8 100644 --- a/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake @@ -10,3 +10,27 @@ run_cmake(add_custom_command-TARGET) run_cmake(IMPORTED_LIBNAME-bad-value) run_cmake(IMPORTED_LIBNAME-non-iface) run_cmake(IMPORTED_LIBNAME-non-imported) + +function(run_WithSources CASE) + if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + endif() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${CASE}-build) + run_cmake(${CASE}) + set(RunCMake_TEST_NO_CLEAN 1) + foreach(build IN LISTS ARGN) + if(build MATCHES "^([^:]+)$") + run_cmake_command(${CASE}-${CMAKE_MATCH_1} ${CMAKE_COMMAND} --build . --config Debug) + elseif(build MATCHES "^([^:]+):([^:,]+)(,merge)?$") + if(CMAKE_MATCH_3 STREQUAL ",merge") + set(RunCMake_TEST_OUTPUT_MERGE 1) + endif() + run_cmake_command(${CASE}-${CMAKE_MATCH_1} ${CMAKE_COMMAND} --build . --config Debug --target ${CMAKE_MATCH_2}) + endif() + endforeach() +endfunction() + +run_WithSources(ConfigSources "build1:iface") +run_WithSources(EmptySources "build1:iface" "build2:iface2,merge") +run_WithSources(ExcludeFromAll "build1" "build2:iface" "build3:iface2,merge") +run_WithSources(PublicSources "build1" "build2:iface" "build3:iface2,merge") diff --git a/Tests/RunCMake/InterfaceLibrary/iface.c b/Tests/RunCMake/InterfaceLibrary/iface.c new file mode 100644 index 0000000..c7e7372 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/iface.c @@ -0,0 +1,4 @@ +int iface(void) +{ + return 0; +} diff --git a/Tests/RunCMake/InterfaceLibrary/iface_broken.c b/Tests/RunCMake/InterfaceLibrary/iface_broken.c new file mode 100644 index 0000000..4ff7f31 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/iface_broken.c @@ -0,0 +1 @@ +#error This file should not compile diff --git a/Tests/RunCMake/InterfaceLibrary/invalid_signature-stderr.txt b/Tests/RunCMake/InterfaceLibrary/invalid_signature-stderr.txt index 6374b33..763f9f8 100644 --- a/Tests/RunCMake/InterfaceLibrary/invalid_signature-stderr.txt +++ b/Tests/RunCMake/InterfaceLibrary/invalid_signature-stderr.txt @@ -1,8 +1,3 @@ -CMake Error at invalid_signature.cmake:2 \(add_library\): - add_library INTERFACE library requires no source arguments. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) -+ CMake Error at invalid_signature.cmake:3 \(add_library\): add_library INTERFACE library specified with conflicting/multiple types. Call Stack \(most recent call first\): @@ -73,16 +68,6 @@ CMake Error at invalid_signature.cmake:16 \(add_library\): Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) + -CMake Error at invalid_signature.cmake:17 \(add_library\): - add_library INTERFACE library may not be used with EXCLUDE_FROM_ALL. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) -+ -CMake Error at invalid_signature.cmake:18 \(add_library\): - add_library INTERFACE library may not be used with EXCLUDE_FROM_ALL. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) -+ CMake Error at invalid_signature.cmake:20 \(add_library\): add_library GLOBAL option may only be used with IMPORTED libraries. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/InterfaceLibrary/invalid_signature.cmake b/Tests/RunCMake/InterfaceLibrary/invalid_signature.cmake index 4e53534..2a575b5 100644 --- a/Tests/RunCMake/InterfaceLibrary/invalid_signature.cmake +++ b/Tests/RunCMake/InterfaceLibrary/invalid_signature.cmake @@ -1,5 +1,5 @@ -add_library(iface1 INTERFACE empty.cpp) + add_library(iface3 STATIC INTERFACE) add_library(iface4 STATIC INTERFACE empty.cpp) add_library(iface5 SHARED INTERFACE) @@ -14,7 +14,7 @@ add_library(iface13 INTERFACE UNKNOWN) add_library(iface14 INTERFACE ALIAS) add_library(iface15 ALIAS INTERFACE) add_library(iface16 INTERFACE INTERFACE) -add_library(iface17 INTERFACE EXCLUDE_FROM_ALL) -add_library(iface18 EXCLUDE_FROM_ALL INTERFACE) + + # add_library(iface19 GLOBAL INTERFACE) Tested separately add_library(iface20 INTERFACE GLOBAL) diff --git a/Tests/RunCMake/InterfaceLibrary/use_iface.c b/Tests/RunCMake/InterfaceLibrary/use_iface.c new file mode 100644 index 0000000..66293e4 --- /dev/null +++ b/Tests/RunCMake/InterfaceLibrary/use_iface.c @@ -0,0 +1,6 @@ +extern int iface(void); + +int main(void) +{ + return iface(); +} diff --git a/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake new file mode 100644 index 0000000..bcdc101 --- /dev/null +++ b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake @@ -0,0 +1,25 @@ +set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/iface.vcxproj") +if(NOT EXISTS "${vcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") + return() +endif() + +set(found_iface_h 0) +file(STRINGS "${vcProjectFile}" lines) +foreach(line IN LISTS lines) + if(line MATCHES "<([A-Za-z0-9_]+) +Include=.*iface\\.h") + set(rule "${CMAKE_MATCH_1}") + if(NOT rule STREQUAL "None") + set(RunCMake_TEST_FAILED "iface.h referenced as ${rule} instead of None in\n ${vcProjectFile}") + return() + endif() + if(found_iface_h) + set(RunCMake_TEST_FAILED "iface.h referenced multiple times in\n ${vcProjectFile}") + return() + endif() + set(found_iface_h 1) + endif() +endforeach() +if(NOT found_iface_h) + set(RunCMake_TEST_FAILED "iface.h not referenced in\n ${vcProjectFile}") +endif() diff --git a/Tests/RunCMake/VS10Project/InterfaceLibSources.cmake b/Tests/RunCMake/VS10Project/InterfaceLibSources.cmake new file mode 100644 index 0000000..3672be1 --- /dev/null +++ b/Tests/RunCMake/VS10Project/InterfaceLibSources.cmake @@ -0,0 +1 @@ +add_library(iface INTERFACE iface.h) diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index 93ef603..e9f251a 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -6,6 +6,7 @@ cmake_policy(SET CMP0054 NEW) run_cmake(VsCsharpSourceGroup) run_cmake(VsCSharpCompilerOpts) run_cmake(ExplicitCMakeLists) +run_cmake(InterfaceLibSources) run_cmake(RuntimeLibrary) run_cmake(SourceGroupCMakeLists) run_cmake(SourceGroupTreeCMakeLists) diff --git a/Tests/RunCMake/VS10Project/iface.h b/Tests/RunCMake/VS10Project/iface.h new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/XcodeProject/InterfaceLibSources-check.cmake b/Tests/RunCMake/XcodeProject/InterfaceLibSources-check.cmake new file mode 100644 index 0000000..613951a --- /dev/null +++ b/Tests/RunCMake/XcodeProject/InterfaceLibSources-check.cmake @@ -0,0 +1,16 @@ +set(xcProjectFile "${RunCMake_TEST_BINARY_DIR}/InterfaceLibSources.xcodeproj/project.pbxproj") +if(NOT EXISTS "${xcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${xcProjectFile} does not exist.") + return() +endif() + +set(found_iface_h 0) +file(STRINGS "${xcProjectFile}" lines) +foreach(line IN LISTS lines) + if(line MATCHES "PBXFileReference.*explicitFileType.*sourcecode\\.c\\.h.*iface\\.h") + set(found_iface_h 1) + endif() +endforeach() +if(NOT found_iface_h) + set(RunCMake_TEST_FAILED "iface.h not referenced in\n ${xcProjectFile}") +endif() diff --git a/Tests/RunCMake/XcodeProject/InterfaceLibSources.cmake b/Tests/RunCMake/XcodeProject/InterfaceLibSources.cmake new file mode 100644 index 0000000..3672be1 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/InterfaceLibSources.cmake @@ -0,0 +1 @@ +add_library(iface INTERFACE iface.h) diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index 342dbbc..cd6fd06 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -2,6 +2,7 @@ include(RunCMake) run_cmake(ExplicitCMakeLists) run_cmake(ImplicitCMakeLists) +run_cmake(InterfaceLibSources) run_cmake(XcodeFileType) run_cmake(XcodeAttributeLocation) diff --git a/Tests/RunCMake/XcodeProject/iface.h b/Tests/RunCMake/XcodeProject/iface.h new file mode 100644 index 0000000..e69de29 -- cgit v0.12 From bafa9fe8876387fa16cc8c03832d27df81238af1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 20 Jul 2020 15:30:31 -0400 Subject: fileapi: Add INTERFACE libraries with SOURCES to codemodel-v2 INTERFACE libraries with SOURCES now appear in the generated buildsystem, so include them in the codemodel output too. We do not need to bump the `codemodel-v2` object kind minor version because that was already done in post-3.18 development by commit 7d6861f367 (fileapi: Extend codemodel targets with language standard, 2020-06-18). Fixes: #18608 --- Help/manual/cmake-file-api.7.rst | 3 +- Source/cmFileAPICodemodel.cxx | 2 +- Tests/RunCMake/FileAPI/codemodel-v2-check.py | 6 ++ .../codemodel-v2-data/directories/interface.json | 14 ++++ .../FileAPI/codemodel-v2-data/directories/top.json | 1 + .../codemodel-v2-data/projects/codemodel-v2.json | 1 + .../codemodel-v2-data/projects/interface.json | 13 ++++ .../targets/all_build_interface.json | 79 ++++++++++++++++++++++ .../codemodel-v2-data/targets/all_build_top.json | 4 ++ .../FileAPI/codemodel-v2-data/targets/cxx_exe.json | 2 +- .../codemodel-v2-data/targets/iface_srcs.json | 67 ++++++++++++++++++ .../targets/zero_check_interface.json | 70 +++++++++++++++++++ Tests/RunCMake/FileAPI/codemodel-v2.cmake | 1 + Tests/RunCMake/FileAPI/interface/CMakeLists.txt | 3 + 14 files changed, 263 insertions(+), 3 deletions(-) create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-data/projects/interface.json create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_interface.json create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-data/targets/iface_srcs.json create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-data/targets/zero_check_interface.json create mode 100644 Tests/RunCMake/FileAPI/interface/CMakeLists.txt diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 34edc56..6876e1c 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -650,7 +650,8 @@ with members: ``type`` A string specifying the type of the target. The value is one of ``EXECUTABLE``, ``STATIC_LIBRARY``, ``SHARED_LIBRARY``, - ``MODULE_LIBRARY``, ``OBJECT_LIBRARY``, or ``UTILITY``. + ``MODULE_LIBRARY``, ``OBJECT_LIBRARY``, ``INTERFACE_LIBRARY``, + or ``UTILITY``. ``backtrace`` Optional member that is present when a CMake language backtrace to diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index e9af208..55fb115 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -625,7 +625,7 @@ Json::Value CodemodelConfig::DumpTargets() for (cmGeneratorTarget* gt : targetList) { if (gt->GetType() == cmStateEnums::GLOBAL_TARGET || - gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + !gt->IsInBuildSystem()) { continue; } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index b567bf1..c66757f 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -522,6 +522,7 @@ def gen_check_directories(c, g): read_codemodel_json_data("directories/custom.json"), read_codemodel_json_data("directories/cxx.json"), read_codemodel_json_data("directories/imported.json"), + read_codemodel_json_data("directories/interface.json"), read_codemodel_json_data("directories/object.json"), read_codemodel_json_data("directories/dir.json"), read_codemodel_json_data("directories/dir_dir.json"), @@ -594,6 +595,10 @@ def gen_check_targets(c, g, inSource): read_codemodel_json_data("targets/link_imported_object_exe.json"), read_codemodel_json_data("targets/link_imported_interface_exe.json"), + read_codemodel_json_data("targets/all_build_interface.json"), + read_codemodel_json_data("targets/zero_check_interface.json"), + read_codemodel_json_data("targets/iface_srcs.json"), + read_codemodel_json_data("targets/all_build_custom.json"), read_codemodel_json_data("targets/zero_check_custom.json"), read_codemodel_json_data("targets/custom_tgt.json"), @@ -722,6 +727,7 @@ def gen_check_projects(c, g): read_codemodel_json_data("projects/alias.json"), read_codemodel_json_data("projects/object.json"), read_codemodel_json_data("projects/imported.json"), + read_codemodel_json_data("projects/interface.json"), read_codemodel_json_data("projects/custom.json"), read_codemodel_json_data("projects/external.json"), ] diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json new file mode 100644 index 0000000..b10d496 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json @@ -0,0 +1,14 @@ +{ + "source": "^interface$", + "build": "^interface$", + "parentSource": "^\\.$", + "childSources": null, + "targetIds": [ + "^ALL_BUILD::@25b7fa8ea00134654b85$", + "^ZERO_CHECK::@25b7fa8ea00134654b85$", + "^iface_srcs::@25b7fa8ea00134654b85$" + ], + "projectName": "Interface", + "minimumCMakeVersion": "3.12", + "hasInstallRule": null +} diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json index c144953..736d1f5 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json @@ -7,6 +7,7 @@ "^custom$", "^cxx$", "^imported$", + "^interface$", "^object$", "^.*/Tests/RunCMake/FileAPIExternalSource$", "^dir$" diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json index f3aac63..4d0cdc0 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json @@ -6,6 +6,7 @@ "Custom", "Cxx", "Imported", + "Interface", "Object", "External" ], diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/interface.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/interface.json new file mode 100644 index 0000000..2a22767 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/interface.json @@ -0,0 +1,13 @@ +{ + "name": "Interface", + "parentName": "codemodel-v2", + "childNames": null, + "directorySources": [ + "^interface$" + ], + "targetIds": [ + "^ALL_BUILD::@25b7fa8ea00134654b85$", + "^ZERO_CHECK::@25b7fa8ea00134654b85$", + "^iface_srcs::@25b7fa8ea00134654b85$" + ] +} diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_interface.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_interface.json new file mode 100644 index 0000000..fa2a6e5 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_interface.json @@ -0,0 +1,79 @@ +{ + "name": "ALL_BUILD", + "id": "^ALL_BUILD::@25b7fa8ea00134654b85$", + "directorySource": "^interface$", + "projectName": "Interface", + "type": "UTILITY", + "isGeneratorProvided": true, + "sources": [ + { + "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/interface/CMakeFiles/ALL_BUILD$", + "isGenerated": true, + "sourceGroupName": "", + "compileGroupLanguage": null, + "backtrace": [ + { + "file": "^interface/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/interface/CMakeFiles/ALL_BUILD\\.rule$", + "isGenerated": true, + "sourceGroupName": "CMake Rules", + "compileGroupLanguage": null, + "backtrace": [ + { + "file": "^interface/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ], + "sourceGroups": [ + { + "name": "", + "sourcePaths": [ + "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/interface/CMakeFiles/ALL_BUILD$" + ] + }, + { + "name": "CMake Rules", + "sourcePaths": [ + "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/interface/CMakeFiles/ALL_BUILD\\.rule$" + ] + } + ], + "compileGroups": null, + "backtrace": [ + { + "file": "^interface/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ], + "folder": null, + "nameOnDisk": null, + "artifacts": null, + "build": "^interface$", + "source": "^interface$", + "install": null, + "link": null, + "archive": null, + "dependencies": [ + { + "id": "^ZERO_CHECK::@25b7fa8ea00134654b85$", + "backtrace": null + }, + { + "id": "^iface_srcs::@25b7fa8ea00134654b85$", + "backtrace": null + } + ] +} diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json index 59bd750..d023f99 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json @@ -176,6 +176,10 @@ "backtrace": null }, { + "id": "^iface_srcs::@25b7fa8ea00134654b85$", + "backtrace": null + }, + { "id": "^custom_exe::@c11385ffed57b860da63$", "backtrace": null }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json index e7ab55b..c9e652b 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json @@ -119,7 +119,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 37, + "line": 38, "command": "install", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/iface_srcs.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/iface_srcs.json new file mode 100644 index 0000000..97d7ccd --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/iface_srcs.json @@ -0,0 +1,67 @@ +{ + "name": "iface_srcs", + "id": "^iface_srcs::@25b7fa8ea00134654b85$", + "directorySource": "^interface$", + "projectName": "Interface", + "type": "INTERFACE_LIBRARY", + "isGeneratorProvided": null, + "sources": [ + { + "path": "^empty\\.c$", + "isGenerated": null, + "sourceGroupName": "Source Files", + "compileGroupLanguage": null, + "backtrace": [ + { + "file": "^interface/CMakeLists\\.txt$", + "line": 3, + "command": "add_library", + "hasParent": true + }, + { + "file": "^interface/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ], + "sourceGroups": [ + { + "name": "Source Files", + "sourcePaths": [ + "^empty\\.c$" + ] + } + ], + "compileGroups": null, + "backtrace": [ + { + "file": "^interface/CMakeLists\\.txt$", + "line": 3, + "command": "add_library", + "hasParent": true + }, + { + "file": "^interface/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ], + "folder": null, + "nameOnDisk": null, + "artifacts": null, + "build": "^interface$", + "source": "^interface$", + "install": null, + "link": null, + "archive": null, + "dependencies": [ + { + "id": "^ZERO_CHECK::@25b7fa8ea00134654b85$", + "backtrace": null + } + ] +} diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/zero_check_interface.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/zero_check_interface.json new file mode 100644 index 0000000..fdd4b2a --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/zero_check_interface.json @@ -0,0 +1,70 @@ +{ + "name": "ZERO_CHECK", + "id": "^ZERO_CHECK::@25b7fa8ea00134654b85$", + "directorySource": "^interface$", + "projectName": "Interface", + "type": "UTILITY", + "isGeneratorProvided": true, + "sources": [ + { + "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/interface/CMakeFiles/ZERO_CHECK$", + "isGenerated": true, + "sourceGroupName": "", + "compileGroupLanguage": null, + "backtrace": [ + { + "file": "^interface/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/interface/CMakeFiles/ZERO_CHECK\\.rule$", + "isGenerated": true, + "sourceGroupName": "CMake Rules", + "compileGroupLanguage": null, + "backtrace": [ + { + "file": "^interface/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ], + "sourceGroups": [ + { + "name": "", + "sourcePaths": [ + "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/interface/CMakeFiles/ZERO_CHECK$" + ] + }, + { + "name": "CMake Rules", + "sourcePaths": [ + "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/interface/CMakeFiles/ZERO_CHECK\\.rule$" + ] + } + ], + "compileGroups": null, + "backtrace": [ + { + "file": "^interface/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ], + "folder": null, + "nameOnDisk": null, + "artifacts": null, + "build": "^interface$", + "source": "^interface$", + "install": null, + "link": null, + "archive": null, + "dependencies": null +} diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake index c98a84c..2405954 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake +++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake @@ -18,6 +18,7 @@ add_subdirectory(cxx) add_subdirectory(alias) add_subdirectory(object) add_subdirectory(imported) +add_subdirectory(interface) add_subdirectory(custom) add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../FileAPIExternalSource" "${CMAKE_CURRENT_BINARY_DIR}/../FileAPIExternalBuild") add_subdirectory(dir) diff --git a/Tests/RunCMake/FileAPI/interface/CMakeLists.txt b/Tests/RunCMake/FileAPI/interface/CMakeLists.txt new file mode 100644 index 0000000..97948c5 --- /dev/null +++ b/Tests/RunCMake/FileAPI/interface/CMakeLists.txt @@ -0,0 +1,3 @@ +project(Interface) +add_library(iface_none INTERFACE) +add_library(iface_srcs INTERFACE ../empty.c) -- cgit v0.12