summaryrefslogtreecommitdiffstats
path: root/Source/cmGeneratorTarget.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r--Source/cmGeneratorTarget.cxx1139
1 files changed, 653 insertions, 486 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 3fe5c83..a0f677b 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -2,9 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorTarget.h"
+#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <assert.h>
-#include <cmsys/RegularExpression.hxx>
#include <errno.h>
#include <iterator>
#include <queue>
@@ -75,197 +75,6 @@ public:
};
cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
-void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib,
- cmGeneratorTarget const* target, cmake* cm)
-{
- if (!badObjLib.empty()) {
- std::ostringstream e;
- e << "OBJECT library \"" << target->GetName() << "\" contains:\n";
- for (std::vector<cmSourceFile*>::const_iterator i = badObjLib.begin();
- i != badObjLib.end(); ++i) {
- e << " " << (*i)->GetLocation().GetName() << "\n";
- }
- e << "but may contain only sources that compile, header files, and "
- "other files that would not affect linking of a normal library.";
- cm->IssueMessage(cmake::FATAL_ERROR, e.str(), target->GetBacktrace());
- }
-}
-
-struct ObjectSourcesTag
-{
-};
-struct CustomCommandsTag
-{
-};
-struct ExtraSourcesTag
-{
-};
-struct HeaderSourcesTag
-{
-};
-struct ExternalObjectsTag
-{
-};
-struct IDLSourcesTag
-{
-};
-struct ResxTag
-{
-};
-struct ModuleDefinitionFileTag
-{
-};
-struct AppManifestTag
-{
-};
-struct ManifestsTag
-{
-};
-struct CertificatesTag
-{
-};
-struct XamlTag
-{
-};
-
-template <typename Tag, typename OtherTag>
-struct IsSameTag
-{
- enum
- {
- Result = false
- };
-};
-
-template <typename Tag>
-struct IsSameTag<Tag, Tag>
-{
- enum
- {
- Result = true
- };
-};
-
-template <bool>
-struct DoAccept
-{
- template <typename T>
- static void Do(T& /*unused*/, cmSourceFile* /*unused*/)
- {
- }
-};
-
-template <>
-struct DoAccept<true>
-{
- static void Do(std::vector<cmSourceFile const*>& files, cmSourceFile* f)
- {
- files.push_back(f);
- }
- static void Do(cmGeneratorTarget::ResxData& data, cmSourceFile* f)
- {
- // Build and save the name of the corresponding .h file
- // This relationship will be used later when building the project files.
- // Both names would have been auto generated from Visual Studio
- // where the user supplied the file name and Visual Studio
- // appended the suffix.
- std::string resx = f->GetFullPath();
- std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
- data.ExpectedResxHeaders.insert(hFileName);
- data.ResxSources.push_back(f);
- }
- static void Do(cmGeneratorTarget::XamlData& data, cmSourceFile* f)
- {
- // Build and save the name of the corresponding .h and .cpp file
- // This relationship will be used later when building the project files.
- // Both names would have been auto generated from Visual Studio
- // where the user supplied the file name and Visual Studio
- // appended the suffix.
- std::string xaml = f->GetFullPath();
- std::string hFileName = xaml + ".h";
- std::string cppFileName = xaml + ".cpp";
- data.ExpectedXamlHeaders.insert(hFileName);
- data.ExpectedXamlSources.insert(cppFileName);
- data.XamlSources.push_back(f);
- }
- static void Do(std::string& data, cmSourceFile* f)
- {
- data = f->GetFullPath();
- }
-};
-
-template <typename Tag, typename DataType = std::vector<cmSourceFile const*> >
-struct TagVisitor
-{
- DataType& Data;
- std::vector<cmSourceFile*> BadObjLibFiles;
- cmGeneratorTarget const* Target;
- cmGlobalGenerator* GlobalGenerator;
- cmsys::RegularExpression Header;
- bool IsObjLib;
-
- TagVisitor(cmGeneratorTarget const* target, DataType& data)
- : Data(data)
- , Target(target)
- , GlobalGenerator(target->GetLocalGenerator()->GetGlobalGenerator())
- , Header(CM_HEADER_REGEX)
- , IsObjLib(target->GetType() == cmStateEnums::OBJECT_LIBRARY)
- {
- }
-
- ~TagVisitor()
- {
- reportBadObjLib(this->BadObjLibFiles, this->Target,
- this->GlobalGenerator->GetCMakeInstance());
- }
-
- void Accept(cmSourceFile* sf)
- {
- std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
- if (sf->GetCustomCommand()) {
- DoAccept<IsSameTag<Tag, CustomCommandsTag>::Result>::Do(this->Data, sf);
- } else if (this->Target->GetType() == cmStateEnums::UTILITY) {
- DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
- } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
- DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
- } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
- DoAccept<IsSameTag<Tag, ExternalObjectsTag>::Result>::Do(this->Data, sf);
- if (this->IsObjLib) {
- this->BadObjLibFiles.push_back(sf);
- }
- } else if (!sf->GetLanguage().empty()) {
- DoAccept<IsSameTag<Tag, ObjectSourcesTag>::Result>::Do(this->Data, sf);
- } else if (ext == "def") {
- DoAccept<IsSameTag<Tag, ModuleDefinitionFileTag>::Result>::Do(this->Data,
- sf);
- if (this->IsObjLib) {
- this->BadObjLibFiles.push_back(sf);
- }
- } else if (ext == "idl") {
- DoAccept<IsSameTag<Tag, IDLSourcesTag>::Result>::Do(this->Data, sf);
- if (this->IsObjLib) {
- this->BadObjLibFiles.push_back(sf);
- }
- } else if (ext == "resx") {
- DoAccept<IsSameTag<Tag, ResxTag>::Result>::Do(this->Data, sf);
- } else if (ext == "appxmanifest") {
- DoAccept<IsSameTag<Tag, AppManifestTag>::Result>::Do(this->Data, sf);
- } else if (ext == "manifest") {
- DoAccept<IsSameTag<Tag, ManifestsTag>::Result>::Do(this->Data, sf);
- } else if (ext == "pfx") {
- DoAccept<IsSameTag<Tag, CertificatesTag>::Result>::Do(this->Data, sf);
- } else if (ext == "xaml") {
- DoAccept<IsSameTag<Tag, XamlTag>::Result>::Do(this->Data, sf);
- } else if (this->Header.find(sf->GetFullPath().c_str())) {
- DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
- } else if (this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) {
- DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
- } else {
- DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
- }
- }
-};
-
void CreatePropertyGeneratorExpressions(
cmStringRange const& entries, cmBacktraceRange const& backtraces,
std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items,
@@ -286,6 +95,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
, FortranModuleDirectoryCreated(false)
, SourceFileFlagsConstructed(false)
, PolicyWarnedCMP0022(false)
+ , PolicyReportedCMP0069(false)
, DebugIncludesDone(false)
, DebugCompileOptionsDone(false)
, DebugCompileFeaturesDone(false)
@@ -406,52 +216,60 @@ const char* cmGeneratorTarget::GetProperty(const std::string& prop) const
return this->Target->GetProperty(prop);
}
-const char* cmGeneratorTarget::GetOutputTargetType(bool implib) const
+const char* cmGeneratorTarget::GetOutputTargetType(
+ cmStateEnums::ArtifactType artifact) const
{
switch (this->GetType()) {
case cmStateEnums::SHARED_LIBRARY:
if (this->IsDLLPlatform()) {
- if (implib) {
- // A DLL import library is treated as an archive target.
- return "ARCHIVE";
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ // A DLL shared library is treated as a runtime target.
+ return "RUNTIME";
+ case cmStateEnums::ImportLibraryArtifact:
+ // A DLL import library is treated as an archive target.
+ return "ARCHIVE";
}
- // A DLL shared library is treated as a runtime target.
- return "RUNTIME";
} else {
// For non-DLL platforms shared libraries are treated as
// library targets.
return "LIBRARY";
}
+ break;
case cmStateEnums::STATIC_LIBRARY:
// Static libraries are always treated as archive targets.
return "ARCHIVE";
case cmStateEnums::MODULE_LIBRARY:
- if (implib) {
- // Module libraries are always treated as library targets.
- return "ARCHIVE";
- } else {
- // Module import libraries are treated as archive targets.
- return "LIBRARY";
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ // Module import libraries are treated as archive targets.
+ return "LIBRARY";
+ case cmStateEnums::ImportLibraryArtifact:
+ // Module libraries are always treated as library targets.
+ return "ARCHIVE";
}
+ break;
case cmStateEnums::EXECUTABLE:
- if (implib) {
- // Executable import libraries are treated as archive targets.
- return "ARCHIVE";
- } else {
- // Executables are always treated as runtime targets.
- return "RUNTIME";
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ // Executables are always treated as runtime targets.
+ return "RUNTIME";
+ case cmStateEnums::ImportLibraryArtifact:
+ // Executable import libraries are treated as archive targets.
+ return "ARCHIVE";
}
+ break;
default:
break;
}
return "";
}
-std::string cmGeneratorTarget::GetOutputName(const std::string& config,
- bool implib) const
+std::string cmGeneratorTarget::GetOutputName(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
// Lookup/compute/cache the output name for this configuration.
- OutputNameKey key(config, implib);
+ OutputNameKey key(config, artifact);
cmGeneratorTarget::OutputNameMapType::iterator i =
this->OutputNameMap.find(key);
if (i == this->OutputNameMap.end()) {
@@ -461,7 +279,7 @@ std::string cmGeneratorTarget::GetOutputName(const std::string& config,
// Compute output name.
std::vector<std::string> props;
- std::string type = this->GetOutputTargetType(implib);
+ std::string type = this->GetOutputTargetType(artifact);
std::string configUpper = cmSystemTools::UpperCase(config);
if (!type.empty() && !configUpper.empty()) {
// <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
@@ -515,7 +333,7 @@ void cmGeneratorTarget::AddSourceCommon(const std::string& src)
CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(src);
cge->SetEvaluateForBuildsystem(true);
this->SourceEntries.push_back(new TargetPropertyEntry(cge));
- this->SourceFilesMap.clear();
+ this->KindedSourcesMap.clear();
this->LinkImplementationLanguageIsContextDependent = true;
}
@@ -587,27 +405,22 @@ static void handleSystemIncludesDep(
}
/* clang-format off */
-#define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE) \
+#define IMPLEMENT_VISIT(KIND) \
{ \
- std::vector<cmSourceFile*> sourceFiles; \
- this->GetSourceFiles(sourceFiles, config); \
- TagVisitor< DATA##Tag DATATYPE > visitor(this, data); \
- for (std::vector<cmSourceFile*>::const_iterator si = sourceFiles.begin(); \
- si != sourceFiles.end(); ++si) { \
- visitor.Accept(*si); \
+ KindedSources const& kinded = this->GetKindedSources(config); \
+ for (std::vector<SourceAndKind>::const_iterator \
+ si = kinded.Sources.begin(); si != kinded.Sources.end(); ++si) { \
+ if (si->Kind == KIND) { \
+ data.push_back(si->Source); \
+ } \
} \
}
/* clang-format on */
-#define IMPLEMENT_VISIT(DATA) IMPLEMENT_VISIT_IMPL(DATA, EMPTY)
-
-#define EMPTY
-#define COMMA ,
-
void cmGeneratorTarget::GetObjectSources(
std::vector<cmSourceFile const*>& data, const std::string& config) const
{
- IMPLEMENT_VISIT(ObjectSources);
+ IMPLEMENT_VISIT(SourceKindObjectSource);
if (!this->Objects.empty()) {
return;
@@ -656,10 +469,65 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
return this->LocalGenerator->GetFeature(feature, config);
}
-bool cmGeneratorTarget::GetFeatureAsBool(const std::string& feature,
- const std::string& config) const
+bool cmGeneratorTarget::IsIPOEnabled(const std::string& config) const
{
- return cmSystemTools::IsOn(this->GetFeature(feature, config));
+ const char* feature = "INTERPROCEDURAL_OPTIMIZATION";
+ const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config));
+
+ if (!result) {
+ // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies
+ return false;
+ }
+
+ cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069();
+
+ if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) {
+ if (this->Makefile->IsOn("_CMAKE_IPO_LEGACY_BEHAVIOR")) {
+ return true;
+ }
+ if (this->PolicyReportedCMP0069) {
+ // problem is already reported, no need to issue a message
+ return false;
+ }
+ if (cmp0069 == cmPolicies::WARN) {
+ std::ostringstream w;
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0069) << "\n";
+ w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target "
+ << "'" << this->GetName() << "'.";
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace());
+
+ this->PolicyReportedCMP0069 = true;
+ }
+ return false;
+ }
+
+ // Note: check consistency with messages from CheckIPOSupported
+ const char* message = CM_NULLPTR;
+ if (!this->Makefile->IsOn("_CMAKE_IPO_SUPPORTED_BY_CMAKE")) {
+ message = "CMake doesn't support IPO for current compiler";
+ } else if (!this->Makefile->IsOn(
+ "_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) {
+ message = "Compiler doesn't support IPO";
+ } else if (!this->GlobalGenerator->IsIPOSupported()) {
+ message = "CMake doesn't support IPO for current generator";
+ }
+
+ if (!message) {
+ // No error/warning messages
+ return true;
+ }
+
+ if (this->PolicyReportedCMP0069) {
+ // problem is already reported, no need to issue a message
+ return false;
+ }
+
+ this->PolicyReportedCMP0069 = true;
+
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR, message, this->GetBacktrace());
+ return false;
}
const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
@@ -668,6 +536,18 @@ const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
return this->Objects[file];
}
+const char* cmGeneratorTarget::GetCustomObjectExtension() const
+{
+ static std::string extension;
+ const bool has_ptx_extension =
+ this->GetPropertyAsBool("CUDA_PTX_COMPILATION");
+ if (has_ptx_extension) {
+ extension = ".ptx";
+ return extension.c_str();
+ }
+ return CM_NULLPTR;
+}
+
void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
{
this->ExplicitObjectName.insert(sf);
@@ -681,84 +561,79 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
return it != this->ExplicitObjectName.end();
}
-void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile const*>& data,
- const std::string& config) const
+void cmGeneratorTarget::GetModuleDefinitionSources(
+ std::vector<cmSourceFile const*>& data, const std::string& config) const
{
- IMPLEMENT_VISIT(IDLSources);
+ IMPLEMENT_VISIT(SourceKindModuleDefinition);
}
void cmGeneratorTarget::GetHeaderSources(
std::vector<cmSourceFile const*>& data, const std::string& config) const
{
- IMPLEMENT_VISIT(HeaderSources);
+ IMPLEMENT_VISIT(SourceKindHeader);
}
void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile const*>& data,
const std::string& config) const
{
- IMPLEMENT_VISIT(ExtraSources);
+ IMPLEMENT_VISIT(SourceKindExtra);
}
void cmGeneratorTarget::GetCustomCommands(
std::vector<cmSourceFile const*>& data, const std::string& config) const
{
- IMPLEMENT_VISIT(CustomCommands);
+ IMPLEMENT_VISIT(SourceKindCustomCommand);
}
void cmGeneratorTarget::GetExternalObjects(
std::vector<cmSourceFile const*>& data, const std::string& config) const
{
- IMPLEMENT_VISIT(ExternalObjects);
+ IMPLEMENT_VISIT(SourceKindExternalObject);
}
-void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& srcs,
+void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& headers,
const std::string& config) const
{
- ResxData data;
- IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
- srcs = data.ExpectedResxHeaders;
+ KindedSources const& kinded = this->GetKindedSources(config);
+ headers = kinded.ExpectedResxHeaders;
}
-void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& srcs,
+void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& data,
const std::string& config) const
{
- ResxData data;
- IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
- srcs = data.ResxSources;
+ IMPLEMENT_VISIT(SourceKindResx);
}
void cmGeneratorTarget::GetAppManifest(std::vector<cmSourceFile const*>& data,
const std::string& config) const
{
- IMPLEMENT_VISIT(AppManifest);
+ IMPLEMENT_VISIT(SourceKindAppManifest);
}
void cmGeneratorTarget::GetManifests(std::vector<cmSourceFile const*>& data,
const std::string& config) const
{
- IMPLEMENT_VISIT(Manifests);
+ IMPLEMENT_VISIT(SourceKindManifest);
}
void cmGeneratorTarget::GetCertificates(std::vector<cmSourceFile const*>& data,
const std::string& config) const
{
- IMPLEMENT_VISIT(Certificates);
+ IMPLEMENT_VISIT(SourceKindCertificate);
}
void cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers,
const std::string& config) const
{
- XamlData data;
- IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
- headers = data.ExpectedXamlHeaders;
+ KindedSources const& kinded = this->GetKindedSources(config);
+ headers = kinded.ExpectedXamlHeaders;
}
void cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
const std::string& config) const
{
- XamlData data;
- IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
- srcs = data.ExpectedXamlSources;
+ KindedSources const& kinded = this->GetKindedSources(config);
+ srcs = kinded.ExpectedXamlSources;
}
std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
@@ -776,21 +651,20 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
return this->UtilityItems;
}
-void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& srcs,
+void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& data,
const std::string& config) const
{
- XamlData data;
- IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
- srcs = data.XamlSources;
+ IMPLEMENT_VISIT(SourceKindXaml);
}
const char* cmGeneratorTarget::GetLocation(const std::string& config) const
{
static std::string location;
if (this->IsImported()) {
- location = this->Target->ImportedGetFullPath(config, false);
+ location = this->Target->ImportedGetFullPath(
+ config, cmStateEnums::RuntimeBinaryArtifact);
} else {
- location = this->GetFullPath(config, false);
+ location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
}
return location.c_str();
}
@@ -827,7 +701,8 @@ const char* cmGeneratorTarget::GetLocationForBuild() const
{
static std::string location;
if (this->IsImported()) {
- location = this->Target->ImportedGetFullPath("", false);
+ location = this->Target->ImportedGetFullPath(
+ "", cmStateEnums::RuntimeBinaryArtifact);
return location.c_str();
}
@@ -840,14 +715,14 @@ const char* cmGeneratorTarget::GetLocationForBuild() const
}
if (this->IsAppBundleOnApple()) {
- std::string macdir = this->BuildMacContentDirectory("", "", false);
+ std::string macdir = this->BuildBundleDirectory("", "", FullLevel);
if (!macdir.empty()) {
location += "/";
location += macdir;
}
}
location += "/";
- location += this->GetFullName("", false);
+ location += this->GetFullName("", cmStateEnums::RuntimeBinaryArtifact);
return location.c_str();
}
@@ -1088,24 +963,16 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
const std::string& config) const
{
-
- // Lookup any existing link implementation for this configuration.
- std::string key = cmSystemTools::UpperCase(config);
-
- if (!this->LinkImplementationLanguageIsContextDependent) {
- files = this->SourceFilesMap.begin()->second;
- return;
- }
-
- SourceFilesMapType::iterator it = this->SourceFilesMap.find(key);
- if (it != this->SourceFilesMap.end()) {
- files = it->second;
- } else {
+ if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ // Since we are still configuring not all sources may exist yet,
+ // so we need to avoid full source classification because that
+ // requires the absolute paths to all sources to be determined.
+ // Since this is only for compatibility with old policies that
+ // projects should not depend on anymore, just compute the files
+ // without memoizing them.
std::vector<std::string> srcs;
this->GetSourceFiles(srcs, config);
-
std::set<cmSourceFile*> emitted;
-
for (std::vector<std::string>::const_iterator i = srcs.begin();
i != srcs.end(); ++i) {
cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
@@ -1113,7 +980,184 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
files.push_back(sf);
}
}
- this->SourceFilesMap[key] = files;
+ return;
+ }
+
+ KindedSources const& kinded = this->GetKindedSources(config);
+ files.reserve(kinded.Sources.size());
+ for (std::vector<SourceAndKind>::const_iterator si = kinded.Sources.begin();
+ si != kinded.Sources.end(); ++si) {
+ files.push_back(si->Source);
+ }
+}
+
+void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
+ std::vector<cmSourceFile*>& files, const std::string& config) const
+{
+ KindedSources const& kinded = this->GetKindedSources(config);
+ files.reserve(kinded.Sources.size());
+ for (std::vector<SourceAndKind>::const_iterator si = kinded.Sources.begin();
+ si != kinded.Sources.end(); ++si) {
+ if (si->Source->GetObjectLibrary().empty()) {
+ files.push_back(si->Source);
+ }
+ }
+}
+
+cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
+ std::string const& config) const
+{
+ // If we already processed one configuration and found no dependenc
+ // on configuration then always use the one result.
+ if (!this->LinkImplementationLanguageIsContextDependent) {
+ return this->KindedSourcesMap.begin()->second;
+ }
+
+ // Lookup any existing link implementation for this configuration.
+ std::string const key = cmSystemTools::UpperCase(config);
+ KindedSourcesMapType::iterator it = this->KindedSourcesMap.find(key);
+ if (it != this->KindedSourcesMap.end()) {
+ return it->second;
+ }
+
+ // Add an entry to the map for this configuration.
+ KindedSources& files = this->KindedSourcesMap[key];
+ this->ComputeKindedSources(files, config);
+ return files;
+}
+
+void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
+ std::string const& config) const
+{
+ // Get the source file paths by string.
+ std::vector<std::string> srcs;
+ this->GetSourceFiles(srcs, config);
+
+ cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
+ std::vector<cmSourceFile*> badObjLib;
+
+ std::set<cmSourceFile*> emitted;
+ for (std::vector<std::string>::const_iterator i = srcs.begin();
+ i != srcs.end(); ++i) {
+ // Create each source at most once.
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
+ if (!emitted.insert(sf).second) {
+ continue;
+ }
+
+ // Compute the kind (classification) of this source file.
+ SourceKind kind;
+ std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
+ if (sf->GetCustomCommand()) {
+ kind = SourceKindCustomCommand;
+ } else if (this->Target->GetType() == cmStateEnums::UTILITY) {
+ kind = SourceKindExtra;
+ } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
+ kind = SourceKindHeader;
+ } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
+ kind = SourceKindExternalObject;
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ badObjLib.push_back(sf);
+ }
+ } else if (!sf->GetLanguage().empty()) {
+ kind = SourceKindObjectSource;
+ } else if (ext == "def") {
+ kind = SourceKindModuleDefinition;
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ badObjLib.push_back(sf);
+ }
+ } else if (ext == "idl") {
+ kind = SourceKindIDL;
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ badObjLib.push_back(sf);
+ }
+ } else if (ext == "resx") {
+ kind = SourceKindResx;
+ // Build and save the name of the corresponding .h file
+ // This relationship will be used later when building the project files.
+ // Both names would have been auto generated from Visual Studio
+ // where the user supplied the file name and Visual Studio
+ // appended the suffix.
+ std::string resx = sf->GetFullPath();
+ std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
+ files.ExpectedResxHeaders.insert(hFileName);
+ } else if (ext == "appxmanifest") {
+ kind = SourceKindAppManifest;
+ } else if (ext == "manifest") {
+ kind = SourceKindManifest;
+ } else if (ext == "pfx") {
+ kind = SourceKindCertificate;
+ } else if (ext == "xaml") {
+ kind = SourceKindXaml;
+ // Build and save the name of the corresponding .h and .cpp file
+ // This relationship will be used later when building the project files.
+ // Both names would have been auto generated from Visual Studio
+ // where the user supplied the file name and Visual Studio
+ // appended the suffix.
+ std::string xaml = sf->GetFullPath();
+ std::string hFileName = xaml + ".h";
+ std::string cppFileName = xaml + ".cpp";
+ files.ExpectedXamlHeaders.insert(hFileName);
+ files.ExpectedXamlSources.insert(cppFileName);
+ } else if (header_regex.find(sf->GetFullPath().c_str())) {
+ kind = SourceKindHeader;
+ } else {
+ kind = SourceKindExtra;
+ }
+
+ // Save this classified source file in the result vector.
+ SourceAndKind entry = { sf, kind };
+ files.Sources.push_back(entry);
+ }
+
+ if (!badObjLib.empty()) {
+ std::ostringstream e;
+ e << "OBJECT library \"" << this->GetName() << "\" contains:\n";
+ for (std::vector<cmSourceFile*>::const_iterator i = badObjLib.begin();
+ i != badObjLib.end(); ++i) {
+ e << " " << (*i)->GetLocation().GetName() << "\n";
+ }
+ e << "but may contain only sources that compile, header files, and "
+ "other files that would not affect linking of a normal library.";
+ this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
+ }
+}
+
+std::vector<cmGeneratorTarget::AllConfigSource> const&
+cmGeneratorTarget::GetAllConfigSources() const
+{
+ if (this->AllConfigSources.empty()) {
+ this->ComputeAllConfigSources();
+ }
+ return this->AllConfigSources;
+}
+
+void cmGeneratorTarget::ComputeAllConfigSources() const
+{
+ std::vector<std::string> configs;
+ this->Makefile->GetConfigurations(configs);
+
+ std::map<cmSourceFile const*, size_t> index;
+
+ for (size_t ci = 0; ci < configs.size(); ++ci) {
+ KindedSources const& sources = this->GetKindedSources(configs[ci]);
+ for (std::vector<cmGeneratorTarget::SourceAndKind>::const_iterator si =
+ sources.Sources.begin();
+ si != sources.Sources.end(); ++si) {
+ std::map<cmSourceFile const*, size_t>::iterator mi =
+ index.find(si->Source);
+ if (mi == index.end()) {
+ AllConfigSource acs;
+ acs.Source = si->Source;
+ acs.Kind = si->Kind;
+ this->AllConfigSources.push_back(acs);
+ std::map<cmSourceFile const*, size_t>::value_type entry(
+ si->Source, this->AllConfigSources.size() - 1);
+ mi = index.insert(entry).first;
+ }
+ this->AllConfigSources[mi->second].Configs.push_back(ci);
+ }
}
}
@@ -1123,7 +1167,8 @@ std::string cmGeneratorTarget::GetCompilePDBName(
std::string prefix;
std::string base;
std::string suffix;
- this->GetFullNameInternal(config, false, prefix, base, suffix);
+ this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+ prefix, base, suffix);
// Check for a per-configuration output directory target property.
std::string configUpper = cmSystemTools::UpperCase(config);
@@ -1321,8 +1366,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir(
return false;
}
const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
- bool use_install_name =
- this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
+ bool use_install_name = this->MacOSXUseInstallNameDir();
if (install_name && use_install_name &&
std::string(install_name) == "@rpath") {
install_name_is_rpath = true;
@@ -1395,6 +1439,53 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const
return cmp0042 == cmPolicies::NEW;
}
+bool cmGeneratorTarget::MacOSXUseInstallNameDir() const
+{
+ const char* build_with_install_name =
+ this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR");
+ if (build_with_install_name) {
+ return cmSystemTools::IsOn(build_with_install_name);
+ }
+
+ cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
+ if (cmp0068 == cmPolicies::NEW) {
+ return false;
+ }
+
+ bool use_install_name = this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
+
+ if (use_install_name && cmp0068 == cmPolicies::WARN) {
+ this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
+ this->GetName());
+ }
+
+ return use_install_name;
+}
+
+bool cmGeneratorTarget::CanGenerateInstallNameDir(
+ InstallNameType name_type) const
+{
+ cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
+
+ if (cmp0068 == cmPolicies::NEW) {
+ return true;
+ }
+
+ bool skip = this->Makefile->IsOn("CMAKE_SKIP_RPATH");
+ if (name_type == INSTALL_NAME_FOR_INSTALL) {
+ skip |= this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
+ } else {
+ skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH");
+ }
+
+ if (skip && cmp0068 == cmPolicies::WARN) {
+ this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
+ this->GetName());
+ }
+
+ return !skip;
+}
+
std::string cmGeneratorTarget::GetSOName(const std::string& config) const
{
if (this->IsImported()) {
@@ -1424,19 +1515,31 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const
return soName;
}
-std::string cmGeneratorTarget::GetAppBundleDirectory(const std::string& config,
- bool contentOnly) const
+static bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level)
{
- std::string fpath = this->GetFullName(config, false);
+ return level == cmGeneratorTarget::FullLevel;
+}
+
+static bool shouldAddContentLevel(
+ cmGeneratorTarget::BundleDirectoryLevel level)
+{
+ return level == cmGeneratorTarget::ContentLevel || shouldAddFullLevel(level);
+}
+
+std::string cmGeneratorTarget::GetAppBundleDirectory(
+ const std::string& config, BundleDirectoryLevel level) const
+{
+ std::string fpath =
+ this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact);
fpath += ".";
const char* ext = this->GetProperty("BUNDLE_EXTENSION");
if (!ext) {
ext = "app";
}
fpath += ext;
- if (!this->Makefile->PlatformIsAppleIos()) {
+ if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
fpath += "/Contents";
- if (!contentOnly) {
+ if (shouldAddFullLevel(level)) {
fpath += "/MacOS";
}
}
@@ -1449,11 +1552,11 @@ bool cmGeneratorTarget::IsBundleOnApple() const
this->IsCFBundleOnApple();
}
-std::string cmGeneratorTarget::GetCFBundleDirectory(const std::string& config,
- bool contentOnly) const
+std::string cmGeneratorTarget::GetCFBundleDirectory(
+ const std::string& config, BundleDirectoryLevel level) const
{
std::string fpath;
- fpath += this->GetOutputName(config, false);
+ fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
fpath += ".";
const char* ext = this->GetProperty("BUNDLE_EXTENSION");
if (!ext) {
@@ -1464,63 +1567,64 @@ std::string cmGeneratorTarget::GetCFBundleDirectory(const std::string& config,
}
}
fpath += ext;
- if (!this->Makefile->PlatformIsAppleIos()) {
+ if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
fpath += "/Contents";
- if (!contentOnly) {
+ if (shouldAddFullLevel(level)) {
fpath += "/MacOS";
}
}
return fpath;
}
-std::string cmGeneratorTarget::GetFrameworkDirectory(const std::string& config,
- bool rootDir) const
+std::string cmGeneratorTarget::GetFrameworkDirectory(
+ const std::string& config, BundleDirectoryLevel level) const
{
std::string fpath;
- fpath += this->GetOutputName(config, false);
+ fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
fpath += ".";
const char* ext = this->GetProperty("BUNDLE_EXTENSION");
if (!ext) {
ext = "framework";
}
fpath += ext;
- if (!rootDir && !this->Makefile->PlatformIsAppleIos()) {
+ if (shouldAddFullLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
fpath += "/Versions/";
fpath += this->GetFrameworkVersion();
}
return fpath;
}
-std::string cmGeneratorTarget::GetFullName(const std::string& config,
- bool implib) const
+std::string cmGeneratorTarget::GetFullName(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
if (this->IsImported()) {
- return this->GetFullNameImported(config, implib);
+ return this->GetFullNameImported(config, artifact);
}
- return this->GetFullNameInternal(config, implib);
+ return this->GetFullNameInternal(config, artifact);
}
std::string cmGeneratorTarget::GetInstallNameDirForBuildTree(
const std::string& config) const
{
- // If building directly for installation then the build tree install_name
- // is the same as the install tree.
- if (this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) {
- return this->GetInstallNameDirForInstallTree();
- }
+ if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
- // Use the build tree directory for the target.
- if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") &&
- !this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
- !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) {
- std::string dir;
- if (this->MacOSXRpathInstallNameDirDefault()) {
- dir = "@rpath";
- } else {
- dir = this->GetDirectory(config);
+ // If building directly for installation then the build tree install_name
+ // is the same as the install tree.
+ if (this->MacOSXUseInstallNameDir()) {
+ return this->GetInstallNameDirForInstallTree();
+ }
+
+ // Use the build tree directory for the target.
+ if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_BUILD)) {
+ std::string dir;
+ if (this->MacOSXRpathInstallNameDirDefault()) {
+ dir = "@rpath";
+ } else {
+ dir = this->GetDirectory(config);
+ }
+ dir += "/";
+ return dir;
}
- dir += "/";
- return dir;
}
return "";
}
@@ -1531,8 +1635,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
std::string dir;
const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
- if (!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
- !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) {
+ if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
if (install_name_dir && *install_name_dir) {
dir = install_name_dir;
dir += "/";
@@ -1790,44 +1893,43 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
}
}
-void cmGeneratorTarget::GetFullNameComponents(std::string& prefix,
- std::string& base,
- std::string& suffix,
- const std::string& config,
- bool implib) const
+void cmGeneratorTarget::GetFullNameComponents(
+ std::string& prefix, std::string& base, std::string& suffix,
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
- this->GetFullNameInternal(config, implib, prefix, base, suffix);
+ this->GetFullNameInternal(config, artifact, prefix, base, suffix);
}
-std::string cmGeneratorTarget::BuildMacContentDirectory(
- const std::string& base, const std::string& config, bool contentOnly) const
+std::string cmGeneratorTarget::BuildBundleDirectory(
+ const std::string& base, const std::string& config,
+ BundleDirectoryLevel level) const
{
std::string fpath = base;
if (this->IsAppBundleOnApple()) {
- fpath += this->GetAppBundleDirectory(config, contentOnly);
+ fpath += this->GetAppBundleDirectory(config, level);
}
if (this->IsFrameworkOnApple()) {
- fpath += this->GetFrameworkDirectory(config, contentOnly);
+ fpath += this->GetFrameworkDirectory(config, level);
}
if (this->IsCFBundleOnApple()) {
- fpath += this->GetCFBundleDirectory(config, contentOnly);
+ fpath += this->GetCFBundleDirectory(config, level);
}
return fpath;
}
std::string cmGeneratorTarget::GetMacContentDirectory(
- const std::string& config, bool implib) const
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
// Start with the output directory for the target.
- std::string fpath = this->GetDirectory(config, implib);
+ std::string fpath = this->GetDirectory(config, artifact);
fpath += "/";
- bool contentOnly = true;
+ BundleDirectoryLevel level = ContentLevel;
if (this->IsFrameworkOnApple()) {
// additional files with a framework go into the version specific
// directory
- contentOnly = false;
+ level = FullLevel;
}
- fpath = this->BuildMacContentDirectory(fpath, config, contentOnly);
+ fpath = this->BuildBundleDirectory(fpath, config, level);
return fpath;
}
@@ -1880,57 +1982,51 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
return &i->second;
}
-cmSourceFile const* cmGeneratorTarget::GetModuleDefinitionFile(
- const std::string& config) const
+cmGeneratorTarget::ModuleDefinitionInfo const*
+cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const
{
- std::vector<cmSourceFile const*> data;
- IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile,
- COMMA std::vector<cmSourceFile const*>)
- if (!data.empty()) {
- return data.front();
+ // A module definition file only makes sense on certain target types.
+ if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ !this->IsExecutableWithExports()) {
+ return CM_NULLPTR;
}
- return CM_NULLPTR;
+ // Lookup/compute/cache the compile information for this configuration.
+ std::string config_upper;
+ if (!config.empty()) {
+ config_upper = cmSystemTools::UpperCase(config);
+ }
+ ModuleDefinitionInfoMapType::const_iterator i =
+ this->ModuleDefinitionInfoMap.find(config_upper);
+ if (i == this->ModuleDefinitionInfoMap.end()) {
+ ModuleDefinitionInfo info;
+ this->ComputeModuleDefinitionInfo(config, info);
+ ModuleDefinitionInfoMapType::value_type entry(config_upper, info);
+ i = this->ModuleDefinitionInfoMap.insert(entry).first;
+ }
+ return &i->second;
}
-bool cmGeneratorTarget::IsDLLPlatform() const
+void cmGeneratorTarget::ComputeModuleDefinitionInfo(
+ std::string const& config, ModuleDefinitionInfo& info) const
{
- return this->DLLPlatform;
+ this->GetModuleDefinitionSources(info.Sources, config);
+ info.WindowsExportAllSymbols =
+ this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
+ this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
+ info.DefFileGenerated =
+ info.WindowsExportAllSymbols || info.Sources.size() > 1;
+ if (info.DefFileGenerated) {
+ info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
+ } else if (!info.Sources.empty()) {
+ info.DefFile = info.Sources.front()->GetFullPath();
+ }
}
-void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs,
- const std::string& config) const
+bool cmGeneratorTarget::IsDLLPlatform() const
{
- std::vector<cmSourceFile const*> objectFiles;
- this->GetExternalObjects(objectFiles, config);
- std::vector<cmGeneratorTarget*> objectLibraries;
- for (std::vector<cmSourceFile const*>::const_iterator it =
- objectFiles.begin();
- it != objectFiles.end(); ++it) {
- std::string objLib = (*it)->GetObjectLibrary();
- if (cmGeneratorTarget* tgt =
- this->LocalGenerator->FindGeneratorTargetToUse(objLib)) {
- objectLibraries.push_back(tgt);
- }
- }
-
- std::vector<cmGeneratorTarget*>::const_iterator end =
- cmRemoveDuplicates(objectLibraries);
-
- for (std::vector<cmGeneratorTarget*>::const_iterator ti =
- objectLibraries.begin();
- ti != end; ++ti) {
- cmGeneratorTarget* ogt = *ti;
- std::vector<cmSourceFile const*> objectSources;
- ogt->GetObjectSources(objectSources, config);
- for (std::vector<cmSourceFile const*>::const_iterator si =
- objectSources.begin();
- si != objectSources.end(); ++si) {
- std::string obj = ogt->ObjectDirectory;
- obj += ogt->Objects[*si];
- objs.push_back(obj);
- }
- }
+ return this->DLLPlatform;
}
void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
@@ -2317,19 +2413,28 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
}
}
+//----------------------------------------------------------------------------
+std::string cmGeneratorTarget::GetFeatureSpecificLinkRuleVariable(
+ std::string const& var, std::string const& config) const
+{
+ if (this->IsIPOEnabled(config)) {
+ std::string varIPO = var + "_IPO";
+ if (this->Makefile->IsDefinitionSet(varIPO)) {
+ return varIPO;
+ }
+ }
+
+ return var;
+}
+
+//----------------------------------------------------------------------------
std::string cmGeneratorTarget::GetCreateRuleVariable(
std::string const& lang, std::string const& config) const
{
switch (this->GetType()) {
case cmStateEnums::STATIC_LIBRARY: {
std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY";
- if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION", config)) {
- std::string varIPO = var + "_IPO";
- if (this->Makefile->GetDefinition(varIPO)) {
- return varIPO;
- }
- }
- return var;
+ return this->GetFeatureSpecificLinkRuleVariable(var, config);
}
case cmStateEnums::SHARED_LIBRARY:
return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY";
@@ -2777,7 +2882,8 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
}
// Get the directory.
- std::string dir = this->GetDirectory(config, false);
+ std::string dir =
+ this->GetDirectory(config, cmStateEnums::RuntimeBinaryArtifact);
// Add each name.
std::string f;
@@ -2806,7 +2912,7 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
gg->AddToManifest(f);
}
if (!impName.empty()) {
- f = this->GetDirectory(config, true);
+ f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
f += "/";
f += impName;
gg->AddToManifest(f);
@@ -2824,32 +2930,39 @@ std::string cmGeneratorTarget::GetImportedLibName(
}
std::string cmGeneratorTarget::GetFullPath(const std::string& config,
- bool implib, bool realname) const
+ cmStateEnums::ArtifactType artifact,
+ bool realname) const
{
if (this->IsImported()) {
- return this->Target->ImportedGetFullPath(config, implib);
+ return this->Target->ImportedGetFullPath(config, artifact);
}
- return this->NormalGetFullPath(config, implib, realname);
+ return this->NormalGetFullPath(config, artifact, realname);
}
-std::string cmGeneratorTarget::NormalGetFullPath(const std::string& config,
- bool implib,
- bool realname) const
+std::string cmGeneratorTarget::NormalGetFullPath(
+ const std::string& config, cmStateEnums::ArtifactType artifact,
+ bool realname) const
{
- std::string fpath = this->GetDirectory(config, implib);
+ std::string fpath = this->GetDirectory(config, artifact);
fpath += "/";
if (this->IsAppBundleOnApple()) {
- fpath = this->BuildMacContentDirectory(fpath, config, false);
+ fpath = this->BuildBundleDirectory(fpath, config, FullLevel);
fpath += "/";
}
// Add the full name of the target.
- if (implib) {
- fpath += this->GetFullName(config, true);
- } else if (realname) {
- fpath += this->NormalGetRealName(config);
- } else {
- fpath += this->GetFullName(config, false);
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ if (realname) {
+ fpath += this->NormalGetRealName(config);
+ } else {
+ fpath +=
+ this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact);
+ }
+ break;
+ case cmStateEnums::ImportLibraryArtifact:
+ fpath += this->GetFullName(config, cmStateEnums::ImportLibraryArtifact);
+ break;
}
return fpath;
}
@@ -2926,7 +3039,8 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName,
std::string prefix;
std::string base;
std::string suffix;
- this->GetFullNameInternal(config, false, prefix, base, suffix);
+ this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+ prefix, base, suffix);
// The library name.
name = prefix + base + suffix;
@@ -2951,7 +3065,8 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName,
// The import library name.
if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY) {
- impName = this->GetFullNameInternal(config, true);
+ impName =
+ this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
} else {
impName = "";
}
@@ -2992,7 +3107,8 @@ void cmGeneratorTarget::GetExecutableNames(std::string& name,
std::string prefix;
std::string base;
std::string suffix;
- this->GetFullNameInternal(config, false, prefix, base, suffix);
+ this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+ prefix, base, suffix);
// The executable name.
name = prefix + base + suffix;
@@ -3012,19 +3128,20 @@ void cmGeneratorTarget::GetExecutableNames(std::string& name,
#endif
// The import library name.
- impName = this->GetFullNameInternal(config, true);
+ impName =
+ this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
// The program database file name.
pdbName = this->GetPDBName(config);
}
-std::string cmGeneratorTarget::GetFullNameInternal(const std::string& config,
- bool implib) const
+std::string cmGeneratorTarget::GetFullNameInternal(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
std::string prefix;
std::string base;
std::string suffix;
- this->GetFullNameInternal(config, implib, prefix, base, suffix);
+ this->GetFullNameInternal(config, artifact, prefix, base, suffix);
return prefix + base + suffix;
}
@@ -3033,22 +3150,21 @@ const char* cmGeneratorTarget::ImportedGetLocation(
{
static std::string location;
assert(this->IsImported());
- location = this->Target->ImportedGetFullPath(config, false);
+ location = this->Target->ImportedGetFullPath(
+ config, cmStateEnums::RuntimeBinaryArtifact);
return location.c_str();
}
-std::string cmGeneratorTarget::GetFullNameImported(const std::string& config,
- bool implib) const
+std::string cmGeneratorTarget::GetFullNameImported(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
return cmSystemTools::GetFilenameName(
- this->Target->ImportedGetFullPath(config, implib));
+ this->Target->ImportedGetFullPath(config, artifact));
}
-void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
- bool implib,
- std::string& outPrefix,
- std::string& outBase,
- std::string& outSuffix) const
+void cmGeneratorTarget::GetFullNameInternal(
+ const std::string& config, cmStateEnums::ArtifactType artifact,
+ std::string& outPrefix, std::string& outBase, std::string& outSuffix) const
{
// Use just the target name for non-main target types.
if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
@@ -3061,9 +3177,12 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
return;
}
+ const bool isImportedLibraryArtifact =
+ (artifact == cmStateEnums::ImportLibraryArtifact);
+
// Return an empty name for the import library if this platform
// does not support import libraries.
- if (implib &&
+ if (isImportedLibraryArtifact &&
!this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
outPrefix = "";
outBase = "";
@@ -3076,14 +3195,16 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
this->GetType() != cmStateEnums::MODULE_LIBRARY &&
this->GetType() != cmStateEnums::EXECUTABLE) {
- implib = false;
+ artifact = cmStateEnums::RuntimeBinaryArtifact;
}
// Compute the full name for main target types.
- const char* targetPrefix = (implib ? this->GetProperty("IMPORT_PREFIX")
- : this->GetProperty("PREFIX"));
- const char* targetSuffix = (implib ? this->GetProperty("IMPORT_SUFFIX")
- : this->GetProperty("SUFFIX"));
+ const char* targetPrefix =
+ (isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX")
+ : this->GetProperty("PREFIX"));
+ const char* targetSuffix =
+ (isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX")
+ : this->GetProperty("SUFFIX"));
const char* configPostfix = CM_NULLPTR;
if (!config.empty()) {
std::string configProp = cmSystemTools::UpperCase(config);
@@ -3095,8 +3216,8 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
configPostfix = CM_NULLPTR;
}
}
- const char* prefixVar = this->Target->GetPrefixVariableInternal(implib);
- const char* suffixVar = this->Target->GetSuffixVariableInternal(implib);
+ const char* prefixVar = this->Target->GetPrefixVariableInternal(artifact);
+ const char* suffixVar = this->Target->GetSuffixVariableInternal(artifact);
// Check for language-specific default prefix and suffix.
std::string ll = this->GetLinkerLanguage(config);
@@ -3123,20 +3244,14 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
// frameworks have directory prefix but no suffix
std::string fw_prefix;
if (this->IsFrameworkOnApple()) {
- fw_prefix = this->GetOutputName(config, false);
- fw_prefix += ".";
- const char* ext = this->GetProperty("BUNDLE_EXTENSION");
- if (!ext) {
- ext = "framework";
- }
- fw_prefix += ext;
+ fw_prefix = this->GetFrameworkDirectory(config, ContentLevel);
fw_prefix += "/";
targetPrefix = fw_prefix.c_str();
targetSuffix = CM_NULLPTR;
}
if (this->IsCFBundleOnApple()) {
- fw_prefix = this->GetCFBundleDirectory(config, false);
+ fw_prefix = this->GetCFBundleDirectory(config, FullLevel);
fw_prefix += "/";
targetPrefix = fw_prefix.c_str();
targetSuffix = CM_NULLPTR;
@@ -3146,14 +3261,15 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
outPrefix = targetPrefix ? targetPrefix : "";
// Append the target name or property-specified name.
- outBase += this->GetOutputName(config, implib);
+ outBase += this->GetOutputName(config, artifact);
// Append the per-configuration postfix.
outBase += configPostfix ? configPostfix : "";
// Name shared libraries with their version number on some platforms.
if (const char* soversion = this->GetProperty("SOVERSION")) {
- if (this->GetType() == cmStateEnums::SHARED_LIBRARY && !implib &&
+ if (this->GetType() == cmStateEnums::SHARED_LIBRARY &&
+ !isImportedLibraryArtifact &&
this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) {
outBase += "-";
outBase += soversion;
@@ -3175,7 +3291,8 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
std::string prefix;
std::string base;
std::string suffix;
- this->GetFullNameInternal(config, false, prefix, base, suffix);
+ this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+ prefix, base, suffix);
std::vector<std::string> props;
std::string configUpper = cmSystemTools::UpperCase(config);
@@ -3197,6 +3314,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
{
@@ -3222,8 +3379,18 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
// were not listed in one of the other lists.
if (const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) {
flags.MacFolder = location;
+ const bool stripResources =
+ this->GlobalGenerator->ShouldStripResourcePath(this->Makefile);
if (strcmp(location, "Resources") == 0) {
flags.Type = cmGeneratorTarget::SourceFileTypeResource;
+ if (stripResources) {
+ flags.MacFolder = "";
+ }
+ } else if (cmSystemTools::StringStartsWith(location, "Resources/")) {
+ flags.Type = cmGeneratorTarget::SourceFileTypeDeepResource;
+ if (stripResources) {
+ flags.MacFolder += strlen("Resources/");
+ }
} else {
flags.Type = cmGeneratorTarget::SourceFileTypeMacContent;
}
@@ -3277,7 +3444,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const
if (cmSourceFile* sf = this->Makefile->GetSource(*it)) {
SourceFileFlags& flags = this->SourceFlagsMap[sf];
flags.MacFolder = "";
- if (!this->Makefile->PlatformIsAppleIos()) {
+ if (!this->GlobalGenerator->ShouldStripResourcePath(this->Makefile)) {
flags.MacFolder = "Resources";
}
flags.Type = cmGeneratorTarget::SourceFileTypeResource;
@@ -3806,15 +3973,14 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
<< theTarget->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str());
break;
- } else {
- propContent = consistent.second;
- continue;
}
- } else {
- // Explicitly set on target and not set in iface. Can't disagree.
+ propContent = consistent.second;
continue;
}
- } else if (impliedByUse) {
+ // Explicitly set on target and not set in iface. Can't disagree.
+ continue;
+ }
+ if (impliedByUse) {
propContent = impliedValue<PropertyType>(propContent);
if (ifaceIsSet) {
@@ -3832,43 +3998,36 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
<< "\" is in conflict.\n";
cmSystemTools::Error(e.str().c_str());
break;
- } else {
- propContent = consistent.second;
- continue;
}
- } else {
- // Implicitly set on target and not set in iface. Can't disagree.
+ propContent = consistent.second;
continue;
}
- } else {
- if (ifaceIsSet) {
- if (propInitialized) {
- std::pair<bool, PropertyType> consistent =
- consistentProperty(propContent, ifacePropContent, t);
- report += reportEntry;
- report += compatibilityAgree(t, propContent != consistent.second);
- if (!consistent.first) {
- std::ostringstream e;
- e << "The INTERFACE_" << p << " property of \""
- << theTarget->GetName() << "\" does\nnot agree with the value "
- "of "
- << p << " already determined\nfor \"" << tgt->GetName()
- << "\".\n";
- cmSystemTools::Error(e.str().c_str());
- break;
- } else {
- propContent = consistent.second;
- continue;
- }
- } else {
- report += reportEntry + "(Interface set)\n";
- propContent = ifacePropContent;
- propInitialized = true;
+ // Implicitly set on target and not set in iface. Can't disagree.
+ continue;
+ }
+ if (ifaceIsSet) {
+ if (propInitialized) {
+ std::pair<bool, PropertyType> consistent =
+ consistentProperty(propContent, ifacePropContent, t);
+ report += reportEntry;
+ report += compatibilityAgree(t, propContent != consistent.second);
+ if (!consistent.first) {
+ std::ostringstream e;
+ e << "The INTERFACE_" << p << " property of \""
+ << theTarget->GetName() << "\" does\nnot agree with the value of "
+ << p << " already determined\nfor \"" << tgt->GetName() << "\".\n";
+ cmSystemTools::Error(e.str().c_str());
+ break;
}
- } else {
- // Not set. Nothing to agree on.
+ propContent = consistent.second;
continue;
}
+ report += reportEntry + "(Interface set)\n";
+ propContent = ifacePropContent;
+ propInitialized = true;
+ } else {
+ // Not set. Nothing to agree on.
+ continue;
}
}
@@ -4277,26 +4436,31 @@ const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries(
return iface.Exists ? &iface : CM_NULLPTR;
}
-std::string cmGeneratorTarget::GetDirectory(const std::string& config,
- bool implib) const
+std::string cmGeneratorTarget::GetDirectory(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
if (this->IsImported()) {
// Return the directory from which the target is imported.
return cmSystemTools::GetFilenamePath(
- this->Target->ImportedGetFullPath(config, implib));
+ this->Target->ImportedGetFullPath(config, artifact));
}
if (OutputInfo const* info = this->GetOutputInfo(config)) {
// Return the directory in which the target will be built.
- return implib ? info->ImpDir : info->OutDir;
+ switch (artifact) {
+ case cmStateEnums::RuntimeBinaryArtifact:
+ return info->OutDir;
+ case cmStateEnums::ImportLibraryArtifact:
+ return info->ImpDir;
+ }
}
return "";
}
-bool cmGeneratorTarget::UsesDefaultOutputDir(const std::string& config,
- bool implib) const
+bool cmGeneratorTarget::UsesDefaultOutputDir(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
{
std::string dir;
- return this->ComputeOutputDir(config, implib, dir);
+ return this->ComputeOutputDir(config, artifact, dir);
}
cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
@@ -4330,8 +4494,10 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
i = this->OutputInfoMap.insert(entry).first;
// Compute output directories.
- this->ComputeOutputDir(config, false, info.OutDir);
- this->ComputeOutputDir(config, true, info.ImpDir);
+ this->ComputeOutputDir(config, cmStateEnums::RuntimeBinaryArtifact,
+ info.OutDir);
+ this->ComputeOutputDir(config, cmStateEnums::ImportLibraryArtifact,
+ info.ImpDir);
if (!this->ComputePDBOutputDir("PDB", config, info.PdbDir)) {
info.PdbDir = info.OutDir;
}
@@ -4351,14 +4517,15 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
}
bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
- bool implib, std::string& out) const
+ cmStateEnums::ArtifactType artifact,
+ std::string& out) const
{
bool usesDefaultOutputDir = false;
std::string conf = config;
// Look for a target property defining the target output directory
// based on the target type.
- std::string targetTypeName = this->GetOutputTargetType(implib);
+ std::string targetTypeName = this->GetOutputTargetType(artifact);
const char* propertyName = CM_NULLPTR;
std::string propertyNameStr = targetTypeName;
if (!propertyNameStr.empty()) {
@@ -4883,11 +5050,11 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles(
std::vector<std::string>::const_iterator it = configs.begin();
const std::string& firstConfig = *it;
- this->GetSourceFiles(files, firstConfig);
+ this->GetSourceFilesWithoutObjectLibraries(files, firstConfig);
for (; it != configs.end(); ++it) {
std::vector<cmSourceFile*> configFiles;
- this->GetSourceFiles(configFiles, *it);
+ this->GetSourceFilesWithoutObjectLibraries(configFiles, *it);
if (configFiles != files) {
std::string firstConfigFiles;
const char* sep = "";