diff options
author | Brad King <brad.king@kitware.com> | 2018-04-12 15:36:06 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2018-04-12 15:36:28 (GMT) |
commit | 498be66fd7211fb782eaac8be7c2b0e50e3ab5da (patch) | |
tree | 2bf6aa9f7a8132b8585bcc53394df3802a6f34b4 /Source | |
parent | 2cdefcbe62707a82eccbc301fe34f85bb74d932a (diff) | |
parent | 312527de473692e17f2b858a87faa157c73e488f (diff) | |
download | CMake-498be66fd7211fb782eaac8be7c2b0e50e3ab5da.zip CMake-498be66fd7211fb782eaac8be7c2b0e50e3ab5da.tar.gz CMake-498be66fd7211fb782eaac8be7c2b0e50e3ab5da.tar.bz2 |
Merge topic 'add_support_for_clr_targets'
312527de47 document COMMON_LANGUAGE_RUNTIME target properties
4b7a82b4ed cmVisualStudio10TargetGenerator: set /clr compiler flag from property
20e31fb4c9 cmExportFileGenerator: add target property for managed targets
411a22706a cmGeneratorTarget: add handling of managed assemblies to HasImportLibrary()
fb433ff283 cmGeneratorTarget: Make import library checks config-aware
4c1f33961f cmGeneratorTarget: add GetManagedType() and CheckManagedType() methods
6c517a9f8d cmGeneratorTarget: add HasLanguage() as wrapper for GetLanguages()
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1916
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmExportBuildFileGenerator.cxx | 5 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 14 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 3 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 84 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 31 | ||||
-rw-r--r-- | Source/cmInstallTargetGenerator.cxx | 8 | ||||
-rw-r--r-- | Source/cmMakefileExecutableTargetGenerator.cxx | 4 | ||||
-rw-r--r-- | Source/cmMakefileLibraryTargetGenerator.cxx | 4 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmNinjaNormalTargetGenerator.cxx | 4 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 16 |
11 files changed, 151 insertions, 24 deletions
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index bbbc998..72489bf 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -224,13 +224,14 @@ void cmExportBuildFileGenerator::SetImportLocationProperty( } // Add the import library for windows DLLs. - if (target->HasImportLibrary() && + if (target->HasImportLibrary(config) && mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { std::string prop = "IMPORTED_IMPLIB"; prop += suffix; std::string value = target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact); - target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}"); + target->GetImplibGNUtoMS(config, value, value, + "${CMAKE_IMPORT_LIBRARY_SUFFIX}"); properties[prop] = value; } } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 2dcbfa0..8894d44 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -777,6 +777,20 @@ void cmExportFileGenerator::SetImportDetailProperties( properties[prop] = m.str(); } } + + // Add information if this target is a managed target + if (target->GetManagedType(config) != + cmGeneratorTarget::ManagedType::Native) { + std::string prop = "IMPORTED_COMMON_LANGUAGE_RUNTIME"; + prop += suffix; + std::string propval; + if (auto* p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) { + propval = p; + } + // TODO: make sure propval is set to non-empty string for + // CSharp targets (i.e. force ManagedType::Managed). + properties[prop] = propval; + } } template <typename T> diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 09b7faf..89ed4f0 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1675,7 +1675,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag> "executables with ENABLE_EXPORTS."); return std::string(); } - cmStateEnums::ArtifactType artifact = target->HasImportLibrary() + cmStateEnums::ArtifactType artifact = + target->HasImportLibrary(context->Config) ? cmStateEnums::ImportLibraryArtifact : cmStateEnums::RuntimeBinaryArtifact; return target->GetFullPath(context->Config, artifact); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 63bfbc6..0cb299c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -4978,6 +4978,16 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, } } + // Get information if target is managed assembly. + { + std::string linkProp = "IMPORTED_COMMON_LANGUAGE_RUNTIME"; + if (auto pc = this->GetProperty(linkProp + suffix)) { + info.Managed = this->CheckManagedType(pc); + } else if (auto p = this->GetProperty(linkProp)) { + info.Managed = this->CheckManagedType(p); + } + } + // Get the cyclic repetition count. if (this->GetType() == cmStateEnums::STATIC_LIBRARY) { std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY"; @@ -5195,6 +5205,18 @@ void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages, } } +bool cmGeneratorTarget::HasLanguage(std::string const& language, + std::string const& config, + bool exclusive) const +{ + std::set<std::string> languages; + this->GetLanguages(languages, config); + // add linker language (if it is different from compiler languages) + languages.insert(this->GetLinkerLanguage(config)); + return (languages.size() == 1 || !exclusive) && + languages.count(language) > 0; +} + void cmGeneratorTarget::ComputeLinkImplementationLanguages( const std::string& config, cmOptionalLinkImplementation& impl) const { @@ -5381,16 +5403,17 @@ std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const return ""; } -bool cmGeneratorTarget::HasImplibGNUtoMS() const +bool cmGeneratorTarget::HasImplibGNUtoMS(std::string const& config) const { - return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS"); + return this->HasImportLibrary(config) && this->GetPropertyAsBool("GNUtoMS"); } -bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& gnuName, +bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& config, + std::string const& gnuName, std::string& out, const char* newExt) const { - if (this->HasImplibGNUtoMS() && gnuName.size() > 6 && + if (this->HasImplibGNUtoMS(config) && gnuName.size() > 6 && gnuName.substr(gnuName.size() - 6) == ".dll.a") { out = gnuName.substr(0, gnuName.size() - 6); out += newExt ? newExt : ".lib"; @@ -5405,11 +5428,14 @@ bool cmGeneratorTarget::IsExecutableWithExports() const this->GetPropertyAsBool("ENABLE_EXPORTS")); } -bool cmGeneratorTarget::HasImportLibrary() const +bool cmGeneratorTarget::HasImportLibrary(std::string const& config) const { return (this->IsDLLPlatform() && (this->GetType() == cmStateEnums::SHARED_LIBRARY || - this->IsExecutableWithExports())); + this->IsExecutableWithExports()) && + // Assemblies which have only managed code do not have + // import libraries. + this->GetManagedType(config) != ManagedType::Managed); } std::string cmGeneratorTarget::GetSupportDirectory() const @@ -5462,3 +5488,49 @@ bool cmGeneratorTarget::IsCFBundleOnApple() const return (this->GetType() == cmStateEnums::MODULE_LIBRARY && this->Makefile->IsOn("APPLE") && this->GetPropertyAsBool("BUNDLE")); } + +cmGeneratorTarget::ManagedType cmGeneratorTarget::CheckManagedType( + std::string const& propval) const +{ + // The type of the managed assembly (mixed unmanaged C++ and C++/CLI, + // or only C++/CLI) does only depend on whether the property is an empty + // string or contains any value at all. In Visual Studio generators + // this propval is prepended with /clr[:] which results in: + // + // 1. propval does not exist: no /clr flag, unmanaged target, has import + // lib + // 2. empty propval: add /clr as flag, mixed unmanaged/managed + // target, has import lib + // 3. any value (safe,pure): add /clr:[propval] as flag, target with + // managed code only, no import lib + return propval.empty() ? ManagedType::Mixed : ManagedType::Managed; +} + +cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType( + const std::string& config) const +{ + // Only libraries and executables can be managed targets. + if (this->GetType() != cmStateEnums::SHARED_LIBRARY && + this->GetType() != cmStateEnums::STATIC_LIBRARY && + this->GetType() != cmStateEnums::EXECUTABLE) { + return ManagedType::Undefined; + } + + // Check imported target. + if (this->IsImported()) { + if (cmGeneratorTarget::ImportInfo const* info = + this->GetImportInfo(config)) { + return info->Managed; + } + return ManagedType::Undefined; + } + + // Check for explicitly set clr target property. + if (auto* clr = this->GetProperty("COMMON_LANGUAGE_RUNTIME")) { + return this->CheckManagedType(clr); + } + + // TODO: need to check if target is a CSharp target here. + // If yes: return ManagedType::Managed. + return ManagedType::Native; +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 2f6ce33..d4a553a 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -364,6 +364,12 @@ public: void GetLanguages(std::set<std::string>& languages, std::string const& config) const; + // Evaluate if the target uses the given language for compilation + // and/or linking. If 'exclusive' is true, 'language' is expected + // to be the only language used for the target. + bool HasLanguage(std::string const& language, std::string const& config, + bool exclusive = true) const; + void GetObjectLibrariesCMP0026( std::vector<cmGeneratorTarget*>& objlibs) const; @@ -566,17 +572,17 @@ public: std::string GetLinkerLanguage(const std::string& config) const; /** Does this target have a GNU implib to convert to MS format? */ - bool HasImplibGNUtoMS() const; + bool HasImplibGNUtoMS(std::string const& config) const; /** Convert the given GNU import library name (.dll.a) to a name with a new extension (.lib or ${CMAKE_IMPORT_LIBRARY_SUFFIX}). */ - bool GetImplibGNUtoMS(std::string const& gnuName, std::string& out, - const char* newExt = nullptr) const; + bool GetImplibGNUtoMS(std::string const& config, std::string const& gnuName, + std::string& out, const char* newExt = nullptr) const; bool IsExecutableWithExports() const; /** Return whether or not the target has a DLL import library. */ - bool HasImportLibrary() const; + bool HasImportLibrary(std::string const& config) const; /** Get a build-tree directory in which to place target support files. */ std::string GetSupportDirectory() const; @@ -597,6 +603,19 @@ public: /** Return whether this target is a CFBundle (plugin) on Apple. */ bool IsCFBundleOnApple() const; + /** Assembly types. The order of the values of this enum is relevant + because of smaller/larger comparison operations! */ + enum ManagedType + { + Undefined = 0, // target is no lib or executable + Native, // target compiles to unmanaged binary. + Mixed, // target compiles to mixed (managed and unmanaged) binary. + Managed // target compiles to managed binary. + }; + + /** Return the type of assembly this target compiles to. */ + ManagedType GetManagedType(const std::string& config) const; + struct SourceFileFlags GetTargetSourceFileFlags( const cmSourceFile* sf) const; @@ -741,10 +760,12 @@ private: { ImportInfo() : NoSOName(false) + , Managed(Native) , Multiplicity(0) { } bool NoSOName; + ManagedType Managed; unsigned int Multiplicity; std::string Location; std::string SOName; @@ -838,6 +859,8 @@ private: bool ComputePDBOutputDir(const std::string& kind, const std::string& config, std::string& out) const; + ManagedType CheckManagedType(std::string const& propval) const; + public: const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure( const std::string& config) const; diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index a9b4908..e0afa2d 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -135,7 +135,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( filesFrom.push_back(std::move(from1)); filesTo.push_back(std::move(to1)); std::string targetNameImportLib; - if (this->Target->GetImplibGNUtoMS(targetNameImport, + if (this->Target->GetImplibGNUtoMS(config, targetNameImport, targetNameImportLib)) { filesFrom.push_back(fromDirConfig + targetNameImportLib); filesTo.push_back(toDir + targetNameImportLib); @@ -201,7 +201,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( filesFrom.push_back(std::move(from1)); filesTo.push_back(std::move(to1)); std::string targetNameImportLib; - if (this->Target->GetImplibGNUtoMS(targetNameImport, + if (this->Target->GetImplibGNUtoMS(config, targetNameImport, targetNameImportLib)) { filesFrom.push_back(fromDirConfig + targetNameImportLib); filesTo.push_back(toDir + targetNameImportLib); @@ -398,7 +398,7 @@ std::string cmInstallTargetGenerator::GetInstallFilename( targetNamePDB, config); if (nameType == NameImplib) { // Use the import library name. - if (!target->GetImplibGNUtoMS(targetNameImport, fname, + if (!target->GetImplibGNUtoMS(config, targetNameImport, fname, "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) { fname = targetNameImport; } @@ -419,7 +419,7 @@ std::string cmInstallTargetGenerator::GetInstallFilename( targetNameImport, targetNamePDB, config); if (nameType == NameImplib) { // Use the import library name. - if (!target->GetImplibGNUtoMS(targetNameImport, fname, + if (!target->GetImplibGNUtoMS(config, targetNameImport, fname, "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) { fname = targetNameImport; } diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 9bbc043..1e59f44 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -477,8 +477,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathImport)); std::string implib; - if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport, - implib)) { + if (this->GeneratorTarget->GetImplibGNUtoMS( + this->ConfigName, targetFullPathImport, implib)) { exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 9299ffe..27fae04 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -641,8 +641,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathImport)); std::string implib; - if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport, - implib)) { + if (this->GeneratorTarget->GetImplibGNUtoMS( + this->ConfigName, targetFullPathImport, implib)) { libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index abe5ff3..3998823 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1402,7 +1402,7 @@ std::string cmMakefileTargetGenerator::GetLinkRule( const std::string& linkRuleVar) { std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar); - if (this->GeneratorTarget->HasImplibGNUtoMS()) { + if (this->GeneratorTarget->HasImplibGNUtoMS(this->ConfigName)) { std::string ruleVar = "CMAKE_"; ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); ruleVar += "_GNUtoMS_RULE"; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 52e3677..542bb0a 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -482,7 +482,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() const char* linkCmd = mf->GetDefinition(linkCmdVar); if (linkCmd) { std::string linkCmdStr = linkCmd; - if (this->GetGeneratorTarget()->HasImplibGNUtoMS()) { + if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) { std::string ruleVar = "CMAKE_"; ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); ruleVar += "_GNUtoMS_RULE"; @@ -881,7 +881,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() targetOutputImplib, cmOutputConverter::SHELL); vars["TARGET_IMPLIB"] = impLibPath; EnsureParentDirectoryExists(impLibPath); - if (genTarget.HasImportLibrary()) { + if (genTarget.HasImportLibrary(cfgName)) { byproducts.push_back(targetOutputImplib); } } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 3289b55..13af167 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2418,6 +2418,22 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( clOptions.AddFlag("AssemblerListingLocation", asmLocation); } } + + // check for managed C++ assembly compiler flag. This overrides any + // /clr* compiler flags which may be defined in the flags variable(s). + if (this->ProjectType != csproj) { + // TODO: add check here, if /clr was defined manually and issue + // warning that this is discouraged. + if (auto* clr = + this->GeneratorTarget->GetProperty("COMMON_LANGUAGE_RUNTIME")) { + std::string clrString = clr; + if (!clrString.empty()) { + clrString = ":" + clrString; + } + flags += " /clr" + clrString; + } + } + clOptions.Parse(flags.c_str()); clOptions.Parse(defineFlags.c_str()); std::vector<std::string> targetDefines; |