Browse Source

AIX: Add option to archive shared libraries

Add option `CMAKE_AIX_SHARED_LIBRARY_ARCHIVE`.

There will no versions for the shared objects when this option is used.

Closes: #26033
Aditya Vidyadhar Kamath 1 năm trước cách đây
mục cha
commit
d27fe9dfba

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -109,6 +109,7 @@ Properties on Targets
 
    /prop_tgt/ADDITIONAL_CLEAN_FILES
    /prop_tgt/AIX_EXPORT_ALL_SYMBOLS
+   /prop_tgt/AIX_SHARED_LIBRARY_ARCHIVE
    /prop_tgt/ALIAS_GLOBAL
    /prop_tgt/ALIASED_TARGET
    /prop_tgt/ANDROID_ANT_ADDITIONAL_OPTIONS

+ 3 - 0
Help/manual/cmake-variables.7.rst

@@ -106,6 +106,7 @@ Variables that Provide Information
    /variable/CMAKE_SCRIPT_MODE_FILE
    /variable/CMAKE_SHARED_LIBRARY_PREFIX
    /variable/CMAKE_SHARED_LIBRARY_SUFFIX
+   /variable/CMAKE_SHARED_LIBRARY_ARCHIVE_SUFFIX
    /variable/CMAKE_SHARED_MODULE_PREFIX
    /variable/CMAKE_SHARED_MODULE_SUFFIX
    /variable/CMAKE_SIZEOF_VOID_P
@@ -360,6 +361,7 @@ Variables that Control the Build
    :maxdepth: 1
 
    /variable/CMAKE_ADSP_ROOT
+   /variable/CMAKE_AIX_SHARED_LIBRARY_ARCHIVE
    /variable/CMAKE_AIX_EXPORT_ALL_SYMBOLS
    /variable/CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS
    /variable/CMAKE_ANDROID_API
@@ -614,6 +616,7 @@ Variables for Languages
    /variable/CMAKE_LANG_COMPILER_TARGET
    /variable/CMAKE_LANG_COMPILER_VERSION
    /variable/CMAKE_LANG_CREATE_SHARED_LIBRARY
+   /variable/CMAKE_LANG_CREATE_SHARED_LIBRARY_ARCHIVE
    /variable/CMAKE_LANG_CREATE_SHARED_MODULE
    /variable/CMAKE_LANG_CREATE_STATIC_LIBRARY
    /variable/CMAKE_LANG_EXTENSIONS

+ 20 - 0
Help/prop_tgt/AIX_SHARED_LIBRARY_ARCHIVE.rst

@@ -0,0 +1,20 @@
+AIX_SHARED_LIBRARY_ARCHIVE
+--------------------------
+
+.. versionadded:: 3.31
+
+On AIX, enable creation of a shared library archive.  This places
+the shared object ``.so`` file inside an archive ``.a`` file.
+
+By default, CMake creates shared libraries on AIX as plain
+shared object ``.so`` files for consistency with other UNIX platforms.
+Alternatively, set this property to a true value to create a shared
+library archive instead, as is AIX convention.
+
+When a shared library is archived the shared object in the archive
+does not record any version information from :prop_tgt:`VERSION` or
+:prop_tgt`SOVERSION` target properties.
+
+This property defaults to :variable:`CMAKE_AIX_SHARED_LIBRARY_ARCHIVE`
+if that variable is set when a ``SHARED`` library target is created
+by :command:`add_library`.

+ 6 - 0
Help/release/dev/aix-archive-shared-libraries.rst

@@ -0,0 +1,6 @@
+aix-archive-shared-libraries
+----------------------------
+
+* On AIX, shared libraries may now be created as shared library archives.
+  See the :variable:`CMAKE_AIX_SHARED_LIBRARY_ARCHIVE` variable
+  and :prop_tgt:`AIX_SHARED_LIBRARY_ARCHIVE` target property.

+ 10 - 0
Help/variable/CMAKE_AIX_SHARED_LIBRARY_ARCHIVE.rst

@@ -0,0 +1,10 @@
+CMAKE_AIX_SHARED_LIBRARY_ARCHIVE
+--------------------------------
+
+.. versionadded:: 3.31
+
+On AIX, enable creation of shared library archives.
+
+This variable initializes the :prop_tgt:`AIX_SHARED_LIBRARY_ARCHIVE`
+target property on ``SHARED`` library targets as they are created
+by :command:`add_library`.  See that target property for details.

+ 8 - 0
Help/variable/CMAKE_LANG_CREATE_SHARED_LIBRARY_ARCHIVE.rst

@@ -0,0 +1,8 @@
+CMAKE_<LANG>_CREATE_SHARED_LIBRARY_ARCHIVE
+------------------------------------------
+
+Rule variable to create a shared library with archive.
+
+This is a rule variable that tells CMake how to create a shared
+library with an archive for the language <LANG>.  This rule variable
+is a ; delimited list of commands to run to perform the linking step.

+ 7 - 0
Help/variable/CMAKE_SHARED_LIBRARY_ARCHIVE_SUFFIX.rst

@@ -0,0 +1,7 @@
+CMAKE_SHARED_LIBRARY_ARCHIVE_SUFFIX
+-----------------------------------
+
+The suffix for archived shared libraries that you link to.
+
+The suffix to use for the end of a archive containing a
+shared library, ``.a`` on AIX.

+ 8 - 0
Modules/Platform/AIX-GNU.cmake

@@ -30,6 +30,14 @@ macro(__aix_compiler_gnu lang)
     "<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>"
     )
 
+  # Create an archive for shared library if CMAKE_AIX_SHARED_LIBRARY_ARCHIVE is used.
+  string(REPLACE " <SONAME_FLAG><TARGET_SONAME> -o <TARGET>" " -o <TARGET_SONAME>"
+    CMAKE_${lang}_CREATE_SHARED_LIBRARY_ARCHIVE "${CMAKE_${lang}_CREATE_SHARED_LIBRARY}")
+  list(APPEND CMAKE_${lang}_CREATE_SHARED_LIBRARY_ARCHIVE
+    "<CMAKE_AR> -X32_64 rc <TARGET> <TARGET_SONAME>"
+    "rm -f <TARGET_SONAME>"
+  )
+
   set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
     "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>"
     "<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")

+ 8 - 0
Modules/Platform/AIX-XL.cmake

@@ -34,6 +34,14 @@ macro(__aix_compiler_xl lang)
     "<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>"
     )
 
+  # Create an archive for shared library if CMAKE_AIX_SHARED_LIBRARY_ARCHIVE is used.
+  string(REPLACE " <SONAME_FLAG><TARGET_SONAME> -o <TARGET>" " -o <TARGET_SONAME>"
+    CMAKE_${lang}_CREATE_SHARED_LIBRARY_ARCHIVE "${CMAKE_${lang}_CREATE_SHARED_LIBRARY}")
+  list(APPEND CMAKE_${lang}_CREATE_SHARED_LIBRARY_ARCHIVE
+    "<CMAKE_AR> -X32_64 rc <TARGET> <TARGET_SONAME>"
+    "rm -f <TARGET_SONAME>"
+  )
+
   set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
     "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>"
     "<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")

+ 1 - 0
Modules/Platform/AIX.cmake

@@ -1,5 +1,6 @@
 set(CMAKE_SHARED_LIBRARY_PREFIX "lib")          # lib
 set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")          # .so
+set(CMAKE_SHARED_LIBRARY_ARCHIVE_SUFFIX ".a")   # .a
 set(CMAKE_AIX_IMPORT_FILE_PREFIX "")
 set(CMAKE_AIX_IMPORT_FILE_SUFFIX ".imp")
 set(CMAKE_DL_LIBS "-lld")

+ 1 - 0
Modules/SystemInformation.in

@@ -6,6 +6,7 @@ CMAKE_STATIC_LIBRARY_PREFIX == "${CMAKE_STATIC_LIBRARY_PREFIX}"
 CMAKE_STATIC_LIBRARY_SUFFIX == "${CMAKE_STATIC_LIBRARY_SUFFIX}"
 CMAKE_SHARED_LIBRARY_PREFIX == "${CMAKE_SHARED_LIBRARY_PREFIX}"
 CMAKE_SHARED_LIBRARY_SUFFIX == "${CMAKE_SHARED_LIBRARY_SUFFIX}"
+CMAKE_SHARED_LIBRARY_ARCHIVE_SUFFIX == "${CMAKE_SHARED_LIBRARY_ARCHIVE_SUFFIX}"
 CMAKE_SHARED_MODULE_PREFIX == "${CMAKE_SHARED_MODULE_PREFIX}"
 CMAKE_SHARED_MODULE_SUFFIX == "${CMAKE_SHARED_MODULE_SUFFIX}"
 

+ 21 - 3
Source/cmGeneratorTarget.cxx

@@ -2294,6 +2294,9 @@ std::string cmGeneratorTarget::GetCreateRuleVariable(
       return this->GetFeatureSpecificLinkRuleVariable(var, lang, config);
     }
     case cmStateEnums::SHARED_LIBRARY:
+      if (this->IsArchivedAIXSharedLibrary()) {
+        return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY_ARCHIVE";
+      }
       return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY";
     case cmStateEnums::MODULE_LIBRARY:
       return "CMAKE_" + lang + "_CREATE_SHARED_MODULE";
@@ -2938,7 +2941,7 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
   cmValue soversion = this->GetProperty("SOVERSION");
   if (!this->HasSOName(config) ||
       this->Makefile->IsOn("CMAKE_PLATFORM_NO_VERSIONED_SONAME") ||
-      this->IsFrameworkOnApple()) {
+      this->IsFrameworkOnApple() || this->IsArchivedAIXSharedLibrary()) {
     // Versioning is supported only for shared libraries and modules,
     // and then only when the platform supports an soname flag.
     version = nullptr;
@@ -2971,6 +2974,11 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
     }
     targetNames.Real += cmStrCat(targetNames.Base, components.suffix);
     targetNames.SharedObject = targetNames.Real;
+  } else if (this->IsArchivedAIXSharedLibrary()) {
+    targetNames.SharedObject =
+      cmStrCat(components.prefix, targetNames.Base, ".so");
+    targetNames.Real =
+      cmStrCat(components.prefix, targetNames.Base, components.suffix);
   } else {
     // The library's soname.
     this->ComputeVersionedName(targetNames.SharedObject, components.prefix,
@@ -3054,8 +3062,13 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
 
   // The executable name.
   targetNames.Base = components.base;
-  targetNames.Output =
-    components.prefix + targetNames.Base + components.suffix;
+
+  if (this->IsArchivedAIXSharedLibrary()) {
+    targetNames.Output = components.prefix + targetNames.Base;
+  } else {
+    targetNames.Output =
+      components.prefix + targetNames.Base + components.suffix;
+  }
 
 // The executable's real name on disk.
 #if defined(__CYGWIN__)
@@ -4801,6 +4814,11 @@ bool cmGeneratorTarget::IsFrameworkOnApple() const
   return this->Target->IsFrameworkOnApple();
 }
 
+bool cmGeneratorTarget::IsArchivedAIXSharedLibrary() const
+{
+  return this->Target->IsArchivedAIXSharedLibrary();
+}
+
 bool cmGeneratorTarget::IsImportedFrameworkFolderOnApple(
   const std::string& config) const
 {

+ 3 - 0
Source/cmGeneratorTarget.h

@@ -884,6 +884,9 @@ public:
   /** Return whether this target is a CFBundle (plugin) on Apple.  */
   bool IsCFBundleOnApple() const;
 
+  /** Return whether this target is a shared library on AIX.  */
+  bool IsArchivedAIXSharedLibrary() const;
+
   /** Assembly types. The order of the values of this enum is relevant
       because of smaller/larger comparison operations! */
   enum ManagedType

+ 5 - 1
Source/cmInstallTargetGenerator.cxx

@@ -66,7 +66,7 @@ void computeFilesToInstall(
   // Library interface name.
   std::string fromSOName;
   std::string toSOName;
-  if (library != output) {
+  if (!library.empty() && library != output) {
     haveNamelink = true;
     fromSOName = cmStrCat(fromDirConfig, library);
     toSOName = library;
@@ -403,6 +403,10 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
 
       files.From.emplace_back(std::move(from1));
       files.To.emplace_back(std::move(to1));
+    } else if (this->Target->IsArchivedAIXSharedLibrary()) {
+      // Install only the archive on AIX.
+      computeFilesToInstall(files, this->NamelinkMode, fromDirConfig,
+                            targetNames.Output, {}, targetNames.Real);
     } else {
       computeFilesToInstall(files, this->NamelinkMode, fromDirConfig,
                             targetNames.Output, targetNames.SharedObject,

+ 7 - 1
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -169,6 +169,11 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
   std::string linkRuleVar =
     cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_LIBRARY");
 
+  if (this->GeneratorTarget->IsArchivedAIXSharedLibrary()) {
+    linkRuleVar =
+      cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_LIBRARY_ARCHIVE");
+  }
+
   std::string extraFlags;
   this->GetTargetLinkFlags(extraFlags, linkLanguage);
   this->LocalGenerator->AddConfigVariableFlags(
@@ -788,7 +793,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     vars.LinkLibraries = linkLibs.c_str();
     vars.ObjectsQuoted = buildObjs.c_str();
     std::string targetOutSOName;
-    if (this->GeneratorTarget->HasSOName(this->GetConfigName())) {
+    if (this->GeneratorTarget->HasSOName(this->GetConfigName()) ||
+        this->GeneratorTarget->IsArchivedAIXSharedLibrary()) {
       vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
       targetOutSOName = this->LocalGenerator->ConvertToOutputFormat(
         this->TargetNames.SharedObject, cmOutputConverter::SHELL);

+ 2 - 1
Source/cmNinjaNormalTargetGenerator.cxx

@@ -1459,7 +1459,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
 
   cmNinjaVars symlinkVars;
   bool const symlinkNeeded =
-    (targetOutput != targetOutputReal && !gt->IsFrameworkOnApple());
+    (targetOutput != targetOutputReal && !gt->IsFrameworkOnApple() &&
+     !gt->IsArchivedAIXSharedLibrary());
   if (!symlinkNeeded) {
     vars["POST_BUILD"] = postBuildCmdLine;
   } else {

+ 11 - 1
Source/cmTarget.cxx

@@ -407,6 +407,8 @@ TargetProperty const StaticTargetProperties[] = {
   { "VS_USE_DEBUG_LIBRARIES"_s, IC::NonImportedTarget },
   // ---- OpenWatcom
   { "WATCOM_RUNTIME_LIBRARY"_s, IC::CanCompileSources },
+  // ---- AIX
+  { "AIX_SHARED_LIBRARY_ARCHIVE"_s, IC::SharedLibraryTarget },
   // -- Language
   // ---- C
   COMMON_LANGUAGE_PROPERTIES(C),
@@ -1284,6 +1286,12 @@ bool cmTarget::IsFrameworkOnApple() const
           this->IsApple() && this->GetPropertyAsBool("FRAMEWORK"));
 }
 
+bool cmTarget::IsArchivedAIXSharedLibrary() const
+{
+  return (this->GetType() == cmStateEnums::SHARED_LIBRARY && this->IsAIX() &&
+          this->GetPropertyAsBool("AIX_SHARED_LIBRARY_ARCHIVE"));
+}
+
 bool cmTarget::IsAppBundleOnApple() const
 {
   return (this->GetType() == cmStateEnums::EXECUTABLE && this->IsApple() &&
@@ -2997,7 +3005,9 @@ const char* cmTarget::GetSuffixVariableInternal(
     case cmStateEnums::SHARED_LIBRARY:
       switch (artifact) {
         case cmStateEnums::RuntimeBinaryArtifact:
-          return "CMAKE_SHARED_LIBRARY_SUFFIX";
+          return this->IsArchivedAIXSharedLibrary()
+            ? "CMAKE_SHARED_LIBRARY_ARCHIVE_SUFFIX"
+            : "CMAKE_SHARED_LIBRARY_SUFFIX";
         case cmStateEnums::ImportLibraryArtifact:
           return this->IsApple() ? "CMAKE_APPLE_IMPORT_FILE_SUFFIX"
                                  : "CMAKE_IMPORT_LIBRARY_SUFFIX";

+ 3 - 0
Source/cmTarget.h

@@ -234,6 +234,9 @@ public:
   //! Return whether this target is a shared library Framework on Apple.
   bool IsFrameworkOnApple() const;
 
+  //! Return whether to archive shared library or not on AIX.
+  bool IsArchivedAIXSharedLibrary() const;
+
   //! Return whether this target is an executable Bundle on Apple.
   bool IsAppBundleOnApple() const;
 

+ 1 - 0
Tests/CMakeLists.txt

@@ -493,6 +493,7 @@ if(BUILD_TESTING)
   ADD_TEST_MACRO(OutDir runtime/OutDir)
   ADD_TEST_MACRO(OutName exe.OutName.exe)
   ADD_TEST_MACRO(ObjectLibrary UseCshared)
+  ADD_TEST_MACRO(SharedLibraryArchive UseSLA)
   ADD_TEST_MACRO(NewlineArgs NewlineArgs)
   ADD_TEST_MACRO(SetLang SetLangX)
   ADD_TEST_MACRO(EmptyProperty EmptyProperty)

+ 5 - 0
Tests/ExportImport/Export/CMakeLists.txt

@@ -479,6 +479,9 @@ add_library(testMod1 MODULE empty.cpp)
 add_library(testMod2 MODULE empty.cpp)
 set_property(TARGET testMod2 PROPERTY BUNDLE 1)
 
+add_library(testSharedLibArchiveAIX SHARED testSharedLibArchiveAIX.c)
+set_property(TARGET testSharedLibArchiveAIX PROPERTY AIX_SHARED_LIBRARY_ARCHIVE 1)
+
 install(TARGETS testLibRequired
         EXPORT RequiredExp DESTINATION lib
         INCLUDES DESTINATION
@@ -618,6 +621,7 @@ install(
   systemlib
   testInterfaceIncludeUser
   testInterfaceIncludeUser2
+  testSharedLibArchiveAIX
   EXPORT exp
   RUNTIME DESTINATION $<1:bin>$<0:/wrong>
   LIBRARY DESTINATION $<1:lib>$<0:/wrong> NAMELINK_SKIP
@@ -695,6 +699,7 @@ export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 te
   testExeWithPluginHelper testExePluginHelperObj
   testMod1 testMod2
   testLibPerConfigDest
+  testSharedLibArchiveAIX
   NAMESPACE bld_
   APPEND FILE ExportBuildTree.cmake
   )

+ 10 - 0
Tests/ExportImport/Export/testSharedLibArchiveAIX.c

@@ -0,0 +1,10 @@
+#if defined(_WIN32) || defined(__CYGWIN__)
+#  define EXPORT __declspec(dllexport)
+#else
+#  define EXPORT
+#endif
+
+EXPORT int testSharedLibArchiveAIX(void)
+{
+  return 0;
+}

+ 2 - 0
Tests/ExportImport/Import/A/CMakeLists.txt

@@ -68,6 +68,7 @@ target_link_libraries(imp_testExe1
   exp_testLib7
   exp_testLibCycleA
   exp_testLibPerConfigDest
+  exp_testSharedLibArchiveAIX
   exp_testStaticLibWithPlugin
   )
 
@@ -123,6 +124,7 @@ target_link_libraries(imp_testExe1b
   bld_testLib7
   bld_testLibCycleA
   bld_testLibPerConfigDest
+  bld_testSharedLibArchiveAIX
   bld_testStaticLibWithPlugin
   )
 

+ 3 - 2
Tests/ExportImport/Import/A/imp_testExe1.c

@@ -11,6 +11,7 @@ extern int testLib7(void);
 extern int testLibCycleA1(void);
 extern int testLibPerConfigDest(void);
 extern int testStaticLibPlugin(void);
+extern int testSharedLibArchiveAIX(void);
 
 /* Switch a symbol between debug and optimized builds to make sure the
    proper library is found from the testLib4 link interface.  */
@@ -26,6 +27,6 @@ int main(void)
   return (testLib2() + generated_by_testExe1() + testLib3() + testLib4() +
           testLib5() + testLib6() + testLib7() + testLibCycleA1() +
           testLibPerConfigDest() + testStaticLibPlugin() +
-          generated_by_testExe3() + generated_by_testExe4() + testLib4lib() +
-          testLib4libcfg());
+          testSharedLibArchiveAIX() + generated_by_testExe3() +
+          generated_by_testExe4() + testLib4lib() + testLib4libcfg());
 }

+ 20 - 0
Tests/SharedLibraryArchive/CMakeLists.txt

@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.30)
+project(SharedLibraryArchive C)
+
+set(CMAKE_AIX_SHARED_LIBRARY_ARCHIVE 1)
+
+add_library(sla SHARED sla.c)
+get_property(aix_sla TARGET sla PROPERTY AIX_SHARED_LIBRARY_ARCHIVE)
+if(NOT aix_sla)
+  message(FATAL_ERROR "AIX_SHARED_LIBRARY_ARCHIVE not initialized on SHARED library")
+endif()
+add_custom_command(TARGET sla POST_BUILD VERBATIM
+  COMMAND ${CMAKE_COMMAND} -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -Dsla=$<TARGET_FILE:sla> -P${CMAKE_CURRENT_SOURCE_DIR}/sla-check.cmake
+  )
+
+add_executable(UseSLA use_sla.c)
+get_property(aix_sla TARGET UseSLA PROPERTY AIX_SHARED_LIBRARY_ARCHIVE)
+if(aix_sla)
+  message(FATAL_ERROR "AIX_SHARED_LIBRARY_ARCHIVE initialized on EXECUTABLE")
+endif()
+target_link_libraries(UseSLA PRIVATE sla)

+ 9 - 0
Tests/SharedLibraryArchive/sla-check.cmake

@@ -0,0 +1,9 @@
+if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+  if(NOT sla MATCHES [[/libsla\.a]])
+    message(FATAL_ERROR "sla library does not look like an archive:\n ${sla}")
+  endif()
+  execute_process(COMMAND ar t ${sla} OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE sla_members)
+  if(NOT sla_members MATCHES [[^libsla\.so]])
+    message(FATAL_ERROR "sla library archive does not have expected members:\n ${sla_members}")
+  endif()
+endif()

+ 7 - 0
Tests/SharedLibraryArchive/sla.c

@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+  int sla(void)
+{
+  return 0;
+}

+ 9 - 0
Tests/SharedLibraryArchive/use_sla.c

@@ -0,0 +1,9 @@
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+  int sla(void);
+
+int main(void)
+{
+  return sla();
+}