mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-07 22:59:56 -05:00
install,export: Maybe transform OBJECT libraries to INTERFACE libraries
Teach the `install` and `export` commands to support installing and exporting `OBJECT` libraries without their object files. Transform them to `INTERFACE` libraries in such cases. For `install(TARGETS)`, activate this when no destination for the object files is specified. For `export`, activate this only under Xcode with multiple architectures when we have no well-defined object file locations to give to clients.
This commit is contained in:
@@ -40,7 +40,8 @@ void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
|
||||
}
|
||||
|
||||
void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
|
||||
std::ostream& os, const cmGeneratorTarget* target)
|
||||
std::ostream& os, cmGeneratorTarget const* target,
|
||||
cmStateEnums::TargetType /*targetType*/)
|
||||
{
|
||||
std::string targetName = this->Namespace;
|
||||
targetName += target->GetExportName();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
class cmGeneratorTarget;
|
||||
|
||||
@@ -47,8 +48,9 @@ protected:
|
||||
void GenerateImportHeaderCode(std::ostream& os,
|
||||
const std::string& config = "") override;
|
||||
void GenerateImportFooterCode(std::ostream& os) override;
|
||||
void GenerateImportTargetCode(std::ostream& os,
|
||||
const cmGeneratorTarget* target) override;
|
||||
void GenerateImportTargetCode(
|
||||
std::ostream& os, cmGeneratorTarget const* target,
|
||||
cmStateEnums::TargetType /*targetType*/) override;
|
||||
void GenerateExpectedTargetsCode(
|
||||
std::ostream& os, const std::string& expectedTargets) override;
|
||||
void GenerateImportPropertyCode(
|
||||
|
||||
@@ -59,7 +59,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
this->LG->GetMakefile()->GetBacktrace());
|
||||
return false;
|
||||
}
|
||||
if (te->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
this->GenerateRequiredCMakeVersion(os, "3.0.0");
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
|
||||
// Create all the imported targets.
|
||||
for (cmGeneratorTarget* gte : this->Exports) {
|
||||
this->GenerateImportTargetCode(os, gte);
|
||||
this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte));
|
||||
|
||||
gte->Target->AppendBuildInterfaceIncludes();
|
||||
|
||||
@@ -128,12 +128,13 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
|
||||
// Collect import properties for this target.
|
||||
ImportPropertyMap properties;
|
||||
|
||||
if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
|
||||
if (this->GetExportTargetType(target) != cmStateEnums::INTERFACE_LIBRARY) {
|
||||
this->SetImportLocationProperty(config, suffix, target, properties);
|
||||
}
|
||||
if (!properties.empty()) {
|
||||
// Get the rest of the target details.
|
||||
if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
|
||||
if (this->GetExportTargetType(target) !=
|
||||
cmStateEnums::INTERFACE_LIBRARY) {
|
||||
this->SetImportDetailProperties(config, suffix, target, properties,
|
||||
missingTargets);
|
||||
this->SetImportLinkInterface(config, suffix,
|
||||
@@ -153,6 +154,19 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
|
||||
}
|
||||
}
|
||||
|
||||
cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
cmStateEnums::TargetType targetType = target->GetType();
|
||||
// An object library exports as an interface library if we cannot
|
||||
// tell clients where to find the objects.
|
||||
if (targetType == cmStateEnums::OBJECT_LIBRARY &&
|
||||
!this->LG->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) {
|
||||
targetType = cmStateEnums::INTERFACE_LIBRARY;
|
||||
}
|
||||
return targetType;
|
||||
}
|
||||
|
||||
void cmExportBuildFileGenerator::SetExportSet(cmExportSet* exportSet)
|
||||
{
|
||||
this->ExportSet = exportSet;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
@@ -53,6 +54,8 @@ protected:
|
||||
void GenerateImportTargetsConfig(
|
||||
std::ostream& os, const std::string& config, std::string const& suffix,
|
||||
std::vector<std::string>& missingTargets) override;
|
||||
cmStateEnums::TargetType GetExportTargetType(
|
||||
cmGeneratorTarget const* target) const;
|
||||
void HandleMissingTarget(std::string& link_libs,
|
||||
std::vector<std::string>& missingTargets,
|
||||
cmGeneratorTarget* depender,
|
||||
|
||||
@@ -146,17 +146,6 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
|
||||
}
|
||||
|
||||
if (cmTarget* target = gg->FindTarget(currentTarget)) {
|
||||
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
|
||||
std::string reason;
|
||||
if (!this->Makefile->GetGlobalGenerator()
|
||||
->HasKnownObjectFileLocation(&reason)) {
|
||||
std::ostringstream e;
|
||||
e << "given OBJECT library \"" << currentTarget
|
||||
<< "\" which may not be exported" << reason << ".";
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (target->GetType() == cmStateEnums::UTILITY) {
|
||||
this->SetError("given custom target \"" + currentTarget +
|
||||
"\" which may not be exported.");
|
||||
|
||||
@@ -901,8 +901,10 @@ void cmExportFileGenerator::GenerateExpectedTargetsCode(
|
||||
"\n\n";
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
void cmExportFileGenerator::GenerateImportTargetCode(
|
||||
std::ostream& os, const cmGeneratorTarget* target)
|
||||
std::ostream& os, cmGeneratorTarget const* target,
|
||||
cmStateEnums::TargetType targetType)
|
||||
{
|
||||
// Construct the imported target name.
|
||||
std::string targetName = this->Namespace;
|
||||
@@ -911,7 +913,7 @@ void cmExportFileGenerator::GenerateImportTargetCode(
|
||||
|
||||
// Create the imported target.
|
||||
os << "# Create imported target " << targetName << "\n";
|
||||
switch (target->GetType()) {
|
||||
switch (targetType) {
|
||||
case cmStateEnums::EXECUTABLE:
|
||||
os << "add_executable(" << targetName << " IMPORTED)\n";
|
||||
break;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmVersion.h"
|
||||
#include "cmVersionConfig.h"
|
||||
|
||||
@@ -76,7 +77,8 @@ protected:
|
||||
virtual void GenerateImportFooterCode(std::ostream& os);
|
||||
void GenerateImportVersionCode(std::ostream& os);
|
||||
virtual void GenerateImportTargetCode(std::ostream& os,
|
||||
cmGeneratorTarget const* target);
|
||||
cmGeneratorTarget const* target,
|
||||
cmStateEnums::TargetType targetType);
|
||||
virtual void GenerateImportPropertyCode(std::ostream& os,
|
||||
const std::string& config,
|
||||
cmGeneratorTarget const* target,
|
||||
|
||||
@@ -55,7 +55,8 @@ void cmExportInstallAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
|
||||
}
|
||||
|
||||
void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
|
||||
std::ostream& os, const cmGeneratorTarget* target)
|
||||
std::ostream& os, cmGeneratorTarget const* target,
|
||||
cmStateEnums::TargetType /*targetType*/)
|
||||
{
|
||||
std::string targetName = this->Namespace;
|
||||
targetName += target->GetExportName();
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
class cmGeneratorTarget;
|
||||
class cmInstallExportGenerator;
|
||||
@@ -41,8 +42,9 @@ protected:
|
||||
void GenerateImportHeaderCode(std::ostream& os,
|
||||
const std::string& config = "") override;
|
||||
void GenerateImportFooterCode(std::ostream& os) override;
|
||||
void GenerateImportTargetCode(std::ostream& os,
|
||||
const cmGeneratorTarget* target) override;
|
||||
void GenerateImportTargetCode(
|
||||
std::ostream& os, cmGeneratorTarget const* target,
|
||||
cmStateEnums::TargetType /*targetType*/) override;
|
||||
void GenerateExpectedTargetsCode(
|
||||
std::ostream& os, const std::string& expectedTargets) override;
|
||||
void GenerateImportPropertyCode(
|
||||
|
||||
@@ -75,11 +75,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
// Create all the imported targets.
|
||||
for (cmTargetExport* te : allTargets) {
|
||||
cmGeneratorTarget* gt = te->Target;
|
||||
cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
|
||||
|
||||
requiresConfigFiles =
|
||||
requiresConfigFiles || gt->GetType() != cmStateEnums::INTERFACE_LIBRARY;
|
||||
requiresConfigFiles || targetType != cmStateEnums::INTERFACE_LIBRARY;
|
||||
|
||||
this->GenerateImportTargetCode(os, gt);
|
||||
this->GenerateImportTargetCode(os, gt, targetType);
|
||||
|
||||
ImportPropertyMap properties;
|
||||
|
||||
@@ -114,7 +115,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
require2_8_12 = true;
|
||||
}
|
||||
}
|
||||
if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
if (targetType == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
require3_0_0 = true;
|
||||
}
|
||||
if (gt->GetProperty("INTERFACE_SOURCES")) {
|
||||
@@ -308,7 +309,7 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
|
||||
// Add each target in the set to the export.
|
||||
for (cmTargetExport* te : *this->IEGen->GetExportSet()->GetTargetExports()) {
|
||||
// Collect import properties for this target.
|
||||
if (te->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -426,6 +427,19 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
|
||||
}
|
||||
}
|
||||
|
||||
cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
|
||||
cmTargetExport const* targetExport) const
|
||||
{
|
||||
cmStateEnums::TargetType targetType = targetExport->Target->GetType();
|
||||
// An OBJECT library installed with no OBJECTS DESTINATION
|
||||
// is transformed to an INTERFACE library.
|
||||
if (targetType == cmStateEnums::OBJECT_LIBRARY &&
|
||||
targetExport->ObjectsGenerator == nullptr) {
|
||||
targetType = cmStateEnums::INTERFACE_LIBRARY;
|
||||
}
|
||||
return targetType;
|
||||
}
|
||||
|
||||
void cmExportInstallFileGenerator::HandleMissingTarget(
|
||||
std::string& link_libs, std::vector<std::string>& missingTargets,
|
||||
cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
@@ -17,6 +18,7 @@ class cmGeneratorTarget;
|
||||
class cmGlobalGenerator;
|
||||
class cmInstallExportGenerator;
|
||||
class cmInstallTargetGenerator;
|
||||
class cmTargetExport;
|
||||
|
||||
/** \class cmExportInstallFileGenerator
|
||||
* \brief Generate a file exporting targets from an install tree.
|
||||
@@ -57,6 +59,8 @@ protected:
|
||||
void GenerateImportTargetsConfig(
|
||||
std::ostream& os, const std::string& config, std::string const& suffix,
|
||||
std::vector<std::string>& missingTargets) override;
|
||||
cmStateEnums::TargetType GetExportTargetType(
|
||||
cmTargetExport const* targetExport) const;
|
||||
void HandleMissingTarget(std::string& link_libs,
|
||||
std::vector<std::string>& missingTargets,
|
||||
cmGeneratorTarget* depender,
|
||||
|
||||
@@ -32,7 +32,7 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
this->Exports.pop_back();
|
||||
if (emitted.insert(te).second) {
|
||||
emittedDeps.insert(te);
|
||||
this->GenerateImportTargetCode(os, te);
|
||||
this->GenerateImportTargetCode(os, te, te->GetType());
|
||||
|
||||
ImportPropertyMap properties;
|
||||
|
||||
|
||||
+14
-17
@@ -360,17 +360,6 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
|
||||
std::string reason;
|
||||
if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
|
||||
&reason)) {
|
||||
std::ostringstream e;
|
||||
e << "TARGETS given OBJECT library \"" << tgt
|
||||
<< "\" which may not be installed" << reason << ".";
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Store the target in the list to be installed.
|
||||
targets.push_back(target);
|
||||
} else {
|
||||
@@ -534,15 +523,23 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
|
||||
case cmStateEnums::OBJECT_LIBRARY: {
|
||||
// Objects use OBJECT properties.
|
||||
if (!objectArgs.GetDestination().empty()) {
|
||||
// Verify that we know where the objects are to install them.
|
||||
std::string reason;
|
||||
if (!this->Makefile->GetGlobalGenerator()
|
||||
->HasKnownObjectFileLocation(&reason)) {
|
||||
std::ostringstream e;
|
||||
e << "TARGETS given OBJECT library \"" << target.GetName()
|
||||
<< "\" whose objects may not be installed" << reason << ".";
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
objectGenerator =
|
||||
CreateInstallTargetGenerator(target, objectArgs, false);
|
||||
} else {
|
||||
std::ostringstream e;
|
||||
e << "TARGETS given no OBJECTS DESTINATION for object library "
|
||||
"target \""
|
||||
<< target.GetName() << "\".";
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
// Installing an OBJECT library without a destination transforms
|
||||
// it to an INTERFACE library. It installs no files but can be
|
||||
// exported.
|
||||
}
|
||||
} break;
|
||||
case cmStateEnums::EXECUTABLE: {
|
||||
|
||||
Reference in New Issue
Block a user