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
This commit is contained in:
parent
afb998704e
commit
4391913133
@ -118,8 +118,35 @@ target using the commands:
|
|||||||
and then it is used as an argument to :command:`target_link_libraries`
|
and then it is used as an argument to :command:`target_link_libraries`
|
||||||
like any other target.
|
like any other target.
|
||||||
|
|
||||||
An interface library has no source files itself and is not included
|
An interface library created with the above signature has no source files
|
||||||
as a target in the generated buildsystem.
|
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(<name> INTERFACE [<source>...] [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
|
Imported Libraries
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -922,8 +922,8 @@ property from it:
|
|||||||
Interface Libraries
|
Interface Libraries
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
An ``INTERFACE`` target has no :prop_tgt:`LOCATION` and is mutable, but is
|
An ``INTERFACE`` library target does not compile sources and does not
|
||||||
otherwise similar to an :prop_tgt:`IMPORTED` target.
|
produce a library artifact on disk, so it has no :prop_tgt:`LOCATION`.
|
||||||
|
|
||||||
It may specify usage requirements such as
|
It may specify usage requirements such as
|
||||||
:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`,
|
: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
|
:command:`target_sources`, and :command:`target_link_libraries` commands
|
||||||
may be used with ``INTERFACE`` libraries.
|
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.
|
A primary use-case for ``INTERFACE`` libraries is header-only libraries.
|
||||||
|
|
||||||
.. code-block:: cmake
|
.. 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
|
target_include_directories(Eigen INTERFACE
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||||
$<INSTALL_INTERFACE:include/Eigen>
|
$<INSTALL_INTERFACE:include/Eigen>
|
||||||
@ -980,7 +991,12 @@ to must be installed separately:
|
|||||||
|
|
||||||
.. code-block:: cmake
|
.. 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
|
target_include_directories(Eigen INTERFACE
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||||
$<INSTALL_INTERFACE:include/Eigen>
|
$<INSTALL_INTERFACE:include/Eigen>
|
||||||
@ -990,9 +1006,6 @@ to must be installed separately:
|
|||||||
install(EXPORT eigenExport NAMESPACE Upstream::
|
install(EXPORT eigenExport NAMESPACE Upstream::
|
||||||
DESTINATION lib/cmake/Eigen
|
DESTINATION lib/cmake/Eigen
|
||||||
)
|
)
|
||||||
install(FILES
|
install(FILES ${Eigen_headers}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/eigen.h
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/vector.h
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/matrix.h
|
|
||||||
DESTINATION include/Eigen
|
DESTINATION include/Eigen
|
||||||
)
|
)
|
||||||
|
@ -14,3 +14,11 @@ Properties starting with ``INTERFACE_`` or ``IMPORTED_`` are not allowed as
|
|||||||
they are reserved for internal CMake use.
|
they are reserved for internal CMake use.
|
||||||
|
|
||||||
Properties containing generator expressions are also not allowed.
|
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.
|
||||||
|
6
Help/release/dev/build-interface-targets.rst
Normal file
6
Help/release/dev/build-interface-targets.rst
Normal file
@ -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.
|
@ -2,8 +2,6 @@
|
|||||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||||
#include "cmAddLibraryCommand.h"
|
#include "cmAddLibraryCommand.h"
|
||||||
|
|
||||||
#include <cmext/algorithm>
|
|
||||||
|
|
||||||
#include "cmExecutionStatus.h"
|
#include "cmExecutionStatus.h"
|
||||||
#include "cmGeneratorExpression.h"
|
#include "cmGeneratorExpression.h"
|
||||||
#include "cmGlobalGenerator.h"
|
#include "cmGlobalGenerator.h"
|
||||||
@ -111,20 +109,10 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
|
|||||||
"INTERFACE library specified with conflicting ALIAS type.");
|
"INTERFACE library specified with conflicting ALIAS type.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (excludeFromAll) {
|
|
||||||
status.SetError(
|
|
||||||
"INTERFACE library may not be used with EXCLUDE_FROM_ALL.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
++s;
|
++s;
|
||||||
type = cmStateEnums::INTERFACE_LIBRARY;
|
type = cmStateEnums::INTERFACE_LIBRARY;
|
||||||
haveSpecifiedType = true;
|
haveSpecifiedType = true;
|
||||||
} else if (*s == "EXCLUDE_FROM_ALL") {
|
} 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;
|
++s;
|
||||||
excludeFromAll = true;
|
excludeFromAll = true;
|
||||||
} else if (*s == "IMPORTED") {
|
} else if (*s == "IMPORTED") {
|
||||||
@ -143,10 +131,6 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type == cmStateEnums::INTERFACE_LIBRARY) {
|
if (type == cmStateEnums::INTERFACE_LIBRARY) {
|
||||||
if (s != args.end()) {
|
|
||||||
status.SetError("INTERFACE library requires no source arguments.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (importGlobal && !importTarget) {
|
if (importGlobal && !importTarget) {
|
||||||
status.SetError(
|
status.SetError(
|
||||||
"INTERFACE library specified as GLOBAL, but not as IMPORTED.");
|
"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 (type == cmStateEnums::INTERFACE_LIBRARY) {
|
||||||
if (!cmGeneratorExpression::IsValidTargetName(libName) ||
|
if (!cmGeneratorExpression::IsValidTargetName(libName) ||
|
||||||
libName.find("::") != std::string::npos) {
|
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));
|
cmStrCat("Invalid name for INTERFACE library target: ", libName));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mf.AddLibrary(libName, type, srclists, excludeFromAll);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cm::append(srclists, s, args.end());
|
std::vector<std::string> srcs(s, args.end());
|
||||||
|
mf.AddLibrary(libName, type, srcs, excludeFromAll);
|
||||||
mf.AddLibrary(libName, type, srclists, excludeFromAll);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1099,6 +1099,10 @@ bool cmGeneratorTarget::IsInBuildSystem() const
|
|||||||
case cmStateEnums::GLOBAL_TARGET:
|
case cmStateEnums::GLOBAL_TARGET:
|
||||||
return true;
|
return true;
|
||||||
case cmStateEnums::INTERFACE_LIBRARY:
|
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:
|
case cmStateEnums::UNKNOWN_LIBRARY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1543,7 +1547,6 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
|
|||||||
std::string const& config) const
|
std::string const& config) const
|
||||||
{
|
{
|
||||||
std::vector<BT<std::string>> files;
|
std::vector<BT<std::string>> files;
|
||||||
assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
|
|
||||||
|
|
||||||
if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
|
if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
|
||||||
// At configure-time, this method can be called as part of getting the
|
// 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());
|
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
|
||||||
if (sf->GetCustomCommand()) {
|
if (sf->GetCustomCommand()) {
|
||||||
kind = SourceKindCustomCommand;
|
kind = SourceKindCustomCommand;
|
||||||
// XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
|
} else if (this->Target->GetType() == cmStateEnums::UTILITY ||
|
||||||
// NOLINTNEXTLINE(bugprone-branch-clone)
|
this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY
|
||||||
} else if (this->Target->GetType() == cmStateEnums::UTILITY) {
|
// XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
|
||||||
|
// NOLINTNEXTLINE(bugprone-branch-clone)
|
||||||
|
) {
|
||||||
kind = SourceKindExtra;
|
kind = SourceKindExtra;
|
||||||
} else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
|
} else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
|
||||||
kind = SourceKindUnityBatched;
|
kind = SourceKindUnityBatched;
|
||||||
|
@ -1093,6 +1093,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
|
|||||||
}
|
}
|
||||||
// FALLTHROUGH
|
// FALLTHROUGH
|
||||||
case cmStateEnums::GLOBAL_TARGET:
|
case cmStateEnums::GLOBAL_TARGET:
|
||||||
|
case cmStateEnums::INTERFACE_LIBRARY:
|
||||||
case cmStateEnums::UTILITY: {
|
case cmStateEnums::UTILITY: {
|
||||||
std::string path =
|
std::string path =
|
||||||
cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/',
|
cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/',
|
||||||
@ -1105,7 +1106,6 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case cmStateEnums::INTERFACE_LIBRARY:
|
|
||||||
case cmStateEnums::UNKNOWN_LIBRARY:
|
case cmStateEnums::UNKNOWN_LIBRARY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1204,6 +1204,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gtgt->GetType() == cmStateEnums::UTILITY ||
|
if (gtgt->GetType() == cmStateEnums::UTILITY ||
|
||||||
|
gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
|
||||||
gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
|
gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
|
||||||
cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
|
cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
|
||||||
if (!t) {
|
if (!t) {
|
||||||
@ -2536,7 +2537,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
|
|||||||
this->XCodeObjectMap[gtgt] = target;
|
this->XCodeObjectMap[gtgt] = target;
|
||||||
|
|
||||||
// Add source files without build rules for editing convenience.
|
// 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) {
|
gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
|
||||||
std::vector<cmSourceFile*> sources;
|
std::vector<cmSourceFile*> sources;
|
||||||
if (!gtgt->GetConfigCommonSourceFiles(sources)) {
|
if (!gtgt->GetConfigCommonSourceFiles(sources)) {
|
||||||
|
@ -629,9 +629,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
|
|||||||
break;
|
break;
|
||||||
case cmStateEnums::UTILITY:
|
case cmStateEnums::UTILITY:
|
||||||
case cmStateEnums::GLOBAL_TARGET:
|
case cmStateEnums::GLOBAL_TARGET:
|
||||||
|
case cmStateEnums::INTERFACE_LIBRARY:
|
||||||
configType = "10";
|
configType = "10";
|
||||||
CM_FALLTHROUGH;
|
CM_FALLTHROUGH;
|
||||||
default:
|
case cmStateEnums::UNKNOWN_LIBRARY:
|
||||||
targetBuilds = false;
|
targetBuilds = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1638,7 +1639,8 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
|
|||||||
std::string source = sf->GetFullPath();
|
std::string source = sf->GetFullPath();
|
||||||
|
|
||||||
if (source != libName || target->GetType() == cmStateEnums::UTILITY ||
|
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.
|
// Look up the source kind and configs.
|
||||||
std::map<cmSourceFile const*, size_t>::const_iterator map_it =
|
std::map<cmSourceFile const*, size_t>::const_iterator map_it =
|
||||||
sources.Index.find(sf);
|
sources.Index.find(sf);
|
||||||
@ -1937,6 +1939,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran(
|
|||||||
const char* keyword = p ? p->c_str() : "Console Application";
|
const char* keyword = p ? p->c_str() : "Console Application";
|
||||||
const char* projectType = 0;
|
const char* projectType = 0;
|
||||||
switch (target->GetType()) {
|
switch (target->GetType()) {
|
||||||
|
case cmStateEnums::OBJECT_LIBRARY:
|
||||||
case cmStateEnums::STATIC_LIBRARY:
|
case cmStateEnums::STATIC_LIBRARY:
|
||||||
projectType = "typeStaticLibrary";
|
projectType = "typeStaticLibrary";
|
||||||
if (keyword) {
|
if (keyword) {
|
||||||
@ -1958,7 +1961,8 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran(
|
|||||||
break;
|
break;
|
||||||
case cmStateEnums::UTILITY:
|
case cmStateEnums::UTILITY:
|
||||||
case cmStateEnums::GLOBAL_TARGET:
|
case cmStateEnums::GLOBAL_TARGET:
|
||||||
default:
|
case cmStateEnums::INTERFACE_LIBRARY:
|
||||||
|
case cmStateEnums::UNKNOWN_LIBRARY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (projectType) {
|
if (projectType) {
|
||||||
|
@ -71,6 +71,7 @@ std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New(
|
|||||||
case cmStateEnums::OBJECT_LIBRARY:
|
case cmStateEnums::OBJECT_LIBRARY:
|
||||||
result = cm::make_unique<cmMakefileLibraryTargetGenerator>(tgt);
|
result = cm::make_unique<cmMakefileLibraryTargetGenerator>(tgt);
|
||||||
break;
|
break;
|
||||||
|
case cmStateEnums::INTERFACE_LIBRARY:
|
||||||
case cmStateEnums::UTILITY:
|
case cmStateEnums::UTILITY:
|
||||||
result = cm::make_unique<cmMakefileUtilityTargetGenerator>(tgt);
|
result = cm::make_unique<cmMakefileUtilityTargetGenerator>(tgt);
|
||||||
break;
|
break;
|
||||||
|
@ -51,6 +51,7 @@ std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New(
|
|||||||
return cm::make_unique<cmNinjaNormalTargetGenerator>(target);
|
return cm::make_unique<cmNinjaNormalTargetGenerator>(target);
|
||||||
|
|
||||||
case cmStateEnums::UTILITY:
|
case cmStateEnums::UTILITY:
|
||||||
|
case cmStateEnums::INTERFACE_LIBRARY:
|
||||||
case cmStateEnums::GLOBAL_TARGET:
|
case cmStateEnums::GLOBAL_TARGET:
|
||||||
return cm::make_unique<cmNinjaUtilityTargetGenerator>(target);
|
return cm::make_unique<cmNinjaUtilityTargetGenerator>(target);
|
||||||
|
|
||||||
|
@ -401,12 +401,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
|
initProp("FOLDER");
|
||||||
initProp("FOLDER");
|
|
||||||
|
|
||||||
if (this->GetGlobalGenerator()->IsXcode()) {
|
if (this->GetGlobalGenerator()->IsXcode()) {
|
||||||
initProp("XCODE_GENERATE_SCHEME");
|
initProp("XCODE_GENERATE_SCHEME");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup per-configuration property default values.
|
// Setup per-configuration property default values.
|
||||||
@ -521,24 +519,21 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
|
|||||||
initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
|
initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
|
// check for "CMAKE_VS_GLOBALS" variable and set up target properties
|
||||||
|
// if any
|
||||||
// check for "CMAKE_VS_GLOBALS" variable and set up target properties
|
const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
|
||||||
// if any
|
if (globals) {
|
||||||
const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
|
const std::string genName = mf->GetGlobalGenerator()->GetName();
|
||||||
if (globals) {
|
if (cmHasLiteralPrefix(genName, "Visual Studio")) {
|
||||||
const std::string genName = mf->GetGlobalGenerator()->GetName();
|
std::vector<std::string> props = cmExpandedList(globals);
|
||||||
if (cmHasLiteralPrefix(genName, "Visual Studio")) {
|
const std::string vsGlobal = "VS_GLOBAL_";
|
||||||
std::vector<std::string> props = cmExpandedList(globals);
|
for (const std::string& i : props) {
|
||||||
const std::string vsGlobal = "VS_GLOBAL_";
|
// split NAME=VALUE
|
||||||
for (const std::string& i : props) {
|
const std::string::size_type assignment = i.find('=');
|
||||||
// split NAME=VALUE
|
if (assignment != std::string::npos) {
|
||||||
const std::string::size_type assignment = i.find('=');
|
const std::string propName = vsGlobal + i.substr(0, assignment);
|
||||||
if (assignment != std::string::npos) {
|
const std::string propValue = i.substr(assignment + 1);
|
||||||
const std::string propName = vsGlobal + i.substr(0, assignment);
|
initPropValue(propName, propValue.c_str());
|
||||||
const std::string propValue = i.substr(assignment + 1);
|
|
||||||
initPropValue(propName, propValue.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
|
|||||||
}
|
}
|
||||||
if (!content.empty()) {
|
if (!content.empty()) {
|
||||||
if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
|
if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
|
||||||
scope != "INTERFACE") {
|
scope != "INTERFACE" && this->Property != "SOURCES") {
|
||||||
this->SetError("may only set INTERFACE properties on INTERFACE targets");
|
this->SetError("may only set INTERFACE properties on INTERFACE targets");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -315,8 +315,7 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
|
|||||||
void cmVisualStudio10TargetGenerator::Generate()
|
void cmVisualStudio10TargetGenerator::Generate()
|
||||||
{
|
{
|
||||||
// do not generate external ms projects
|
// do not generate external ms projects
|
||||||
if (this->GeneratorTarget->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
|
if (this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) {
|
||||||
this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const std::string ProjectFileExtension =
|
const std::string ProjectFileExtension =
|
||||||
@ -437,7 +436,7 @@ void cmVisualStudio10TargetGenerator::Generate()
|
|||||||
e1.Element("ProjectGuid", "{" + this->GUID + "}");
|
e1.Element("ProjectGuid", "{" + this->GUID + "}");
|
||||||
|
|
||||||
if ((this->MSTools || this->Android) &&
|
if ((this->MSTools || this->Android) &&
|
||||||
this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
|
this->GeneratorTarget->IsInBuildSystem()) {
|
||||||
this->WriteApplicationTypeSettings(e1);
|
this->WriteApplicationTypeSettings(e1);
|
||||||
this->VerifyNecessaryFiles();
|
this->VerifyNecessaryFiles();
|
||||||
}
|
}
|
||||||
@ -605,11 +604,11 @@ void cmVisualStudio10TargetGenerator::Generate()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case cmStateEnums::UTILITY:
|
case cmStateEnums::UTILITY:
|
||||||
|
case cmStateEnums::INTERFACE_LIBRARY:
|
||||||
case cmStateEnums::GLOBAL_TARGET:
|
case cmStateEnums::GLOBAL_TARGET:
|
||||||
outputType = "Utility";
|
outputType = "Utility";
|
||||||
break;
|
break;
|
||||||
case cmStateEnums::UNKNOWN_LIBRARY:
|
case cmStateEnums::UNKNOWN_LIBRARY:
|
||||||
case cmStateEnums::INTERFACE_LIBRARY:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
e1.Element("OutputType", outputType);
|
e1.Element("OutputType", outputType);
|
||||||
@ -1157,6 +1156,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case cmStateEnums::UTILITY:
|
case cmStateEnums::UTILITY:
|
||||||
|
case cmStateEnums::INTERFACE_LIBRARY:
|
||||||
case cmStateEnums::GLOBAL_TARGET:
|
case cmStateEnums::GLOBAL_TARGET:
|
||||||
if (this->NsightTegra) {
|
if (this->NsightTegra) {
|
||||||
// Tegra-Android platform does not understand "Utility".
|
// Tegra-Android platform does not understand "Utility".
|
||||||
@ -1166,7 +1166,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case cmStateEnums::UNKNOWN_LIBRARY:
|
case cmStateEnums::UNKNOWN_LIBRARY:
|
||||||
case cmStateEnums::INTERFACE_LIBRARY:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2152,7 +2151,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
|
|||||||
|
|
||||||
void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
|
void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
|
||||||
{
|
{
|
||||||
if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
|
if (this->GeneratorTarget->GetType() == cmStateEnums::GLOBAL_TARGET) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,26 @@
|
|||||||
|
set(headeronly_headers headeronly/headeronly.h)
|
||||||
add_library(headeronly INTERFACE)
|
add_library(headeronly INTERFACE ${headeronly_headers})
|
||||||
set_property(TARGET headeronly PROPERTY INTERFACE_INCLUDE_DIRECTORIES
|
set_property(TARGET headeronly PROPERTY INTERFACE_INCLUDE_DIRECTORIES
|
||||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/headeronly>"
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/headeronly>"
|
||||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/headeronly>"
|
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/headeronly>"
|
||||||
)
|
)
|
||||||
set_property(TARGET headeronly PROPERTY INTERFACE_COMPILE_DEFINITIONS "HEADERONLY_DEFINE")
|
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
|
||||||
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/headergen>"
|
||||||
|
)
|
||||||
|
set_property(TARGET headergen PROPERTY PUBLIC_HEADER
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/headergen/headergen.h)
|
||||||
|
|
||||||
add_library(pch_iface INTERFACE)
|
add_library(pch_iface INTERFACE)
|
||||||
target_precompile_headers(pch_iface INTERFACE
|
target_precompile_headers(pch_iface INTERFACE
|
||||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/pch/pch.h>"
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/pch/pch.h>"
|
||||||
@ -54,6 +69,11 @@ install(TARGETS headeronly sharediface use_auto_type use_c_restrict source_targe
|
|||||||
pch_iface cmakeonly
|
pch_iface cmakeonly
|
||||||
EXPORT expInterface
|
EXPORT expInterface
|
||||||
)
|
)
|
||||||
|
install(TARGETS headergen
|
||||||
|
EXPORT expInterface
|
||||||
|
PUBLIC_HEADER DESTINATION include/headergen
|
||||||
|
INCLUDES DESTINATION include/headergen
|
||||||
|
)
|
||||||
install(TARGETS sharedlib
|
install(TARGETS sharedlib
|
||||||
EXPORT expInterface
|
EXPORT expInterface
|
||||||
RUNTIME DESTINATION bin
|
RUNTIME DESTINATION bin
|
||||||
@ -63,7 +83,7 @@ install(TARGETS sharedlib
|
|||||||
BUNDLE DESTINATION Applications
|
BUNDLE DESTINATION Applications
|
||||||
)
|
)
|
||||||
install(FILES
|
install(FILES
|
||||||
headeronly/headeronly.h
|
${headeronly_headers}
|
||||||
DESTINATION include/headeronly
|
DESTINATION include/headeronly
|
||||||
)
|
)
|
||||||
install(FILES
|
install(FILES
|
||||||
|
1
Tests/ExportImport/Export/Interface/headergen.h.in
Normal file
1
Tests/ExportImport/Export/Interface/headergen.h.in
Normal file
@ -0,0 +1 @@
|
|||||||
|
#define HEADERGEN_H
|
@ -12,6 +12,9 @@ set_property(TARGET define_iface PROPERTY
|
|||||||
add_executable(headeronlytest_bld headeronlytest.cpp)
|
add_executable(headeronlytest_bld headeronlytest.cpp)
|
||||||
target_link_libraries(headeronlytest_bld bld::headeronly)
|
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)
|
set_property(TARGET bld::sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
|
||||||
|
|
||||||
add_executable(interfacetest_bld interfacetest.cpp)
|
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)
|
add_executable(headeronlytest_exp headeronlytest.cpp)
|
||||||
target_link_libraries(headeronlytest_exp exp::headeronly)
|
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)
|
set_property(TARGET exp::sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
|
||||||
|
|
||||||
add_executable(interfacetest_exp interfacetest.cpp)
|
add_executable(interfacetest_exp interfacetest.cpp)
|
||||||
|
11
Tests/ExportImport/Import/Interface/headergentest.cpp
Normal file
11
Tests/ExportImport/Import/Interface/headergentest.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
#include "headergen.h"
|
||||||
|
|
||||||
|
#ifndef HEADERGEN_H
|
||||||
|
# error Expected HEADERGEN_H
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
@ -44,6 +44,7 @@ add_executable(InterfaceLibrary definetestexe.cpp)
|
|||||||
target_link_libraries(InterfaceLibrary
|
target_link_libraries(InterfaceLibrary
|
||||||
iface_nodepends
|
iface_nodepends
|
||||||
headeriface
|
headeriface
|
||||||
|
iface_genheader
|
||||||
subiface
|
subiface
|
||||||
intermediate
|
intermediate
|
||||||
|
|
||||||
|
@ -15,6 +15,12 @@
|
|||||||
# error Expected IFACE_HEADER_BUILDDIR
|
# error Expected IFACE_HEADER_BUILDDIR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "iface_genheader.h"
|
||||||
|
|
||||||
|
#ifndef IFACE_GENHEADER
|
||||||
|
# error Expected IFACE_GENHEADER
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int obj();
|
extern int obj();
|
||||||
extern int sub();
|
extern int sub();
|
||||||
extern int item();
|
extern int item();
|
||||||
|
@ -11,3 +11,12 @@ add_custom_target(headeriface_gen
|
|||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
add_dependencies(headeriface headeriface_gen)
|
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)
|
||||||
|
1
Tests/InterfaceLibrary/headerdir/iface_genheader.h.in
Normal file
1
Tests/InterfaceLibrary/headerdir/iface_genheader.h.in
Normal file
@ -0,0 +1 @@
|
|||||||
|
#define IFACE_GENHEADER
|
2
Tests/RunCMake/InterfaceLibrary/ConfigSources.cmake
Normal file
2
Tests/RunCMake/InterfaceLibrary/ConfigSources.cmake
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Test an interface library added to the build system by a per-config source.
|
||||||
|
add_library(iface INTERFACE $<$<CONFIG:NotAConfig>:${CMAKE_CURRENT_SOURCE_DIR}/iface.c>)
|
@ -0,0 +1 @@
|
|||||||
|
[^0]
|
@ -0,0 +1 @@
|
|||||||
|
iface2|Invalid project
|
8
Tests/RunCMake/InterfaceLibrary/EmptySources.cmake
Normal file
8
Tests/RunCMake/InterfaceLibrary/EmptySources.cmake
Normal file
@ -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)
|
@ -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()
|
@ -0,0 +1,4 @@
|
|||||||
|
if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/iface.txt")
|
||||||
|
set(RunCMake_TEST_FAILED "iface target not built")
|
||||||
|
return()
|
||||||
|
endif()
|
@ -0,0 +1 @@
|
|||||||
|
[^0]
|
@ -0,0 +1 @@
|
|||||||
|
iface2|Invalid project
|
7
Tests/RunCMake/InterfaceLibrary/ExcludeFromAll.cmake
Normal file
7
Tests/RunCMake/InterfaceLibrary/ExcludeFromAll.cmake
Normal file
@ -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)
|
@ -0,0 +1 @@
|
|||||||
|
[^0]
|
@ -0,0 +1 @@
|
|||||||
|
iface2|Invalid project
|
20
Tests/RunCMake/InterfaceLibrary/PublicSources.cmake
Normal file
20
Tests/RunCMake/InterfaceLibrary/PublicSources.cmake
Normal file
@ -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)
|
@ -10,3 +10,27 @@ run_cmake(add_custom_command-TARGET)
|
|||||||
run_cmake(IMPORTED_LIBNAME-bad-value)
|
run_cmake(IMPORTED_LIBNAME-bad-value)
|
||||||
run_cmake(IMPORTED_LIBNAME-non-iface)
|
run_cmake(IMPORTED_LIBNAME-non-iface)
|
||||||
run_cmake(IMPORTED_LIBNAME-non-imported)
|
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")
|
||||||
|
4
Tests/RunCMake/InterfaceLibrary/iface.c
Normal file
4
Tests/RunCMake/InterfaceLibrary/iface.c
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
int iface(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
1
Tests/RunCMake/InterfaceLibrary/iface_broken.c
Normal file
1
Tests/RunCMake/InterfaceLibrary/iface_broken.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
#error This file should not compile
|
@ -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\):
|
CMake Error at invalid_signature.cmake:3 \(add_library\):
|
||||||
add_library INTERFACE library specified with conflicting/multiple types.
|
add_library INTERFACE library specified with conflicting/multiple types.
|
||||||
Call Stack \(most recent call first\):
|
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\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists.txt:3 \(include\)
|
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\):
|
CMake Error at invalid_signature.cmake:20 \(add_library\):
|
||||||
add_library GLOBAL option may only be used with IMPORTED libraries.
|
add_library GLOBAL option may only be used with IMPORTED libraries.
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
add_library(iface1 INTERFACE empty.cpp)
|
|
||||||
add_library(iface3 STATIC INTERFACE)
|
add_library(iface3 STATIC INTERFACE)
|
||||||
add_library(iface4 STATIC INTERFACE empty.cpp)
|
add_library(iface4 STATIC INTERFACE empty.cpp)
|
||||||
add_library(iface5 SHARED INTERFACE)
|
add_library(iface5 SHARED INTERFACE)
|
||||||
@ -14,7 +14,7 @@ add_library(iface13 INTERFACE UNKNOWN)
|
|||||||
add_library(iface14 INTERFACE ALIAS)
|
add_library(iface14 INTERFACE ALIAS)
|
||||||
add_library(iface15 ALIAS INTERFACE)
|
add_library(iface15 ALIAS INTERFACE)
|
||||||
add_library(iface16 INTERFACE 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(iface19 GLOBAL INTERFACE) Tested separately
|
||||||
add_library(iface20 INTERFACE GLOBAL)
|
add_library(iface20 INTERFACE GLOBAL)
|
||||||
|
6
Tests/RunCMake/InterfaceLibrary/use_iface.c
Normal file
6
Tests/RunCMake/InterfaceLibrary/use_iface.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
extern int iface(void);
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return iface();
|
||||||
|
}
|
25
Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
Normal file
25
Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
Normal file
@ -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()
|
1
Tests/RunCMake/VS10Project/InterfaceLibSources.cmake
Normal file
1
Tests/RunCMake/VS10Project/InterfaceLibSources.cmake
Normal file
@ -0,0 +1 @@
|
|||||||
|
add_library(iface INTERFACE iface.h)
|
@ -6,6 +6,7 @@ cmake_policy(SET CMP0054 NEW)
|
|||||||
run_cmake(VsCsharpSourceGroup)
|
run_cmake(VsCsharpSourceGroup)
|
||||||
run_cmake(VsCSharpCompilerOpts)
|
run_cmake(VsCSharpCompilerOpts)
|
||||||
run_cmake(ExplicitCMakeLists)
|
run_cmake(ExplicitCMakeLists)
|
||||||
|
run_cmake(InterfaceLibSources)
|
||||||
run_cmake(RuntimeLibrary)
|
run_cmake(RuntimeLibrary)
|
||||||
run_cmake(SourceGroupCMakeLists)
|
run_cmake(SourceGroupCMakeLists)
|
||||||
run_cmake(SourceGroupTreeCMakeLists)
|
run_cmake(SourceGroupTreeCMakeLists)
|
||||||
|
0
Tests/RunCMake/VS10Project/iface.h
Normal file
0
Tests/RunCMake/VS10Project/iface.h
Normal file
16
Tests/RunCMake/XcodeProject/InterfaceLibSources-check.cmake
Normal file
16
Tests/RunCMake/XcodeProject/InterfaceLibSources-check.cmake
Normal file
@ -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()
|
1
Tests/RunCMake/XcodeProject/InterfaceLibSources.cmake
Normal file
1
Tests/RunCMake/XcodeProject/InterfaceLibSources.cmake
Normal file
@ -0,0 +1 @@
|
|||||||
|
add_library(iface INTERFACE iface.h)
|
@ -2,6 +2,7 @@ include(RunCMake)
|
|||||||
|
|
||||||
run_cmake(ExplicitCMakeLists)
|
run_cmake(ExplicitCMakeLists)
|
||||||
run_cmake(ImplicitCMakeLists)
|
run_cmake(ImplicitCMakeLists)
|
||||||
|
run_cmake(InterfaceLibSources)
|
||||||
|
|
||||||
run_cmake(XcodeFileType)
|
run_cmake(XcodeFileType)
|
||||||
run_cmake(XcodeAttributeLocation)
|
run_cmake(XcodeAttributeLocation)
|
||||||
|
0
Tests/RunCMake/XcodeProject/iface.h
Normal file
0
Tests/RunCMake/XcodeProject/iface.h
Normal file
Loading…
Reference in New Issue
Block a user