diff options
author | Marc Chevrier <marc.chevrier@gmail.com> | 2018-10-02 15:34:57 (GMT) |
---|---|---|
committer | Marc Chevrier <marc.chevrier@gmail.com> | 2018-11-11 16:34:09 (GMT) |
commit | c4b4d8b3a67718e29edb5676273e528dab566672 (patch) | |
tree | ddb8839ae8a5a15b5ffe8dd8190cf873841475da /Source | |
parent | 724a0346f7bd424ce0e5db246cee46db9f377a6f (diff) | |
download | CMake-c4b4d8b3a67718e29edb5676273e528dab566672.zip CMake-c4b4d8b3a67718e29edb5676273e528dab566672.tar.gz CMake-c4b4d8b3a67718e29edb5676273e528dab566672.tar.bz2 |
POSITION_INDEPENDENT_CODE: Manage link flags for executables
Fixes: #14983, #16561
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 134 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 5 | ||||
-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 |
8 files changed, 197 insertions, 14 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a278a7f..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) { @@ -4299,17 +4352,18 @@ const char* getTypedProperty<const char*>( return genexInterpreter->Evaluate(value, prop).c_str(); } -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) +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> @@ -4324,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, @@ -4344,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) @@ -4386,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: @@ -4399,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, @@ -4408,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) != @@ -4552,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/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 |