AIX: Add an option to disable automatic exports from shared libraries

Since commit 0f150b69d3 (AIX: Explicitly compute shared object exports
for both XL and GNU, 2019-07-11, v3.16.0-rc1~418^2~2) we always export
all symbols from shared libraries by default.  Add a new target property
called `AIX_EXPORT_ALL_SYMBOLS` that can be explicitly set to OFF to
suppress this behavior and export no symbols by default.

Fixes: #20290
This commit is contained in:
Brad King 2020-01-30 09:10:58 -05:00
parent 67f30811ce
commit afcd9fe669
23 changed files with 102 additions and 5 deletions

View File

@ -104,6 +104,7 @@ Properties on Targets
:maxdepth: 1
/prop_tgt/ADDITIONAL_CLEAN_FILES
/prop_tgt/AIX_EXPORT_ALL_SYMBOLS
/prop_tgt/ALIASED_TARGET
/prop_tgt/ANDROID_ANT_ADDITIONAL_OPTIONS
/prop_tgt/ANDROID_API

View File

@ -323,6 +323,7 @@ Variables that Control the Build
.. toctree::
:maxdepth: 1
/variable/CMAKE_AIX_EXPORT_ALL_SYMBOLS
/variable/CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS
/variable/CMAKE_ANDROID_API
/variable/CMAKE_ANDROID_API_MIN

View File

@ -0,0 +1,12 @@
AIX_EXPORT_ALL_SYMBOLS
----------------------
On AIX, CMake automatically exports all symbols from shared libraries, and
from executables with the :prop_tgt:`ENABLE_EXPORTS` target property set.
Explicitly disable this boolean property to suppress the behavior and
export no symbols by default. In this case it is expected that the project
will use other means to export some symbols.
This property is initialized by the value of
the :variable:`CMAKE_AIX_EXPORT_ALL_SYMBOLS` variable if it is set
when a target is created.

View File

@ -0,0 +1,7 @@
aix-no-export-all
-----------------
* The :prop_tgt:`AIX_EXPORT_ALL_SYMBOLS` target property and associated
:variable:`CMAKE_AIX_EXPORT_ALL_SYMBOLS` variable were created to
optionally explicitly disbale automatic export of symbols from shared
libraries on AIX.

View File

@ -0,0 +1,6 @@
CMAKE_AIX_EXPORT_ALL_SYMBOLS
----------------------------
Default value for :prop_tgt:`AIX_EXPORT_ALL_SYMBOLS` target property.
This variable is used to initialize the property on each target as it is
created.

View File

@ -23,11 +23,11 @@ macro(__aix_compiler_gnu lang)
# Construct the export list ourselves to pass only the object files so
# that we export only the symbols actually provided by the sources.
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
"\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <OBJECTS>"
"\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
)
set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
"\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <OBJECTS>"
"\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endmacro()

View File

@ -29,12 +29,12 @@ macro(__aix_compiler_xl lang)
# Construct the export list ourselves to pass only the object files so
# that we export only the symbols actually provided by the sources.
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
"\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp${_OBJECTS}"
"\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS>${_OBJECTS}"
"<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
)
set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
"\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <OBJECTS>"
"\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
unset(_OBJECTS)

View File

@ -17,6 +17,7 @@
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
: GeneratorTarget(gt)
@ -216,6 +217,20 @@ std::string cmCommonTargetGenerator::GetManifests(const std::string& config)
return cmJoin(manifests, " ");
}
std::string cmCommonTargetGenerator::GetAIXExports(std::string const&)
{
std::string aixExports;
if (this->GeneratorTarget->Target->IsAIX()) {
if (const char* exportAll =
this->GeneratorTarget->GetProperty("AIX_EXPORT_ALL_SYMBOLS")) {
if (cmIsOff(exportAll)) {
aixExports = "-n";
}
}
}
return aixExports;
}
void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
const std::string& lang,
const char* name, bool so)

View File

@ -55,6 +55,7 @@ protected:
std::string GetDefines(const std::string& l, const std::string& config);
std::string GetIncludes(std::string const& l, const std::string& config);
std::string GetManifests(const std::string& config);
std::string GetAIXExports(std::string const& config);
std::vector<std::string> GetLinkedTargetDirectories(
const std::string& config) const;

View File

@ -196,6 +196,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
buildObjs, depends, useWatcomQuote);
std::string const& aixExports = this->GetAIXExports(this->GetConfigName());
cmRulePlaceholderExpander::RuleVariables vars;
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
@ -219,6 +221,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
cmOutputConverter::SHELL);
vars.Language = linkLanguage.c_str();
vars.AIXExports = aixExports.c_str();
vars.Objects = buildObjs.c_str();
vars.ObjectDir = objectDir.c_str();
vars.Target = target.c_str();

View File

@ -727,6 +727,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
cmOutputConverter::SHELL);
}
std::string const& aixExports = this->GetAIXExports(this->GetConfigName());
// maybe create .def file from list of objects
this->GenDefFile(real_link_commands);
@ -756,6 +758,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
vars.CMTargetType =
cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
vars.Language = linkLanguage.c_str();
vars.AIXExports = aixExports.c_str();
vars.Objects = buildObjs.c_str();
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();

View File

@ -286,6 +286,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
std::string lang = this->TargetLinkLanguage(config);
vars.Language = config.c_str();
vars.AIXExports = "$AIX_EXPORTS";
if (this->TargetLinkLanguage(config) == "Swift") {
vars.SwiftLibraryName = "$SWIFT_LIBRARY_NAME";
@ -955,6 +956,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]);
vars["MANIFESTS"] = this->GetManifests(config);
vars["AIX_EXPORTS"] = this->GetAIXExports(config);
vars["LINK_PATH"] = frameworkPath + linkPath;
std::string lwyuFlags;

View File

@ -85,6 +85,11 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
return replaceValues.ObjectsQuoted;
}
}
if (replaceValues.AIXExports) {
if (variable == "AIX_EXPORTS") {
return replaceValues.AIXExports;
}
}
if (replaceValues.Defines && variable == "DEFINES") {
return replaceValues.Defines;
}

View File

@ -36,6 +36,7 @@ public:
const char* TargetVersionMajor;
const char* TargetVersionMinor;
const char* Language;
const char* AIXExports;
const char* Objects;
const char* Target;
const char* LinkLibraries;

View File

@ -491,6 +491,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
}
if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
impl->TargetType == cmStateEnums::EXECUTABLE) {
initProp("AIX_EXPORT_ALL_SYMBOLS");
initProp("WINDOWS_EXPORT_ALL_SYMBOLS");
}

View File

@ -0,0 +1 @@
[^0]

View File

@ -0,0 +1 @@
ERROR: Undefined symbol: .AIXNotExported

View File

@ -0,0 +1,7 @@
enable_language(C)
set(CMAKE_AIX_EXPORT_ALL_SYMBOLS OFF)
add_library(AIXExportExplicitLib SHARED AIXExportExplicitLib.c)
add_executable(AIXExportExplicitMain AIXExportExplicitMain.c)
target_link_options(AIXExportExplicitLib PRIVATE LINKER:-bE:${CMAKE_CURRENT_SOURCE_DIR}/AIXExportExplicitLib.exp)
target_link_libraries(AIXExportExplicitMain PRIVATE AIXExportExplicitLib)

View File

@ -0,0 +1,8 @@
int AIXNotExported(void)
{
return 0;
}
int AIXExportedSymbol(void)
{
return 0;
}

View File

@ -0,0 +1 @@
AIXExportedSymbol

View File

@ -0,0 +1,7 @@
extern int AIXNotExported(void);
extern int AIXExportedSymbol(void);
int main(void)
{
return AIXNotExported() + AIXExportedSymbol();
}

View File

@ -55,3 +55,14 @@ if(EXPORTS)
message(SEND_ERROR "\"${EXPORTS_DEF}\" has been updated.")
endif()
endif()
function(run_AIXExportExplicit)
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/AIXExpotExplicit-build")
run_cmake(AIXExportExplicit)
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_OUTPUT_MERGE TRUE)
run_cmake_command(AIXExportExplicit-build ${CMAKE_COMMAND} --build . --config Debug)
endfunction()
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
run_AIXExportExplicit()
endif()

View File

@ -614,7 +614,10 @@ endif()
add_RunCMake_test_group(CPack "${cpack_tests}")
# add a test to make sure symbols are exported from a shared library
# for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used
add_RunCMake_test(AutoExportDll -DCMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID})
add_RunCMake_test(AutoExportDll
-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-DCMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}
)
add_RunCMake_test(AndroidMK)