diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Source/CMakeVersion.cmake | 2 | ||||
-rw-r--r-- | Source/CPack/cpack.cxx | 18 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionDAGChecker.cxx | 12 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionDAGChecker.h | 1 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 3 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 171 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 5 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.cxx | 64 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 23 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.h | 3 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 32 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 4 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 3 | ||||
-rw-r--r-- | Source/cmPolicies.h | 7 | ||||
-rw-r--r-- | Source/cmQtAutoGenGlobalInitializer.cxx | 185 | ||||
-rw-r--r-- | Source/cmQtAutoGenGlobalInitializer.h | 47 | ||||
-rw-r--r-- | Source/cmQtAutoGenInitializer.cxx | 32 | ||||
-rw-r--r-- | Source/cmQtAutoGenInitializer.h | 10 |
19 files changed, 529 insertions, 95 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index ded21bc..9aebfa7 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -320,6 +320,8 @@ set(SRCS cmQtAutoGen.h cmQtAutoGenerator.cxx cmQtAutoGenerator.h + cmQtAutoGenGlobalInitializer.cxx + cmQtAutoGenGlobalInitializer.h cmQtAutoGenInitializer.cxx cmQtAutoGenInitializer.h cmQtAutoGeneratorMocUic.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3671d53..19e2da7 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 13) -set(CMake_VERSION_PATCH 20181109) +set(CMake_VERSION_PATCH 20181113) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index c083945..7cf69fc 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -21,6 +21,7 @@ #include "cmCPackLog.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" +#include "cmDocumentationFormatter.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmStateSnapshot.h" @@ -358,8 +359,21 @@ int main(int argc, char const* const* argv) cpackGenerator->SetTraceExpand(traceExpand); } else { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, - "Cannot initialize CPack generator: " << gen - << std::endl); + "Could not create CPack generator: " << gen + << std::endl); + // Print out all the valid generators + cmDocumentation generatorDocs; + std::vector<cmDocumentationEntry> v; + for (auto const& g : generators.GetGeneratorsList()) { + cmDocumentationEntry e; + e.Name = g.first; + e.Brief = g.second; + v.push_back(std::move(e)); + } + generatorDocs.SetSection("Generators", v); + std::cerr << "\n"; + generatorDocs.PrintDocumentation(cmDocumentation::ListGenerators, + std::cerr); parsed = 0; } diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 8d57441..56eb2bf 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -166,6 +166,18 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression() return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL"; } +bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression() +{ + const cmGeneratorExpressionDAGChecker* top = this; + const cmGeneratorExpressionDAGChecker* parent = this->Parent; + while (parent) { + top = parent; + parent = parent->Parent; + } + + return top->Property == "INTERFACE_POSITION_INDEPENDENT_CODE"; +} + bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries( cmGeneratorTarget const* tgt) { diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index a5134c3..1525c39 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -66,6 +66,7 @@ struct cmGeneratorExpressionDAGChecker const std::string& expr); bool EvaluatingGenexExpression(); + bool EvaluatingPICExpression(); bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr); #define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index f901215..49b97fb 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1225,7 +1225,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode const char* prop = target->GetProperty(propertyName); if (dagCheckerParent) { - if (dagCheckerParent->EvaluatingGenexExpression()) { + if (dagCheckerParent->EvaluatingGenexExpression() || + dagCheckerParent->EvaluatingPICExpression()) { // No check required. } else if (dagCheckerParent->EvaluatingLinkLibraries()) { #define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \ diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1663400..0b28d1e 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -495,6 +495,36 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature, return this->LocalGenerator->GetFeature(feature, config); } +const char* cmGeneratorTarget::GetLinkPIEProperty( + const std::string& config) const +{ + static std::string PICValue; + + PICValue = this->GetLinkInterfaceDependentStringAsBoolProperty( + "POSITION_INDEPENDENT_CODE", config); + + if (PICValue == "(unset)") { + // POSITION_INDEPENDENT_CODE is not set + return nullptr; + } + + switch (this->GetPolicyStatusCMP0083()) { + case cmPolicies::WARN: { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0083); + this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + CM_FALLTHROUGH; + } + case cmPolicies::OLD: + return nullptr; + default: + // nothing to do + break; + } + + return PICValue.c_str(); +} + bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, std::string const& config) const { @@ -4237,6 +4267,29 @@ void cmGeneratorTarget::CheckPropertyCompatibility( } } +template <typename PropertyType> +std::string valueAsString(PropertyType); +template <> +std::string valueAsString<bool>(bool value) +{ + return value ? "TRUE" : "FALSE"; +} +template <> +std::string valueAsString<const char*>(const char* value) +{ + return value ? value : "(unset)"; +} +template <> +std::string valueAsString<std::string>(std::string value) +{ + return value; +} +template <> +std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/) +{ + return "(unset)"; +} + std::string compatibilityType(CompatibleType t) { switch (t) { @@ -4268,34 +4321,49 @@ std::string compatibilityAgree(CompatibleType t, bool dominant) } template <typename PropertyType> -PropertyType getTypedProperty(cmGeneratorTarget const* tgt, - const std::string& prop); +PropertyType getTypedProperty( + cmGeneratorTarget const* tgt, const std::string& prop, + cmGeneratorExpressionInterpreter* genexInterpreter = nullptr); template <> bool getTypedProperty<bool>(cmGeneratorTarget const* tgt, - const std::string& prop) + const std::string& prop, + cmGeneratorExpressionInterpreter* genexInterpreter) { - return tgt->GetPropertyAsBool(prop); -} + if (genexInterpreter == nullptr) { + return tgt->GetPropertyAsBool(prop); + } -template <> -const char* getTypedProperty<const char*>(cmGeneratorTarget const* tgt, - const std::string& prop) -{ - return tgt->GetProperty(prop); + const char* value = tgt->GetProperty(prop); + return cmSystemTools::IsOn(genexInterpreter->Evaluate(value, prop)); } -template <typename PropertyType> -std::string valueAsString(PropertyType); template <> -std::string valueAsString<bool>(bool value) +const char* getTypedProperty<const char*>( + cmGeneratorTarget const* tgt, const std::string& prop, + cmGeneratorExpressionInterpreter* genexInterpreter) { - return value ? "TRUE" : "FALSE"; + const char* value = tgt->GetProperty(prop); + + if (genexInterpreter == nullptr) { + return value; + } + + return genexInterpreter->Evaluate(value, prop).c_str(); } + template <> -std::string valueAsString<const char*>(const char* value) +std::string getTypedProperty<std::string>( + cmGeneratorTarget const* tgt, const std::string& prop, + cmGeneratorExpressionInterpreter* genexInterpreter) { - return value ? value : "(unset)"; + const char* value = tgt->GetProperty(prop); + + if (genexInterpreter == nullptr) { + return valueAsString(value); + } + + return genexInterpreter->Evaluate(value, prop); } template <typename PropertyType> @@ -4310,6 +4378,12 @@ const char* impliedValue<const char*>(const char* /*unused*/) { return ""; } +template <> +std::string impliedValue<std::string>( + std::string /*unused*/) // NOLINT(clang-tidy) +{ + return std::string(); +} template <typename PropertyType> std::pair<bool, PropertyType> consistentProperty(PropertyType lhs, @@ -4330,6 +4404,13 @@ std::pair<bool, const char*> consistentStringProperty(const char* lhs, return std::make_pair(b, b ? lhs : nullptr); } +std::pair<bool, std::string> consistentStringProperty(const std::string& lhs, + const std::string& rhs) +{ + const bool b = lhs == rhs; + return std::make_pair(b, b ? lhs : valueAsString(nullptr)); +} + std::pair<bool, const char*> consistentNumberProperty(const char* lhs, const char* rhs, CompatibleType t) @@ -4372,9 +4453,10 @@ std::pair<bool, const char*> consistentProperty(const char* lhs, const char* const null_ptr = nullptr; switch (t) { - case BoolType: - assert(false && "consistentProperty for strings called with BoolType"); - return std::pair<bool, const char*>(false, null_ptr); + case BoolType: { + bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs); + return std::make_pair(same, same ? lhs : nullptr); + } case StringType: return consistentStringProperty(lhs, rhs); case NumberMinType: @@ -4385,6 +4467,40 @@ std::pair<bool, const char*> consistentProperty(const char* lhs, return std::pair<bool, const char*>(false, null_ptr); } +std::pair<bool, std::string> consistentProperty(const std::string& lhs, + const std::string& rhs, + CompatibleType t) +{ + const std::string null_ptr = valueAsString(nullptr); + + if (lhs == null_ptr && rhs == null_ptr) { + return std::make_pair(true, lhs); + } + if (lhs == null_ptr) { + return std::make_pair(true, rhs); + } + if (rhs == null_ptr) { + return std::make_pair(true, lhs); + } + + switch (t) { + case BoolType: { + bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs); + return std::make_pair(same, same ? lhs : null_ptr); + } + case StringType: + return consistentStringProperty(lhs, rhs); + case NumberMinType: + case NumberMaxType: { + auto value = consistentNumberProperty(lhs.c_str(), rhs.c_str(), t); + return std::make_pair( + value.first, value.first ? std::string(value.second) : null_ptr); + } + } + assert(false && "Unreachable!"); + return std::pair<bool, std::string>(false, null_ptr); +} + template <typename PropertyType> PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, const std::string& p, @@ -4394,6 +4510,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, PropertyType* /*unused*/) { PropertyType propContent = getTypedProperty<PropertyType>(tgt, p); + std::vector<std::string> headPropKeys = tgt->GetPropertyKeys(); const bool explicitlySet = std::find(headPropKeys.begin(), headPropKeys.end(), p) != @@ -4423,6 +4540,11 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, } std::string interfaceProperty = "INTERFACE_" + p; + std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter( + p == "POSITION_INDEPENDENT_CODE" ? new cmGeneratorExpressionInterpreter( + tgt->GetLocalGenerator(), config, tgt) + : nullptr); + for (cmGeneratorTarget const* theTarget : deps) { // An error should be reported if one dependency // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other @@ -4434,8 +4556,8 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, const bool ifaceIsSet = std::find(propKeys.begin(), propKeys.end(), interfaceProperty) != propKeys.end(); - PropertyType ifacePropContent = - getTypedProperty<PropertyType>(theTarget, interfaceProperty); + PropertyType ifacePropContent = getTypedProperty<PropertyType>( + theTarget, interfaceProperty, genexInterpreter.get()); std::string reportEntry; if (ifaceIsSet) { @@ -4533,6 +4655,13 @@ bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty( BoolType, nullptr); } +std::string cmGeneratorTarget::GetLinkInterfaceDependentStringAsBoolProperty( + const std::string& p, const std::string& config) const +{ + return checkInterfacePropertyCompatibility<std::string>( + this, p, config, "FALSE", BoolType, nullptr); +} + const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty( const std::string& p, const std::string& config) const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 5e7cf12..52defee 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -173,6 +173,8 @@ public: const char* GetFeature(const std::string& feature, const std::string& config) const; + const char* GetLinkPIEProperty(const std::string& config) const; + bool IsIPOEnabled(std::string const& lang, std::string const& config) const; bool IsLinkInterfaceDependentBoolProperty(const std::string& p, @@ -789,6 +791,9 @@ private: cmHeadToLinkInterfaceMap& GetHeadToLinkInterfaceUsageRequirementsMap( std::string const& config) const; + std::string GetLinkInterfaceDependentStringAsBoolProperty( + const std::string& p, const std::string& config) const; + // Cache import information from properties for each configuration. struct ImportInfo { diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index cf85473..2805395 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -34,8 +34,6 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmQtAutoGen.h" -#include "cmQtAutoGenInitializer.h" #include "cmSourceFile.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -46,6 +44,7 @@ #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cmCryptoHash.h" +# include "cmQtAutoGenGlobalInitializer.h" # include "cm_jsoncpp_value.h" # include "cm_jsoncpp_writer.h" #endif @@ -1469,64 +1468,11 @@ bool cmGlobalGenerator::ComputeTargetDepends() bool cmGlobalGenerator::QtAutoGen() { #ifdef CMAKE_BUILD_WITH_CMAKE - std::vector<std::unique_ptr<cmQtAutoGenInitializer>> autogenInits; - - for (cmLocalGenerator* localGen : this->LocalGenerators) { - const std::vector<cmGeneratorTarget*>& targets = - localGen->GetGeneratorTargets(); - // Find targets that require AUTOGEN processing - for (cmGeneratorTarget* target : targets) { - if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { - continue; - } - if (target->GetType() != cmStateEnums::EXECUTABLE && - target->GetType() != cmStateEnums::STATIC_LIBRARY && - target->GetType() != cmStateEnums::SHARED_LIBRARY && - target->GetType() != cmStateEnums::MODULE_LIBRARY && - target->GetType() != cmStateEnums::OBJECT_LIBRARY) { - continue; - } - if (target->IsImported()) { - continue; - } - - const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC"); - const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC"); - const bool rccEnabled = target->GetPropertyAsBool("AUTORCC"); - if (!mocEnabled && !uicEnabled && !rccEnabled) { - continue; - } - - auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target); - // don't do anything if there is no Qt4 or Qt5Core (which contains moc) - if (qtVersion.Major != 4 && qtVersion.Major != 5) { - continue; - } - - autogenInits.emplace_back(cm::make_unique<cmQtAutoGenInitializer>( - target, mocEnabled, uicEnabled, rccEnabled, qtVersion)); - } - } - - if (!autogenInits.empty()) { - // Initialize custom targets - for (auto& autoGen : autogenInits) { - if (!autoGen->InitCustomTargets()) { - return false; - } - } - - // Setup custom targets - for (auto& autoGen : autogenInits) { - if (!autoGen->SetupCustomTargets()) { - return false; - } - autoGen.reset(nullptr); - } - } -#endif - + cmQtAutoGenGlobalInitializer initializer(this->LocalGenerators); + return initializer.generate(); +#else return true; +#endif } cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer( diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index b7a361e..8a38f9b 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1755,6 +1755,26 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( } } +void cmGlobalXCodeGenerator::AddPositionIndependentLinkAttribute( + cmGeneratorTarget* target, cmXCodeObject* buildSettings, + const std::string& configName) +{ + // For now, only EXECUTABLE is concerned + if (target->GetType() != cmStateEnums::EXECUTABLE) { + return; + } + + const char* PICValue = target->GetLinkPIEProperty(configName); + if (PICValue == nullptr) { + // POSITION_INDEPENDENT_CODE is not set + return; + } + + buildSettings->AddAttribute( + "LD_NO_PIE", + this->CreateString(cmSystemTools::IsOn(PICValue) ? "NO" : "YES")); +} + void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, cmXCodeObject* buildSettings, const std::string& configName) @@ -1806,6 +1826,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue)); } + // Handle PIE linker configuration + this->AddPositionIndependentLinkAttribute(gtgt, buildSettings, configName); + // Add define flags this->CurrentLocalGenerator->AppendFlags( defFlags, this->CurrentMakefile->GetDefineFlags()); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 62f7030..9b0d4fe 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -171,6 +171,9 @@ private: const std::string& configName); cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt); void AddDependAndLinkInformation(cmXCodeObject* target); + void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target, + cmXCodeObject* buildSettings, + const std::string& configName); void CreateBuildSettings(cmGeneratorTarget* gtgt, cmXCodeObject* buildSettings, const std::string& buildType); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index a703f4d..da48950 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1201,6 +1201,8 @@ void cmLocalGenerator::GetTargetFlags( break; } + this->AppendPositionIndependentLinkerFlags(linkFlags, target, config, + linkLanguage); this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage); } @@ -2027,6 +2029,36 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, } } +void cmLocalGenerator::AppendPositionIndependentLinkerFlags( + std::string& flags, cmGeneratorTarget* target, const std::string& config, + const std::string& lang) +{ + // For now, only EXECUTABLE is concerned + if (target->GetType() != cmStateEnums::EXECUTABLE) { + return; + } + + const char* PICValue = target->GetLinkPIEProperty(config); + if (PICValue == nullptr) { + // POSITION_INDEPENDENT_CODE is not set + return; + } + + std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_"; + name += cmSystemTools::IsOn(PICValue) ? "PIE" : "NO_PIE"; + + auto pieFlags = this->Makefile->GetSafeDefinition(name); + if (pieFlags.empty()) { + return; + } + + std::vector<std::string> flagsList; + cmSystemTools::ExpandListArgument(pieFlags, flagsList); + for (const auto& flag : flagsList) { + this->AppendFlagEscape(flags, flag); + } +} + void cmLocalGenerator::AppendCompileOptions(std::string& options, const char* options_list, const char* regex) const diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 3dd6929..2fa0070 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -126,6 +126,10 @@ public: void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, const std::string& config, const std::string& lang); + void AppendPositionIndependentLinkerFlags(std::string& flags, + cmGeneratorTarget* target, + const std::string& config, + const std::string& lang); ///! Get the include flags for the current makefile and language std::string GetIncludeFlags(const std::vector<std::string>& includes, cmGeneratorTarget* target, diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 3c46784..9acae49 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -97,6 +97,9 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags( this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage); // LINK_OPTIONS are escaped. this->LocalGenerator->AppendCompileOptions(flags, opts); + + this->LocalGenerator->AppendPositionIndependentLinkerFlags( + flags, this->GeneratorTarget, this->ConfigName, linkLanguage); } void cmMakefileTargetGenerator::CreateRuleFile() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 5c27124..52ef470 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -244,7 +244,9 @@ class cmMakefile; SELECT(POLICY, CMP0082, \ "Install rules from add_subdirectory() are interleaved with those " \ "in caller.", \ - 3, 14, 0, cmPolicies::WARN) + 3, 14, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0083, "Add PIE options when linking executable.", 3, 14, \ + 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -271,7 +273,8 @@ class cmMakefile; F(CMP0069) \ F(CMP0073) \ F(CMP0076) \ - F(CMP0081) + F(CMP0081) \ + F(CMP0083) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx new file mode 100644 index 0000000..5470ec3 --- /dev/null +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -0,0 +1,185 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoGenGlobalInitializer.h" +#include "cmQtAutoGen.h" +#include "cmQtAutoGenInitializer.h" + +#include "cmAlgorithms.h" +#include "cmCustomCommandLines.h" +#include "cmGeneratorTarget.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmState.h" +#include "cmStateTypes.h" +#include "cmSystemTools.h" +#include "cmTarget.h" + +#include <memory> +#include <utility> + +cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( + std::vector<cmLocalGenerator*> const& localGenerators) +{ + for (cmLocalGenerator* localGen : localGenerators) { + // Detect global autogen and autorcc target names + bool globalAutoGenTarget = false; + bool globalAutoRccTarget = false; + { + cmMakefile* makefile = localGen->GetMakefile(); + // Detect global autogen target name + if (cmSystemTools::IsOn( + makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET"))) { + std::string targetName = + makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET_NAME"); + if (targetName.empty()) { + targetName = "autogen"; + } + GlobalAutoGenTargets_.emplace(localGen, std::move(targetName)); + globalAutoGenTarget = true; + } + + // Detect global autorcc target name + if (cmSystemTools::IsOn( + makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET"))) { + std::string targetName = + makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET_NAME"); + if (targetName.empty()) { + targetName = "autorcc"; + } + GlobalAutoRccTargets_.emplace(localGen, std::move(targetName)); + globalAutoRccTarget = true; + } + } + + // Find targets that require AUTOMOC/UIC/RCC processing + for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) { + // Process only certain target types + switch (target->GetType()) { + case cmStateEnums::EXECUTABLE: + case cmStateEnums::STATIC_LIBRARY: + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::OBJECT_LIBRARY: + // Process target + break; + default: + // Don't process target + continue; + } + if (target->IsImported()) { + // Don't process target + continue; + } + + bool const moc = target->GetPropertyAsBool("AUTOMOC"); + bool const uic = target->GetPropertyAsBool("AUTOUIC"); + bool const rcc = target->GetPropertyAsBool("AUTORCC"); + if (moc || uic || rcc) { + // We support Qt4 and Qt5 + auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target); + if ((qtVersion.Major == 4) || (qtVersion.Major == 5)) { + // Create autogen target initializer + Initializers_.emplace_back(cm::make_unique<cmQtAutoGenInitializer>( + this, target, qtVersion, moc, uic, rcc, globalAutoGenTarget, + globalAutoRccTarget)); + } + } + } + } +} + +cmQtAutoGenGlobalInitializer::~cmQtAutoGenGlobalInitializer() +{ +} + +void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget( + cmLocalGenerator* localGen, std::string const& name, + std::string const& comment) +{ + // Test if the target already exists + if (localGen->FindGeneratorTargetToUse(name) == nullptr) { + cmMakefile* makefile = localGen->GetMakefile(); + + // Create utility target + cmTarget* target = makefile->AddUtilityCommand( + name, cmMakefile::TargetOrigin::Generator, true, + makefile->GetHomeOutputDirectory().c_str() /*work dir*/, + std::vector<std::string>() /*output*/, + std::vector<std::string>() /*depends*/, cmCustomCommandLines(), false, + comment.c_str()); + localGen->AddGeneratorTarget(new cmGeneratorTarget(target, localGen)); + + // Set FOLDER property in the target + { + char const* folder = + makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); + if (folder != nullptr) { + target->SetProperty("FOLDER", folder); + } + } + } +} + +void cmQtAutoGenGlobalInitializer::AddToGlobalAutoGen( + cmLocalGenerator* localGen, std::string const& targetName) +{ + auto it = GlobalAutoGenTargets_.find(localGen); + if (it != GlobalAutoGenTargets_.end()) { + cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second); + if (target != nullptr) { + target->Target->AddUtility(targetName, localGen->GetMakefile()); + } + } +} + +void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc( + cmLocalGenerator* localGen, std::string const& targetName) +{ + auto it = GlobalAutoRccTargets_.find(localGen); + if (it != GlobalAutoRccTargets_.end()) { + cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second); + if (target != nullptr) { + target->Target->AddUtility(targetName, localGen->GetMakefile()); + } + } +} + +bool cmQtAutoGenGlobalInitializer::generate() +{ + return (InitializeCustomTargets() && SetupCustomTargets()); +} + +bool cmQtAutoGenGlobalInitializer::InitializeCustomTargets() +{ + // Initialize global autogen targets + { + std::string const comment = "Global AUTOGEN target"; + for (auto const& pair : GlobalAutoGenTargets_) { + GetOrCreateGlobalTarget(pair.first, pair.second, comment); + } + } + // Initialize global autorcc targets + { + std::string const comment = "Global AUTORCC target"; + for (auto const& pair : GlobalAutoRccTargets_) { + GetOrCreateGlobalTarget(pair.first, pair.second, comment); + } + } + // Initialize per target autogen targets + for (auto& initializer : Initializers_) { + if (!initializer->InitCustomTargets()) { + return false; + } + } + return true; +} + +bool cmQtAutoGenGlobalInitializer::SetupCustomTargets() +{ + for (auto& initializer : Initializers_) { + if (!initializer->SetupCustomTargets()) { + return false; + } + } + return true; +} diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h new file mode 100644 index 0000000..9e6bac0 --- /dev/null +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -0,0 +1,47 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmQtAutoGenGlobalInitializer_h +#define cmQtAutoGenGlobalInitializer_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <map> +#include <memory> // IWYU pragma: keep +#include <string> +#include <vector> + +class cmLocalGenerator; +class cmQtAutoGenInitializer; + +/// @brief Initializes the QtAutoGen generators +class cmQtAutoGenGlobalInitializer +{ +public: + cmQtAutoGenGlobalInitializer( + std::vector<cmLocalGenerator*> const& localGenerators); + ~cmQtAutoGenGlobalInitializer(); + + bool generate(); + +private: + friend class cmQtAutoGenInitializer; + + bool InitializeCustomTargets(); + bool SetupCustomTargets(); + + void GetOrCreateGlobalTarget(cmLocalGenerator* localGen, + std::string const& name, + std::string const& comment); + + void AddToGlobalAutoGen(cmLocalGenerator* localGen, + std::string const& targetName); + void AddToGlobalAutoRcc(cmLocalGenerator* localGen, + std::string const& targetName); + +private: + std::vector<std::unique_ptr<cmQtAutoGenInitializer>> Initializers_; + std::map<cmLocalGenerator*, std::string> GlobalAutoGenTargets_; + std::map<cmLocalGenerator*, std::string> GlobalAutoRccTargets_; +}; + +#endif diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index a213c84..793c0b2 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGenInitializer.h" #include "cmQtAutoGen.h" +#include "cmQtAutoGenGlobalInitializer.h" #include "cmAlgorithms.h" #include "cmCustomCommand.h" @@ -174,17 +175,19 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin, return cycle; } -cmQtAutoGenInitializer::cmQtAutoGenInitializer(cmGeneratorTarget* target, - bool mocEnabled, - bool uicEnabled, - bool rccEnabled, - IntegerVersion const& qtVersion) - : Target(target) +cmQtAutoGenInitializer::cmQtAutoGenInitializer( + cmQtAutoGenGlobalInitializer* globalInitializer, cmGeneratorTarget* target, + IntegerVersion const& qtVersion, bool mocEnabled, bool uicEnabled, + bool rccEnabled, bool globalAutogenTarget, bool globalAutoRccTarget) + : GlobalInitializer(globalInitializer) + , Target(target) , QtVersion(qtVersion) { + AutogenTarget.GlobalTarget = globalAutogenTarget; Moc.Enabled = mocEnabled; Uic.Enabled = uicEnabled; Rcc.Enabled = rccEnabled; + Rcc.GlobalTarget = globalAutoRccTarget; } bool cmQtAutoGenInitializer::InitCustomTargets() @@ -882,6 +885,10 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() if (!this->AutogenTarget.DependFiles.empty()) { usePRE_BUILD = false; } + // Cannot use PRE_BUILD when a global autogen target is in place + if (AutogenTarget.GlobalTarget) { + usePRE_BUILD = false; + } } // Create the autogen target/command if (usePRE_BUILD) { @@ -961,6 +968,12 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Add autogen target to the origin target dependencies this->Target->Target->AddUtility(this->AutogenTarget.Name, makefile); + + // Add autogen target to the global autogen target dependencies + if (this->AutogenTarget.GlobalTarget) { + this->GlobalInitializer->AddToGlobalAutoGen(localGen, + this->AutogenTarget.Name); + } } return true; @@ -1004,7 +1017,7 @@ bool cmQtAutoGenInitializer::InitRccTargets() std::string ccComment = "Automatic RCC for "; ccComment += FileProjectRelativePath(makefile, qrc.QrcFile); - if (qrc.Generated) { + if (qrc.Generated || this->Rcc.GlobalTarget) { // Create custom rcc target std::string ccName; { @@ -1035,6 +1048,11 @@ bool cmQtAutoGenInitializer::InitRccTargets() } // Add autogen target to the origin target dependencies this->Target->Target->AddUtility(ccName, makefile); + + // Add autogen target to the global autogen target dependencies + if (this->Rcc.GlobalTarget) { + this->GlobalInitializer->AddToGlobalAutoRcc(localGen, ccName); + } } else { // Create custom rcc command { diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 1d3947b..53ad571 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -13,6 +13,7 @@ class cmGeneratorTarget; class cmTarget; +class cmQtAutoGenGlobalInitializer; /// @brief Initializes the QtAutoGen generators class cmQtAutoGenInitializer : public cmQtAutoGen @@ -46,9 +47,11 @@ public: public: static IntegerVersion GetQtVersion(cmGeneratorTarget const* target); - cmQtAutoGenInitializer(cmGeneratorTarget* target, bool mocEnabled, + cmQtAutoGenInitializer(cmQtAutoGenGlobalInitializer* globalInitializer, + cmGeneratorTarget* target, + IntegerVersion const& qtVersion, bool mocEnabled, bool uicEnabled, bool rccEnabled, - IntegerVersion const& qtVersion); + bool globalAutogenTarget, bool globalAutoRccTarget); bool InitCustomTargets(); bool SetupCustomTargets(); @@ -76,6 +79,7 @@ private: std::string& errorMessage); private: + cmQtAutoGenGlobalInitializer* GlobalInitializer; cmGeneratorTarget* Target; // Configuration @@ -100,6 +104,7 @@ private: struct { std::string Name; + bool GlobalTarget = false; // Settings std::string Parallel; // Configuration files @@ -148,6 +153,7 @@ private: struct { bool Enabled = false; + bool GlobalTarget = false; std::string Executable; std::vector<std::string> ListOptions; std::vector<Qrc> Qrcs; |