objlib: Allow other libraries to link to OBJECT libraries.

Note: This only allows `OBJECT` libraries to be on the right-hand side
of `target_link_libraries` but still does not link its object-files to
the target on the left-hand side.

Issue: #14778
This commit is contained in:
Deniz Bahadir authored and Brad King committed 2018-03-01 09:24:24 -05:00
1 parent 51249e69ea
commit dfb6e84082
20 files changed
+94 -66

No files matched your search

+3
View File
@@ -611,6 +611,9 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
if (!libName.empty()) {
this->AddItem(libName, nullptr);
}
} else if (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
// Ignore object library!
// Its object-files should already have been extracted for linking.
} else {
// Decide whether to use an import library.
bool implib =
+3 -3
View File
@@ -211,11 +211,11 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
if (depender->GetType() != cmStateEnums::EXECUTABLE &&
depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
depender->GetType() != cmStateEnums::MODULE_LIBRARY) {
depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
cmake::FATAL_ERROR,
"Only executables and non-OBJECT libraries may "
"reference target objects.",
"Only executables and libraries may reference target objects.",
depender->GetBacktrace());
return;
}
+3 -1
View File
@@ -159,7 +159,9 @@ cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType(
{
cmStateEnums::TargetType targetType = target->GetType();
// An object library exports as an interface library if we cannot
// tell clients where to find the objects.
// tell clients where to find the objects. This is sufficient
// to support transitive usage requirements on other targets that
// use the object library.
if (targetType == cmStateEnums::OBJECT_LIBRARY &&
!this->LG->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) {
targetType = cmStateEnums::INTERFACE_LIBRARY;
+7 -16
View File
@@ -240,13 +240,16 @@ const char* cmGeneratorTarget::GetOutputTargetType(
case cmStateEnums::MODULE_LIBRARY:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
// Module import libraries are treated as archive targets.
// Module libraries are always treated as library targets.
return "LIBRARY";
case cmStateEnums::ImportLibraryArtifact:
// Module libraries are always treated as library targets.
// Module import libraries are treated as archive targets.
return "ARCHIVE";
}
break;
case cmStateEnums::OBJECT_LIBRARY:
// Object libraries are always treated as object targets.
return "OBJECT";
case cmStateEnums::EXECUTABLE:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
@@ -1671,6 +1674,7 @@ bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const
return this->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::EXECUTABLE;
}
@@ -5323,20 +5327,6 @@ cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink(
tgt = nullptr;
}
if (tgt && tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "Target \"" << this->GetName() << "\" links to "
"OBJECT library \""
<< tgt->GetName()
<< "\" but this is not "
"allowed. "
"One may link only to STATIC or SHARED libraries, or to executables "
"with the ENABLE_EXPORTS property set.";
cmake* cm = this->LocalGenerator->GetCMakeInstance();
cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
tgt = nullptr;
}
return tgt;
}
@@ -5400,6 +5390,7 @@ bool cmGeneratorTarget::IsLinkable() const
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
this->GetType() == cmStateEnums::UNKNOWN_LIBRARY ||
this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
this->IsExecutableWithExports());
}
+8 -10
View File
@@ -114,15 +114,12 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>(
}
if (!noMessage) {
e << "Target \"" << tgt->GetName()
<< "\" contains "
"$<TARGET_OBJECTS> generator expression in its sources "
"list. "
"This content was not previously part of the SOURCES "
"property "
"when that property was read at configure time. Code "
"reading "
"that property needs to be adapted to ignore the generator "
"expression using the string(GENEX_STRIP) command.";
<< "\" contains $<TARGET_OBJECTS> generator expression in its "
"sources list. This content was not previously part of the "
"SOURCES property when that property was read at configure "
"time. Code reading that property needs to be adapted to "
"ignore the generator expression using the string(GENEX_STRIP) "
"command.";
messenger->IssueMessage(messageType, e.str(), context);
}
if (addContent) {
@@ -742,7 +739,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
}
if (cmGeneratorExpression::Find(lib) != std::string::npos ||
(tgt && tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
(tgt && (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
(this->Name == lib)) {
return;
}
+3 -2
View File
@@ -391,14 +391,15 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) &&
(tgt->GetType() != cmStateEnums::SHARED_LIBRARY) &&
(tgt->GetType() != cmStateEnums::UNKNOWN_LIBRARY) &&
(tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
(tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
!tgt->IsExecutableWithExports()) {
std::ostringstream e;
e << "Target \"" << lib << "\" of type "
<< cmState::GetTargetTypeName(tgt->GetType())
<< " may not be linked into another target. One may link only to "
"INTERFACE, STATIC or SHARED libraries, or to executables with the "
"ENABLE_EXPORTS property set.";
"INTERFACE, OBJECT, STATIC or SHARED libraries, or to executables "
"with the ENABLE_EXPORTS property set.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
@@ -1 +0,0 @@
1
@@ -1,6 +0,0 @@
CMake Error at LinkObjRHS1.cmake:3 \(target_link_libraries\):
Target "AnObjLib" of type OBJECT_LIBRARY may not be linked into another
target. One may link only to INTERFACE, STATIC or SHARED libraries, or to
executables with the ENABLE_EXPORTS property set.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
@@ -1,3 +0,0 @@
add_library(A STATIC a.c)
add_library(AnObjLib OBJECT a.c)
target_link_libraries(A AnObjLib)
@@ -1 +0,0 @@
1
@@ -1,6 +0,0 @@
CMake Error at LinkObjRHS2.cmake:1 \(add_library\):
Target "A" links to OBJECT library "AnObjLib" but this is not allowed. One
may link only to STATIC or SHARED libraries, or to executables with the
ENABLE_EXPORTS property set.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
@@ -1,3 +0,0 @@
add_library(A SHARED a.c)
target_link_libraries(A AnObjLib)
add_library(AnObjLib OBJECT a.c)
@@ -0,0 +1,13 @@
enable_language(C)
add_definitions(-DCOMPILE_FOR_SHARED_LIB)
add_library(AnObjLib OBJECT a.c)
target_compile_definitions(AnObjLib INTERFACE REQUIRED)
set_target_properties(AnObjLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_library(A SHARED b.c $<TARGET_OBJECTS:AnObjLib>)
target_link_libraries(A PUBLIC AnObjLib)
add_executable(exe exe.c)
target_link_libraries(exe A)
@@ -0,0 +1,10 @@
enable_language(C)
add_library(AnObjLib OBJECT a.c)
target_compile_definitions(AnObjLib INTERFACE REQUIRED)
add_library(A STATIC b.c $<TARGET_OBJECTS:AnObjLib>)
target_link_libraries(A PUBLIC AnObjLib)
add_executable(exe exe.c)
target_link_libraries(exe A)
@@ -1,4 +1,10 @@
CMake Error at ObjWithObj.cmake:2 \(add_library\):
Only executables and non-OBJECT libraries may reference target objects.
^CMake Error at ObjWithObj.cmake:[0-9]+ \(add_library\):
OBJECT library \"B\" contains:
[^
]*a(\.c)?\.o(bj)?
but may contain only sources that compile, header files, and other files
that would not affect linking of a normal library.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMakeLists.txt:[0-9]+ \(include\)$
@@ -26,9 +26,9 @@ endfunction ()
run_object_lib_build(LinkObjLHSShared)
run_object_lib_build(LinkObjLHSStatic)
run_object_lib_build(LinkObjRHSShared)
run_object_lib_build(LinkObjRHSStatic)
run_cmake(LinkObjRHS1)
run_cmake(LinkObjRHS2)
run_cmake(MissingSource)
run_cmake(ObjWithObj)
run_cmake(OwnSources)
+7 -1
View File
@@ -1,4 +1,10 @@
int a(void)
#if defined(_WIN32) && defined(COMPILE_FOR_SHARED_LIB)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
EXPORT int a(void)
{
return 0;
}
+12 -2
View File
@@ -1,4 +1,14 @@
int b(void)
#if defined(_WIN32) && defined(COMPILE_FOR_SHARED_LIB)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
extern int a(void);
EXPORT int b()
{
return 0;
return a();
}
#ifndef REQUIRED
#error "REQUIRED needs to be defined"
#endif
+14
View File
@@ -0,0 +1,14 @@
#if defined(_WIN32) && defined(COMPILE_FOR_SHARED_LIB)
#define IMPORT __declspec(dllimport)
#else
#define IMPORT
#endif
extern IMPORT int b(void);
int main()
{
return b();
}
#ifndef REQUIRED
#error "REQUIRED needs to be defined"
#endif
@@ -6,11 +6,5 @@
but may contain only sources that compile, header files, and other files
that would not affect linking of a normal library.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
CMake Error at OBJECTwithOnlyObjectSources.cmake:[0-9]+ \(add_library\):
Only executables and non-OBJECT libraries may reference target objects.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$