Merge topic 'objlib-extend'

eec93bce Allow OBJECT libraries to be installed, exported, and imported
93c89bc7 Genex: Allow TARGET_OBJECTS to be used everywhere
ac0cf7ff Genex: Reject TARGET_OBJECTS on non-object libraries earlier
8577978c Tests: ExportImport C code should use explicit (void) in prototypes
26cfd039 cmInstallTargetGenerator: Re-order GenerateScriptForConfig logic
25f3f22a cmGlobalGenerator: Add method to check if object file location is known
d596c550 cmGeneratorTarget: Add method to get the object file directory
930042f2 cmGeneratorTarget: Factor out a GetTargetObjectNames method
...

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !712
This commit is contained in:
Brad King
2017-04-19 14:47:28 +00:00
committed by Kitware Robot
65 changed files with 612 additions and 190 deletions
+4 -5
View File
@@ -64,7 +64,7 @@ Imported Libraries
::
add_library(<name> <SHARED|STATIC|MODULE|UNKNOWN> IMPORTED
add_library(<name> <SHARED|STATIC|MODULE|OBJECT|UNKNOWN> IMPORTED
[GLOBAL])
An :ref:`IMPORTED library target <Imported Targets>` references a library
@@ -106,10 +106,9 @@ may contain only sources that compile, header files, and other files
that would not affect linking of a normal library (e.g. ``.txt``).
They may contain custom commands generating such sources, but not
``PRE_BUILD``, ``PRE_LINK``, or ``POST_BUILD`` commands. Object libraries
cannot be imported, exported, installed, or linked. Some native build
systems may not like targets that have only object files, so consider
adding at least one real source file to any target that references
``$<TARGET_OBJECTS:objlib>``.
cannot be linked. Some native build systems may not like targets that
have only object files, so consider adding at least one real source file
to any target that references ``$<TARGET_OBJECTS:objlib>``.
Alias Libraries
^^^^^^^^^^^^^^^
+12 -11
View File
@@ -73,7 +73,7 @@ Installing Targets
::
install(TARGETS targets... [EXPORT <export-name>]
[[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|
[[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
@@ -86,10 +86,10 @@ Installing Targets
)
The ``TARGETS`` form specifies rules for installing targets from a
project. There are five kinds of target files that may be installed:
``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``FRAMEWORK``, and ``BUNDLE``.
Executables are treated as ``RUNTIME`` targets, except that those
marked with the ``MACOSX_BUNDLE`` property are treated as ``BUNDLE``
project. There are six kinds of target files that may be installed:
``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``OBJECTS``, ``FRAMEWORK``, and
``BUNDLE``. Executables are treated as ``RUNTIME`` targets, except that
those marked with the ``MACOSX_BUNDLE`` property are treated as ``BUNDLE``
targets on OS X. Static libraries are treated as ``ARCHIVE`` targets,
except that those marked with the ``FRAMEWORK`` property are treated
as ``FRAMEWORK`` targets on OS X.
@@ -99,10 +99,11 @@ targets, except that those marked with the ``FRAMEWORK`` property are
treated as ``FRAMEWORK`` targets on OS X. For DLL platforms the DLL
part of a shared library is treated as a ``RUNTIME`` target and the
corresponding import library is treated as an ``ARCHIVE`` target.
All Windows-based systems including Cygwin are DLL platforms.
The ``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, and ``FRAMEWORK`` arguments
change the type of target to which the subsequent properties apply.
If none is given the installation properties apply to all target
All Windows-based systems including Cygwin are DLL platforms. Object
libraries are always treated as ``OBJECTS`` targets.
The ``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``OBJECTS``, and ``FRAMEWORK``
arguments change the type of target to which the subsequent properties
apply. If none is given the installation properties apply to all target
types. If only one is given then only targets of that type will be
installed (which can be used to install just a DLL or just an import
library).
@@ -165,8 +166,8 @@ the ``mySharedLib`` DLL will be installed to ``<prefix>/bin`` and
The ``EXPORT`` option associates the installed target files with an
export called ``<export-name>``. It must appear before any ``RUNTIME``,
``LIBRARY``, or ``ARCHIVE`` options. To actually install the export
file itself, call ``install(EXPORT)``, documented below.
``LIBRARY``, ``ARCHIVE``, or ``OBJECTS`` options. To actually install the
export file itself, call ``install(EXPORT)``, documented below.
Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property
set to ``TRUE`` has undefined behavior.
+9 -3
View File
@@ -125,10 +125,10 @@ The object files collection can be used as source inputs to other targets:
add_executable(test_exe $<TARGET_OBJECTS:archive> test.cpp)
``OBJECT`` libraries may only be used locally as sources in a buildsystem --
they may not be installed, exported, or used in the right hand side of
``OBJECT`` libraries may not be used in the right hand side of
:command:`target_link_libraries`. They also may not be used as the ``TARGET``
in a use of the :command:`add_custom_command(TARGET)` command signature.
in a use of the :command:`add_custom_command(TARGET)` command signature. They
may be installed, and will be exported as an INTERFACE library.
Although object libraries may not be named directly in calls to
the :command:`target_link_libraries` command, they can be "linked"
@@ -136,6 +136,12 @@ indirectly by using an :ref:`Interface Library <Interface Libraries>`
whose :prop_tgt:`INTERFACE_SOURCES` target property is set to name
``$<TARGET_OBJECTS:objlib>``.
Although object libraries may not be used as the ``TARGET``
in a use of the :command:`add_custom_command(TARGET)` command signature,
the list of objects can be used by :command:`add_custom_command(OUTPUT)` or
:command:`file(GENERATE)` by using ``$<TARGET_OBJECTS:objlib>``.
Build Specification and Usage Requirements
==========================================
@@ -290,9 +290,7 @@ Available output expressions are:
Content of ``...`` converted to a C identifier.
``$<TARGET_OBJECTS:objLib>``
List of objects resulting from build of ``objLib``. ``objLib`` must be an
object of type ``OBJECT_LIBRARY``. This expression may only be used in
the sources of :command:`add_library` and :command:`add_executable`
commands.
object of type ``OBJECT_LIBRARY``.
``$<SHELL_PATH:...>``
Content of ``...`` converted to shell path style. For example, slashes are
converted to backslashes in Windows shells and drive letters are converted
+2
View File
@@ -194,6 +194,8 @@ Properties on Targets
/prop_tgt/IMPORTED_LOCATION
/prop_tgt/IMPORTED_NO_SONAME_CONFIG
/prop_tgt/IMPORTED_NO_SONAME
/prop_tgt/IMPORTED_OBJECTS_CONFIG
/prop_tgt/IMPORTED_OBJECTS
/prop_tgt/IMPORTED
/prop_tgt/IMPORTED_SONAME_CONFIG
/prop_tgt/IMPORTED_SONAME
+11
View File
@@ -0,0 +1,11 @@
IMPORTED_OBJECTS
----------------
:ref:`;-list <CMake Language Lists>` of absolute paths to the object
files on disk for an :ref:`imported <Imported targets>`
:ref:`object library <object libraries>`.
Ignored for non-imported targets.
Projects may skip ``IMPORTED_OBJECTS`` if the configuration-specific
property :prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` is set instead.
@@ -0,0 +1,7 @@
IMPORTED_OBJECTS_<CONFIG>
-------------------------
<CONFIG>-specific version of :prop_tgt:`IMPORTED_OBJECTS` property.
Configuration names correspond to those provided by the project from
which the target is imported.
@@ -0,0 +1,6 @@
add_custom_command-TARGET_OBJECTS
---------------------------------
* The :command:`add_custom_command` command learned to evaluate the
``TARGET_OBJECTS``
:manual:`generator expression <cmake-generator-expressions(7)>`.
@@ -0,0 +1,5 @@
add_library-TARGET_OBJECTS
--------------------------
* The :command:`add_library` command ``IMPORTED`` option learned to support
:ref:`Object Libraries`.
@@ -0,0 +1,6 @@
file-GENERATE-TARGET_OBJECTS
----------------------------
* The :command:`file(GENERATE)` subcommand learned to evaluate the
``TARGET_OBJECTS``
:manual:`generator expression <cmake-generator-expressions(7)>`.
@@ -0,0 +1,8 @@
install-TARGET_OBJECTS
----------------------
* The :command:`install(TARGETS)` command learned a new ``OBJECTS`` option to
specify where to install :ref:`Object Libraries`.
* The :command:`install(EXPORT)` command learned how to export
:ref:`Object Libraries`.
+9 -4
View File
@@ -297,10 +297,15 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
if (type == cmStateEnums::OBJECT_LIBRARY) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
"The OBJECT library type may not be used for IMPORTED libraries.");
return true;
std::string reason;
if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
&reason)) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
"The OBJECT library type may not be used for IMPORTED libraries" +
reason + ".");
return true;
}
}
if (type == cmStateEnums::INTERFACE_LIBRARY) {
if (!cmGeneratorExpression::IsValidTargetName(libName)) {
+43 -19
View File
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportBuildFileGenerator.h"
#include "cmAlgorithms.h"
#include "cmExportSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@@ -21,6 +22,8 @@
#include <sstream>
#include <utility>
class cmSourceFile;
cmExportBuildFileGenerator::cmExportBuildFileGenerator()
{
this->LG = CM_NULLPTR;
@@ -171,27 +174,48 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
// Get the makefile in which to lookup target information.
cmMakefile* mf = target->Makefile;
// Add the main target file.
{
std::string prop = "IMPORTED_LOCATION";
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
std::string prop = "IMPORTED_OBJECTS";
prop += suffix;
std::string value;
if (target->IsAppBundleOnApple()) {
value = target->GetFullPath(config, false);
} else {
value = target->GetFullPath(config, false, true);
}
properties[prop] = value;
}
// Add the import library for windows DLLs.
if (target->HasImportLibrary() &&
mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
std::string prop = "IMPORTED_IMPLIB";
prop += suffix;
std::string value = target->GetFullPath(config, true);
target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
properties[prop] = value;
// Compute all the object files inside this target and setup
// IMPORTED_OBJECTS as a list of object files
std::vector<cmSourceFile const*> objectSources;
target->GetObjectSources(objectSources, config);
std::string const obj_dir = target->GetObjectDirectory(config);
std::vector<std::string> objects;
for (std::vector<cmSourceFile const*>::const_iterator si =
objectSources.begin();
si != objectSources.end(); ++si) {
const std::string& obj = target->GetObjectName(*si);
objects.push_back(obj_dir + obj);
}
// Store the property.
properties[prop] = cmJoin(objects, ";");
} else {
// Add the main target file.
{
std::string prop = "IMPORTED_LOCATION";
prop += suffix;
std::string value;
if (target->IsAppBundleOnApple()) {
value = target->GetFullPath(config, false);
} else {
value = target->GetFullPath(config, false, true);
}
properties[prop] = value;
}
// Add the import library for windows DLLs.
if (target->HasImportLibrary() &&
mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
std::string prop = "IMPORTED_IMPLIB";
prop += suffix;
std::string value = target->GetFullPath(config, true);
target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
properties[prop] = value;
}
}
}
+9 -5
View File
@@ -149,11 +149,15 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
if (cmTarget* target = gg->FindTarget(*currentTarget)) {
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "given OBJECT library \"" << *currentTarget
<< "\" which may not be exported.";
this->SetError(e.str());
return false;
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 +
+8
View File
@@ -441,6 +441,11 @@ void getCompatibleInterfaceProperties(cmGeneratorTarget* target,
std::set<std::string>& ifaceProperties,
const std::string& config)
{
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
// object libraries have no link information, so nothing to compute
return;
}
cmComputeLinkInformation* info = target->GetLinkInformation(config);
if (!info) {
@@ -927,6 +932,9 @@ void cmExportFileGenerator::GenerateImportTargetCode(
case cmStateEnums::UNKNOWN_LIBRARY:
os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
break;
case cmStateEnums::OBJECT_LIBRARY:
os << "add_library(" << targetName << " OBJECT IMPORTED)\n";
break;
case cmStateEnums::INTERFACE_LIBRARY:
os << "add_library(" << targetName << " INTERFACE IMPORTED)\n";
break;
+19
View File
@@ -331,6 +331,8 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
properties, importedLocations);
this->SetImportLocationProperty(config, suffix, te->RuntimeGenerator,
properties, importedLocations);
this->SetImportLocationProperty(config, suffix, te->ObjectsGenerator,
properties, importedLocations);
this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator,
properties, importedLocations);
this->SetImportLocationProperty(config, suffix, te->BundleGenerator,
@@ -397,6 +399,23 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
// Store the property.
properties[prop] = value;
importedLocations.insert(prop);
} else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
// Construct the property name.
std::string prop = "IMPORTED_OBJECTS";
prop += suffix;
// Compute all the object files inside this target and setup
// IMPORTED_OBJECTS as a list of object files
std::vector<std::string> objects;
itgen->GetInstallObjectNames(config, objects);
for (std::vector<std::string>::iterator i = objects.begin();
i != objects.end(); ++i) {
*i = value + *i;
}
// Store the property.
properties[prop] = cmJoin(objects, ";");
importedLocations.insert(prop);
} else {
// Construct the property name.
std::string prop = "IMPORTED_LOCATION";
@@ -64,8 +64,10 @@ void cmGeneratorExpressionEvaluationFile::Generate(
return;
}
std::ostringstream e;
e << "Evaluation file to be written multiple times for different "
"configurations or languages with different content:\n "
e << "Evaluation file to be written multiple times with different "
"content. "
"This is generally caused by the content evaluating the "
"configuration type, language, or location of object files:\n "
<< outputFileName;
lg->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
+49 -39
View File
@@ -33,8 +33,6 @@
#include <string.h>
#include <utility>
class cmSourceFile;
std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
std::string const& prop, cmLocalGenerator* lg,
cmGeneratorExpressionContext* context, cmGeneratorTarget const* headTarget,
@@ -1228,15 +1226,6 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
CM_OVERRIDE
{
if (!context->EvaluateForBuildsystem) {
std::ostringstream e;
e << "The evaluation of the TARGET_OBJECTS generator expression "
"is only suitable for consumption by CMake. It is not suitable "
"for writing out elsewhere.";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
std::string tgtName = parameters.front();
cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
if (!gt) {
@@ -1253,39 +1242,60 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
std::vector<cmSourceFile const*> objectSources;
gt->GetObjectSources(objectSources, context->Config);
std::map<cmSourceFile const*, std::string> mapping;
for (std::vector<cmSourceFile const*>::const_iterator it =
objectSources.begin();
it != objectSources.end(); ++it) {
mapping[*it];
if (!context->EvaluateForBuildsystem) {
cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
std::string reason;
if (!gg->HasKnownObjectFileLocation(&reason)) {
std::ostringstream e;
e << "The evaluation of the TARGET_OBJECTS generator expression "
"is only suitable for consumption by CMake (limited"
<< reason << "). "
"It is not suitable for writing out elsewhere.";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
}
gt->LocalGenerator->ComputeObjectFilenames(mapping, gt);
std::vector<std::string> objects;
if (gt->IsImported()) {
const char* loc = CM_NULLPTR;
const char* imp = CM_NULLPTR;
std::string suffix;
if (gt->Target->GetMappedConfig(context->Config, &loc, &imp, suffix)) {
cmSystemTools::ExpandListArgument(loc, objects);
}
context->HadContextSensitiveCondition = true;
} else {
gt->GetTargetObjectNames(context->Config, objects);
std::string obj_dir;
if (context->EvaluateForBuildsystem) {
// Use object file directory with buildsystem placeholder.
obj_dir = gt->ObjectDirectory;
// Here we assume that the set of object files produced
// by an object library does not vary with configuration
// and do not set HadContextSensitiveCondition to true.
} else {
// Use object file directory with per-config location.
obj_dir = gt->GetObjectDirectory(context->Config);
context->HadContextSensitiveCondition = true;
}
for (std::vector<std::string>::iterator oi = objects.begin();
oi != objects.end(); ++oi) {
*oi = obj_dir + *oi;
}
}
// Create the cmSourceFile instances in the referencing directory.
cmMakefile* mf = context->LG->GetMakefile();
std::string obj_dir = gt->ObjectDirectory;
std::string result;
const char* sep = "";
for (std::vector<cmSourceFile const*>::const_iterator it =
objectSources.begin();
it != objectSources.end(); ++it) {
// Find the object file name corresponding to this source file.
std::map<cmSourceFile const*, std::string>::const_iterator map_it =
mapping.find(*it);
// It must exist because we populated the mapping just above.
assert(!map_it->second.empty());
result += sep;
std::string objFile = obj_dir + map_it->second;
mf->AddTargetObject(tgtName, objFile);
result += objFile;
sep = ";";
for (std::vector<std::string>::iterator oi = objects.begin();
oi != objects.end(); ++oi) {
mf->AddTargetObject(tgtName, *oi);
}
return result;
return cmJoin(objects, ";");
}
} targetObjectsNode;
+40
View File
@@ -3274,6 +3274,46 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
return prefix + base + ".pdb";
}
std::string cmGeneratorTarget::GetObjectDirectory(
std::string const& config) const
{
std::string obj_dir =
this->GlobalGenerator->ExpandCFGIntDir(this->ObjectDirectory, config);
#if defined(__APPLE__)
// find and replace $(PROJECT_NAME) xcode placeholder
const std::string projectName = this->LocalGenerator->GetProjectName();
cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName);
#endif
return obj_dir;
}
void cmGeneratorTarget::GetTargetObjectNames(
std::string const& config, std::vector<std::string>& objects) const
{
std::vector<cmSourceFile const*> objectSources;
this->GetObjectSources(objectSources, config);
std::map<cmSourceFile const*, std::string> mapping;
for (std::vector<cmSourceFile const*>::const_iterator it =
objectSources.begin();
it != objectSources.end(); ++it) {
mapping[*it];
}
this->LocalGenerator->ComputeObjectFilenames(mapping, this);
for (std::vector<cmSourceFile const*>::const_iterator it =
objectSources.begin();
it != objectSources.end(); ++it) {
// Find the object file name corresponding to this source file.
std::map<cmSourceFile const*, std::string>::const_iterator map_it =
mapping.find(*it);
// It must exist because we populated the mapping just above.
assert(!map_it->second.empty());
objects.push_back(map_it->second);
}
}
bool cmGeneratorTarget::StrictTargetComparison::operator()(
cmGeneratorTarget const* t1, cmGeneratorTarget const* t2) const
{
+10 -1
View File
@@ -209,6 +209,11 @@ public:
bool realname) const;
std::string NormalGetRealName(const std::string& config) const;
/** Get the names of an object library's object files underneath
its object file directory. */
void GetTargetObjectNames(std::string const& config,
std::vector<std::string>& objects) const;
/** What hierarchy level should the reported directory contain */
enum BundleDirectoryLevel
{
@@ -364,6 +369,10 @@ public:
time config name placeholder if needed for the generator. */
std::string ObjectDirectory;
/** Full path with trailing slash to the top-level directory
holding object files for the given configuration. */
std::string GetObjectDirectory(std::string const& config) const;
void GetAppleArchs(const std::string& config,
std::vector<std::string>& archVec) const;
@@ -534,7 +543,7 @@ public:
std::string GetPDBDirectory(const std::string& config) const;
///! Return the preferred linker language for this target
std::string GetLinkerLanguage(const std::string& config = "") const;
std::string GetLinkerLanguage(const std::string& config) const;
/** Does this target have a GNU implib to convert to MS format? */
bool HasImplibGNUtoMS() const;
+5
View File
@@ -331,6 +331,11 @@ public:
i.e. "Can I build Debug and Release in the same tree?" */
virtual bool IsMultiConfig() const { return false; }
/** Return true if we know the exact location of object files.
If false, store the reason in the given string.
This is meaningful only after EnableLanguage has been called. */
virtual bool HasKnownObjectFileLocation(std::string*) const { return true; }
virtual bool UseFolderProperty() const;
virtual bool IsIPOSupported() const { return false; }
+12
View File
@@ -3720,6 +3720,18 @@ bool cmGlobalXCodeGenerator::IsMultiConfig() const
return true;
}
bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation(
std::string* reason) const
{
if (this->ObjectDirArch.find('$') != std::string::npos) {
if (reason != CM_NULLPTR) {
*reason = " under Xcode with multiple architectures";
}
return false;
}
return true;
}
bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const
{
const char* epnValue =
+2
View File
@@ -87,6 +87,8 @@ public:
i.e. "Can I build Debug and Release in the same tree?" */
bool IsMultiConfig() const CM_OVERRIDE;
bool HasKnownObjectFileLocation(std::string* reason) const CM_OVERRIDE;
bool UseEffectivePlatformName(cmMakefile* mf) const CM_OVERRIDE;
bool ShouldStripResourcePath(cmMakefile*) const CM_OVERRIDE;
+41 -9
View File
@@ -206,6 +206,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmCAStringVector archiveArgVector(&argHelper, "ARCHIVE", &group);
cmCAStringVector libraryArgVector(&argHelper, "LIBRARY", &group);
cmCAStringVector runtimeArgVector(&argHelper, "RUNTIME", &group);
cmCAStringVector objectArgVector(&argHelper, "OBJECTS", &group);
cmCAStringVector frameworkArgVector(&argHelper, "FRAMEWORK", &group);
cmCAStringVector bundleArgVector(&argHelper, "BUNDLE", &group);
cmCAStringVector includesArgVector(&argHelper, "INCLUDES", &group);
@@ -234,6 +235,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmInstallCommandArguments archiveArgs(this->DefaultComponentName);
cmInstallCommandArguments libraryArgs(this->DefaultComponentName);
cmInstallCommandArguments runtimeArgs(this->DefaultComponentName);
cmInstallCommandArguments objectArgs(this->DefaultComponentName);
cmInstallCommandArguments frameworkArgs(this->DefaultComponentName);
cmInstallCommandArguments bundleArgs(this->DefaultComponentName);
cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName);
@@ -246,6 +248,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
archiveArgs.Parse(&archiveArgVector.GetVector(), &unknownArgs);
libraryArgs.Parse(&libraryArgVector.GetVector(), &unknownArgs);
runtimeArgs.Parse(&runtimeArgVector.GetVector(), &unknownArgs);
objectArgs.Parse(&objectArgVector.GetVector(), &unknownArgs);
frameworkArgs.Parse(&frameworkArgVector.GetVector(), &unknownArgs);
bundleArgs.Parse(&bundleArgVector.GetVector(), &unknownArgs);
privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
@@ -265,6 +268,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
archiveArgs.SetGenericArguments(&genericArgs);
libraryArgs.SetGenericArguments(&genericArgs);
runtimeArgs.SetGenericArguments(&genericArgs);
objectArgs.SetGenericArguments(&genericArgs);
frameworkArgs.SetGenericArguments(&genericArgs);
bundleArgs.SetGenericArguments(&genericArgs);
privateHeaderArgs.SetGenericArguments(&genericArgs);
@@ -274,6 +278,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
success = success && archiveArgs.Finalize();
success = success && libraryArgs.Finalize();
success = success && runtimeArgs.Finalize();
success = success && objectArgs.Finalize();
success = success && frameworkArgs.Finalize();
success = success && bundleArgs.Finalize();
success = success && privateHeaderArgs.Finalize();
@@ -287,8 +292,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Enforce argument rules too complex to specify for the
// general-purpose parser.
if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() ||
frameworkArgs.GetNamelinkOnly() || bundleArgs.GetNamelinkOnly() ||
privateHeaderArgs.GetNamelinkOnly() ||
objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() ||
bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() ||
publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) {
this->SetError(
"TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
@@ -296,8 +301,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
return false;
}
if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() ||
frameworkArgs.GetNamelinkSkip() || bundleArgs.GetNamelinkSkip() ||
privateHeaderArgs.GetNamelinkSkip() ||
objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() ||
bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() ||
publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) {
this->SetError(
"TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
@@ -356,11 +361,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
return false;
}
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "TARGETS given OBJECT library \"" << (*targetIt)
<< "\" which may not be installed.";
this->SetError(e.str());
return false;
std::string reason;
if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
&reason)) {
std::ostringstream e;
e << "TARGETS given OBJECT library \"" << (*targetIt)
<< "\" 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);
@@ -379,6 +388,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
bool installsArchive = false;
bool installsLibrary = false;
bool installsRuntime = false;
bool installsObject = false;
bool installsFramework = false;
bool installsBundle = false;
bool installsPrivateHeader = false;
@@ -393,6 +403,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmInstallTargetGenerator* archiveGenerator = CM_NULLPTR;
cmInstallTargetGenerator* libraryGenerator = CM_NULLPTR;
cmInstallTargetGenerator* runtimeGenerator = CM_NULLPTR;
cmInstallTargetGenerator* objectGenerator = CM_NULLPTR;
cmInstallTargetGenerator* frameworkGenerator = CM_NULLPTR;
cmInstallTargetGenerator* bundleGenerator = CM_NULLPTR;
cmInstallFilesGenerator* privateHeaderGenerator = CM_NULLPTR;
@@ -522,6 +533,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
return false;
}
} break;
case cmStateEnums::OBJECT_LIBRARY: {
// Objects use OBJECT properties.
if (!objectArgs.GetDestination().empty()) {
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;
}
} break;
case cmStateEnums::EXECUTABLE: {
if (target.IsAppBundleOnApple()) {
// Application bundles use the BUNDLE properties.
@@ -664,6 +689,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
installsArchive = installsArchive || archiveGenerator != CM_NULLPTR;
installsLibrary = installsLibrary || libraryGenerator != CM_NULLPTR;
installsRuntime = installsRuntime || runtimeGenerator != CM_NULLPTR;
installsObject = installsObject || objectGenerator != CM_NULLPTR;
installsFramework = installsFramework || frameworkGenerator != CM_NULLPTR;
installsBundle = installsBundle || bundleGenerator != CM_NULLPTR;
installsPrivateHeader =
@@ -675,6 +701,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->Makefile->AddInstallGenerator(archiveGenerator);
this->Makefile->AddInstallGenerator(libraryGenerator);
this->Makefile->AddInstallGenerator(runtimeGenerator);
this->Makefile->AddInstallGenerator(objectGenerator);
this->Makefile->AddInstallGenerator(frameworkGenerator);
this->Makefile->AddInstallGenerator(bundleGenerator);
this->Makefile->AddInstallGenerator(privateHeaderGenerator);
@@ -692,6 +719,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
te->HeaderGenerator = publicHeaderGenerator;
te->LibraryGenerator = libraryGenerator;
te->RuntimeGenerator = runtimeGenerator;
te->ObjectsGenerator = objectGenerator;
this->Makefile->GetGlobalGenerator()
->GetExportSets()[exports.GetString()]
->AddTargetExport(te);
@@ -715,6 +743,10 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
runtimeArgs.GetComponent().c_str());
}
if (installsObject) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
objectArgs.GetComponent().c_str());
}
if (installsFramework) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
frameworkArgs.GetComponent().c_str());
+69 -19
View File
@@ -60,25 +60,6 @@ void cmInstallTargetGenerator::GenerateScript(std::ostream& os)
void cmInstallTargetGenerator::GenerateScriptForConfig(
std::ostream& os, const std::string& config, Indent const& indent)
{
// Compute the build tree directory from which to copy the target.
std::string fromDirConfig;
if (this->Target->NeedRelinkBeforeInstall(config)) {
fromDirConfig =
this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory();
fromDirConfig += cmake::GetCMakeFilesDirectory();
fromDirConfig += "/CMakeRelink.dir/";
} else {
fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary);
fromDirConfig += "/";
}
std::string toDir =
this->ConvertToAbsoluteDestination(this->GetDestination(config));
toDir += "/";
// Compute the list of files to install for this target.
std::vector<std::string> filesFrom;
std::vector<std::string> filesTo;
std::string literal_args;
cmStateEnums::TargetType targetType = this->Target->GetType();
cmInstallType type = cmInstallType();
switch (targetType) {
@@ -100,7 +81,11 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
assert(false &&
"INTERFACE_LIBRARY targets have no installable outputs.");
break;
case cmStateEnums::OBJECT_LIBRARY:
this->GenerateScriptForConfigObjectLibrary(os, config, indent);
return;
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
case cmStateEnums::UNKNOWN_LIBRARY:
@@ -109,6 +94,28 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
"cmInstallTargetGenerator created with non-installable target.");
return;
}
// Compute the build tree directory from which to copy the target.
std::string fromDirConfig;
if (this->Target->NeedRelinkBeforeInstall(config)) {
fromDirConfig =
this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory();
fromDirConfig += cmake::GetCMakeFilesDirectory();
fromDirConfig += "/CMakeRelink.dir/";
} else {
fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary);
fromDirConfig += "/";
}
std::string toDir =
this->ConvertToAbsoluteDestination(this->GetDestination(config));
toDir += "/";
// Compute the list of files to install for this target.
std::vector<std::string> filesFrom;
std::vector<std::string> filesTo;
std::string literal_args;
if (targetType == cmStateEnums::EXECUTABLE) {
// There is a bug in cmInstallCommand if this fails.
assert(this->NamelinkMode == NamelinkModeNone);
@@ -315,6 +322,49 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
&cmInstallTargetGenerator::PostReplacementTweaks);
}
static std::string computeInstallObjectDir(cmGeneratorTarget* gt,
std::string const& config)
{
std::string objectDir = "objects";
if (!config.empty()) {
objectDir += "-";
objectDir += config;
}
objectDir += "/";
objectDir += gt->GetName();
return objectDir;
}
void cmInstallTargetGenerator::GenerateScriptForConfigObjectLibrary(
std::ostream& os, const std::string& config, Indent const& indent)
{
// Compute all the object files inside this target
std::vector<std::string> objects;
this->Target->GetTargetObjectNames(config, objects);
std::string const dest = this->GetDestination(config) + "/" +
computeInstallObjectDir(this->Target, config);
std::string const obj_dir = this->Target->GetObjectDirectory(config);
std::string const literal_args = " FILES_FROM_DIR \"" + obj_dir + "\"";
const char* no_dir_permissions = CM_NULLPTR;
const char* no_rename = CM_NULLPTR;
this->AddInstallRule(os, dest, cmInstallType_FILES, objects, this->Optional,
this->FilePermissions.c_str(), no_dir_permissions,
no_rename, literal_args.c_str(), indent);
}
void cmInstallTargetGenerator::GetInstallObjectNames(
std::string const& config, std::vector<std::string>& objects) const
{
this->Target->GetTargetObjectNames(config, objects);
for (std::vector<std::string>::iterator i = objects.begin();
i != objects.end(); ++i) {
*i = computeInstallObjectDir(this->Target, config) + "/" + *i;
}
}
std::string cmInstallTargetGenerator::GetDestination(
std::string const& config) const
{
+6
View File
@@ -41,6 +41,9 @@ public:
std::string GetInstallFilename(const std::string& config) const;
void GetInstallObjectNames(std::string const& config,
std::vector<std::string>& objects) const;
enum NameType
{
NameNormal,
@@ -65,6 +68,9 @@ protected:
void GenerateScript(std::ostream& os) CM_OVERRIDE;
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
Indent const& indent) CM_OVERRIDE;
void GenerateScriptForConfigObjectLibrary(std::ostream& os,
const std::string& config,
Indent const& indent);
typedef void (cmInstallTargetGenerator::*TweakMethod)(std::ostream&,
Indent const&,
const std::string&,
+19 -11
View File
@@ -1351,11 +1351,9 @@ std::string cmTarget::ImportedGetFullPath(const std::string& config,
// Lookup/compute/cache the import information for this
// configuration.
std::string config_upper;
if (!config.empty()) {
config_upper = cmSystemTools::UpperCase(config);
} else {
config_upper = "NOCONFIG";
std::string desired_config = config;
if (config.empty()) {
desired_config = "NOCONFIG";
}
std::string result;
@@ -1365,7 +1363,7 @@ std::string cmTarget::ImportedGetFullPath(const std::string& config,
std::string suffix;
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->GetMappedConfig(config_upper, &loc, &imp, suffix)) {
this->GetMappedConfig(desired_config, &loc, &imp, suffix)) {
if (!pimplib) {
if (loc) {
result = loc;
@@ -1448,18 +1446,28 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
const char** loc, const char** imp,
std::string& suffix) const
{
std::string const locPropBase =
this->GetType() == cmStateEnums::INTERFACE_LIBRARY ? "IMPORTED_LIBNAME"
: "IMPORTED_LOCATION";
std::string config_upper;
if (!desired_config.empty()) {
config_upper = cmSystemTools::UpperCase(desired_config);
}
std::string locPropBase;
if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
locPropBase = "IMPORTED_LIBNAME";
} else if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
locPropBase = "IMPORTED_OBJECTS";
} else {
locPropBase = "IMPORTED_LOCATION";
}
// Track the configuration-specific property suffix.
suffix = "_";
suffix += desired_config;
suffix += config_upper;
std::vector<std::string> mappedConfigs;
{
std::string mapProp = "MAP_IMPORTED_CONFIG_";
mapProp += desired_config;
mapProp += config_upper;
if (const char* mapValue = this->GetProperty(mapProp)) {
cmSystemTools::ExpandListArgument(mapValue, mappedConfigs, true);
}
+1
View File
@@ -26,6 +26,7 @@ public:
cmInstallTargetGenerator* ArchiveGenerator;
cmInstallTargetGenerator* RuntimeGenerator;
cmInstallTargetGenerator* LibraryGenerator;
cmInstallTargetGenerator* ObjectsGenerator;
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
+2 -1
View File
@@ -1881,7 +1881,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
std::string lang =
this->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str());
std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf);
const std::string& linkLanguage = this->GeneratorTarget->GetLinkerLanguage();
const std::string& linkLanguage =
this->GeneratorTarget->GetLinkerLanguage("");
bool needForceLang = false;
// source file does not match its extension language
if (lang != sourceLang) {
+12 -1
View File
@@ -79,6 +79,15 @@ set_property(TARGET testLib7 PROPERTY OUTPUT_NAME_DEBUG testLib7D-$<CONFIG>)
set_property(TARGET testLib7 PROPERTY OUTPUT_NAME_RELEASE testLib7R-$<CONFIG>)
set_property(TARGET testLib7 PROPERTY OUTPUT_NAME testLib7-$<CONFIG>)
# Test exporting OBJECT targets
add_library(testLib8 OBJECT testLib8A.c testLib8B.c sub/testLib8C.c)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
set(maybe_testLib8 testLib8)
else()
set(maybe_testLib8 "")
endif()
# Test using the target_link_libraries command to set the
# LINK_INTERFACE_LIBRARIES* properties. We construct two libraries
# providing the same two symbols. In each library one of the symbols
@@ -474,7 +483,7 @@ install(
TARGETS
testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3 testExe4
testExe2lib testLib4lib testLib4libdbg testLib4libopt
testLib6 testLib7
testLib6 testLib7 ${maybe_testLib8}
testLibCycleA testLibCycleB
testLibNoSONAME
cmp0022NEW cmp0022OLD
@@ -483,6 +492,7 @@ install(
RUNTIME DESTINATION $<1:bin>
LIBRARY DESTINATION $<1:lib> NAMELINK_SKIP
ARCHIVE DESTINATION $<1:lib>
OBJECTS DESTINATION $<1:lib>
FRAMEWORK DESTINATION Frameworks
BUNDLE DESTINATION Applications
)
@@ -535,6 +545,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3
FILE ExportBuildTree.cmake
)
export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 testExe2lib
${maybe_testLib8}
testLib4lib testLib4libdbg testLib4libopt
testLibCycleA testLibCycleB
testLibNoSONAME
@@ -0,0 +1,4 @@
int testLib8C(void)
{
return 0;
}
+4
View File
@@ -0,0 +1,4 @@
int testLib8A(void)
{
return 0;
}
+4
View File
@@ -0,0 +1,4 @@
int testLib8B(void)
{
return 0;
}
@@ -228,6 +228,16 @@ target_link_libraries(imp_lib1 exp_testLib2)
add_library(imp_lib1b STATIC imp_lib1.c)
target_link_libraries(imp_lib1b bld_testLib2)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
# Create a executable that is using objects imported from the install tree
add_executable(imp_testLib8 imp_testLib8.c $<TARGET_OBJECTS:exp_testLib8>)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT XCODE_VERSION VERSION_LESS 5)
# Create a executable that is using objects imported from the build tree
add_executable(imp_testLib8b imp_testLib8.c $<TARGET_OBJECTS:bld_testLib8>)
endif()
endif()
#-----------------------------------------------------------------------------
# Test that handling imported targets, including transitive dependencies,
# works in CheckFunctionExists (...and hopefully all other try_compile() checks
+12 -12
View File
@@ -1,15 +1,15 @@
extern int generated_by_testExe1();
extern int generated_by_testExe3();
extern int generated_by_testExe4();
extern int testLib2();
extern int testLib3();
extern int testLib4();
extern int testLib4lib();
extern int testLib5();
extern int testLib6();
extern int testLib7();
extern int testLibCycleA1();
extern int testLibPerConfigDest();
extern int generated_by_testExe1(void);
extern int generated_by_testExe3(void);
extern int generated_by_testExe4(void);
extern int testLib2(void);
extern int testLib3(void);
extern int testLib4(void);
extern int testLib4lib(void);
extern int testLib5(void);
extern int testLib6(void);
extern int testLib7(void);
extern int testLibCycleA1(void);
extern int testLibPerConfigDest(void);
/* Switch a symbol between debug and optimized builds to make sure the
proper library is found from the testLib4 link interface. */
@@ -0,0 +1,8 @@
int testLib8A(void);
int testLib8B(void);
int main()
{
return (testLib8A() + testLib8B());
}
+16
View File
@@ -292,3 +292,19 @@ set(CMP0044_TYPE NEW)
add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-NEW)
set(CMP0044_TYPE OLD)
add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-OLD)
if(NOT CMAKE_GENERATOR STREQUAL Xcode OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
add_library(objlib OBJECT objlib1.c objlib2.c)
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/objlib_files_$<CONFIGURATION>"
CONTENT "$<JOIN:$<TARGET_OBJECTS:objlib>,\n>\n"
)
add_custom_target(check_object_files ALL
COMMAND ${CMAKE_COMMAND}
"-DOBJLIB_LISTFILE=${CMAKE_CURRENT_BINARY_DIR}/objlib_files_$<CONFIGURATION>"
-DEXPECTED_NUM_OBJECTFILES=2
-P "${CMAKE_CURRENT_SOURCE_DIR}/check_object_files.cmake"
DEPENDS objlib
)
endif()
@@ -0,0 +1,26 @@
if (NOT EXISTS ${OBJLIB_LISTFILE})
message(SEND_ERROR "Object listing file \"${OBJLIB_LISTFILE}\" not found!")
endif()
file(STRINGS ${OBJLIB_LISTFILE} objlib_files ENCODING UTF-8)
list(LENGTH objlib_files num_objectfiles)
if (NOT EXPECTED_NUM_OBJECTFILES EQUAL num_objectfiles)
message(SEND_ERROR "Unexpected number of entries in object list file (${num_objectfiles} instead of ${EXPECTED_NUM_OBJECTFILES})")
endif()
foreach(objlib_file ${objlib_files})
set(file_exists False)
if (EXISTS ${objlib_file})
set(file_exists True)
endif()
if (NOT file_exists)
if(attempts)
list(REMOVE_DUPLICATES attempts)
set(tried " Tried ${attempts}")
endif()
message(SEND_ERROR "File \"${objlib_file}\" does not exist!${tried}")
endif()
endforeach()
+4
View File
@@ -0,0 +1,4 @@
void objlib1()
{
}
+4
View File
@@ -0,0 +1,4 @@
void objlib2()
{
}
@@ -1,5 +1,6 @@
CMake Error in CMakeLists.txt:
Evaluation file to be written multiple times for different configurations
or languages with different content:
Evaluation file to be written multiple times with different content. This
is generally caused by the content evaluating the configuration type,
language, or location of object files:
.*output.txt
@@ -1,9 +1,8 @@
CMake Error at OutputNameMatchesObjects.cmake:2 \(file\):
CMake Error at OutputNameMatchesObjects.cmake:[0-9]+ \(file\):
Error evaluating generator expression:
\$<TARGET_OBJECTS:foo>
The evaluation of the TARGET_OBJECTS generator expression is only suitable
for consumption by CMake. It is not suitable for writing out elsewhere.
Objects of target "foo" referenced but is not an OBJECT library.
Call Stack \(most recent call first\):
CMakeLists.txt:6 \(include\)
CMakeLists.txt:[0-9]+ \(include\)
@@ -1,3 +1,4 @@
enable_language(CXX)
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<BOOL:$<TARGET_OBJECTS:foo>>somefile.cpp"
@@ -1,4 +0,0 @@
CMake Error at Export.cmake:2 \(export\):
export given OBJECT library "A" which may not be exported.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
@@ -0,0 +1,5 @@
CMake Error at ExportNotSupported.cmake:[0-9]+ \(export\):
export given OBJECT library "A" which may not be exported under Xcode with
multiple architectures.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
@@ -0,0 +1,2 @@
add_library(A OBJECT a.c)
export(TARGETS A FILE AExport.cmake)
+11
View File
@@ -1 +1,12 @@
add_library(A OBJECT IMPORTED)
# We don't actually build this example so just configure dummy
# object files to test. They do not have to exist.
set_property(TARGET A APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(A PROPERTIES
IMPORTED_OBJECTS_DEBUG "${CMAKE_CURRENT_BINARY_DIR}/does_not_exist.o"
IMPORTED_OBJECTS "${CMAKE_CURRENT_BINARY_DIR}/does_not_exist.o"
)
add_library(B $<TARGET_OBJECTS:A> b.c)
@@ -1,4 +1,5 @@
CMake Error at Import.cmake:1 \(add_library\):
The OBJECT library type may not be used for IMPORTED libraries.
CMake Error at ImportNotSupported.cmake:[0-9]+ \(add_library\):
The OBJECT library type may not be used for IMPORTED libraries under Xcode
with multiple architectures.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
@@ -0,0 +1 @@
add_library(A OBJECT IMPORTED)
@@ -1,4 +1,5 @@
CMake Error at Install.cmake:2 \(install\):
install TARGETS given OBJECT library "A" which may not be installed.
CMake Error at InstallNotSupported.cmake:[0-9]+ \(install\):
install TARGETS given OBJECT library "A" which may not be installed under
Xcode with multiple architectures.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
@@ -0,0 +1,2 @@
add_library(A OBJECT a.c)
install(TARGETS A DESTINATION lib)
@@ -5,9 +5,15 @@ run_cmake(BadSourceExpression2)
run_cmake(BadSourceExpression3)
run_cmake(BadObjSource1)
run_cmake(BadObjSource2)
run_cmake(Export)
run_cmake(Import)
run_cmake(Install)
if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
run_cmake(ExportNotSupported)
run_cmake(ImportNotSupported)
run_cmake(InstallNotSupported)
else()
run_cmake(Export)
run_cmake(Import)
run_cmake(Install)
endif()
run_cmake(LinkObjLHS)
run_cmake(LinkObjRHS1)
run_cmake(LinkObjRHS2)
+4
View File
@@ -0,0 +1,4 @@
int b(void)
{
return 0;
}
@@ -1,27 +0,0 @@
(CMake Error at BadContext.cmake:4 \(file\):
Error evaluating generator expression:
\$<TARGET_OBJECTS:NoTarget>
The evaluation of the TARGET_OBJECTS generator expression is only suitable
for consumption by CMake. It is not suitable for writing out elsewhere.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
*)+
(CMake Error at BadContext.cmake:5 \(file\):
Error evaluating generator expression:
\$<TARGET_OBJECTS:NoTarget>
The evaluation of the TARGET_OBJECTS generator expression is only suitable
for consumption by CMake. It is not suitable for writing out elsewhere.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
*)+
CMake Error:
Error evaluating generator expression:
\$<TARGET_OBJECTS:NoTarget>
The evaluation of the TARGET_OBJECTS generator expression is only suitable
for consumption by CMake. It is not suitable for writing out elsewhere.
@@ -0,0 +1,24 @@
(CMake Error at NoTarget.cmake:4 \(file\):
Error evaluating generator expression:
\$<TARGET_OBJECTS:NoTarget>
Objects of target "NoTarget" referenced but no such target exists.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
*)+
(CMake Error at NoTarget.cmake:5 \(file\):
Error evaluating generator expression:
\$<TARGET_OBJECTS:NoTarget>
Objects of target "NoTarget" referenced but no such target exists.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
*)+
CMake Error:
Error evaluating generator expression:
\$<TARGET_OBJECTS:NoTarget>
Objects of target "NoTarget" referenced but no such target exists.
@@ -0,0 +1 @@
1
@@ -0,0 +1,8 @@
CMake Error at NotObjlibTarget.cmake:3 \(file\):
Error evaluating generator expression:
\$<TARGET_OBJECTS:StaticLib>
Objects of target "StaticLib" referenced but is not an OBJECT library.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
@@ -0,0 +1,3 @@
add_library(StaticLib empty.cpp)
file(GENERATE OUTPUT test_output CONTENT $<TARGET_OBJECTS:StaticLib>)
@@ -1,3 +1,4 @@
include(RunCMake)
run_cmake(BadContext)
run_cmake(NoTarget)
run_cmake(NotObjlibTarget)
+4
View File
@@ -0,0 +1,4 @@
int empty()
{
return 0;
}