AIX: Explicitly compute executable exports for both XL and GNU

On AIX, symbols in executables must be exported in order to be visible
to modules (plugins) they load via `dlopen`.  Prior to policy `CMP0065`,
CMake linked all executables with flags to export symbols, but the NEW
behavior for that policy is to do so only for executables that have the
`ENABLE_EXPORTS` target property set.  In both cases, CMake has always
used the AIX linker option `-bexpall` option to export symbols from
executables.

This has worked fairly well with the XL compiler, but with the GNU
compiler it works only for C ABI symbols.  The reason is that `-bexpall`
does not export symbols starting in `_` but the GNU C++ ABI mangles all
symbols with a leading `_`.  Therefore we have only supported C ABI
plugins with the GNU compiler on AIX.  Some projects have tried to work
around this by replacing `-bexpall` with `-bexpfull`, but the latter
often exports symbols that we do not want exported.

Avoid using `-bexpall` for executables by instead using by our own
internal `ExportImportList` script to compute symbol export lists from
the object files to be linked into an executable.  Pass the explicitly
computed export list to the AIX linker's `-bE:...` option.  We already
do this for shared object exports.

Issue: #19163
This commit is contained in:
Brad King
2019-07-12 12:55:55 -04:00
parent 0f150b69d3
commit 9f5c2040bf
8 changed files with 45 additions and 9 deletions
+7
View File
@@ -2754,6 +2754,13 @@ std::string cmGeneratorTarget::GetCreateRuleVariable(
case cmStateEnums::MODULE_LIBRARY:
return "CMAKE_" + lang + "_CREATE_SHARED_MODULE";
case cmStateEnums::EXECUTABLE:
if (this->IsExecutableWithExports()) {
std::string linkExeWithExports =
"CMAKE_" + lang + "_LINK_EXECUTABLE_WITH_EXPORTS";
if (this->Makefile->IsDefinitionSet(linkExeWithExports)) {
return linkExeWithExports;
}
}
return "CMAKE_" + lang + "_LINK_EXECUTABLE";
default:
break;
+8 -4
View File
@@ -1515,8 +1515,10 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065(
}
CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to always add the flags
add_shlib_flags = true;
// OLD behavior is to always add the flags, except on AIX where
// we compute symbol exports if ENABLE_EXPORTS is on.
add_shlib_flags =
!(tgt.Target->IsAIX() && tgt.GetPropertyAsBool("ENABLE_EXPORTS"));
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
@@ -1525,8 +1527,10 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065(
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065));
CM_FALLTHROUGH;
case cmPolicies::NEW:
// NEW behavior is to only add the flags if ENABLE_EXPORTS is on
add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS");
// NEW behavior is to only add the flags if ENABLE_EXPORTS is on,
// except on AIX where we compute symbol exports.
add_shlib_flags =
!tgt.Target->IsAIX() && tgt.GetPropertyAsBool("ENABLE_EXPORTS");
break;
}
+11
View File
@@ -171,6 +171,7 @@ public:
bool IsGeneratorProvided;
bool HaveInstallRule;
bool IsDLLPlatform;
bool IsAIX;
bool IsAndroid;
bool IsImportedTarget;
bool ImportedGloballyVisible;
@@ -219,6 +220,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
impl->IsGeneratorProvided = false;
impl->HaveInstallRule = false;
impl->IsDLLPlatform = false;
impl->IsAIX = false;
impl->IsAndroid = false;
impl->IsImportedTarget =
(vis == VisibilityImported || vis == VisibilityImportedGlobally);
@@ -229,6 +231,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
impl->IsDLLPlatform =
!impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
// Check whether we are targeting AIX.
impl->IsAIX =
(impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "AIX");
// Check whether we are targeting an Android platform.
impl->IsAndroid =
(impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android");
@@ -1664,6 +1670,11 @@ bool cmTarget::IsDLLPlatform() const
return impl->IsDLLPlatform;
}
bool cmTarget::IsAIX() const
{
return impl->IsAIX;
}
bool cmTarget::IsImported() const
{
return impl->IsImportedTarget;
+3
View File
@@ -180,6 +180,9 @@ public:
//! Return whether or not the target is for a DLL platform.
bool IsDLLPlatform() const;
//! Return whether or not we are targeting AIX.
bool IsAIX() const;
bool IsImported() const;
bool IsImportedGloballyVisible() const;