Archive shared library in AIX (#11850)

* Archive shared library in AIX

This code change to ensure we archive shared libraries in AIX.

The things we do are:
Archive shared library
Install archived shared library
Build all must build the archived shared library
blibpath must have the archived shared library dependency.

* Archive shared library in AIX.

Made changes as per the review comments given in the first
PR request.

They are:-
Use self.environment.machines[t.for_machine].is_aix()
Remove trial spaces
Use of val instead of internal
Changed comments wherever requested

* Space after octothorpe

* Fixed failed test case causing build break during install section

* Moved AIX specific code to AIXDynamicLinker from backend

* Fix indentation, trailing spaces, add type annotations and Linux/macOS build break

* Remove some more trailing space issues

* Fixed the wrong return type in linkers
pull/11918/head
Aditya Kamath 1 year ago committed by GitHub
parent 78b8d447ee
commit 8946bc05f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      mesonbuild/backend/ninjabackend.py
  2. 6
      mesonbuild/compilers/compilers.py
  3. 6
      mesonbuild/envconfig.py
  4. 24
      mesonbuild/linkers/linkers.py
  5. 9
      mesonbuild/minstall.py

@ -1034,6 +1034,11 @@ class NinjaBackend(backends.Backend):
elem = self.generate_link(target, outname, final_obj_list, linker, pch_objects, stdlib_args=stdlib_args)
self.generate_dependency_scan_target(target, compiled_sources, source2object, generated_source_files, fortran_order_deps)
self.add_build(elem)
#In AIX, we archive shared libraries. If the instance is a shared library, we add a command to archive the shared library
#object and create the build element.
if isinstance(target, build.SharedLibrary) and self.environment.machines[target.for_machine].is_aix():
elem = NinjaBuildElement(self.all_outputs, linker.get_archive_name(outname), 'AIX_LINKER', [outname])
self.add_build(elem)
def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool:
if mesonlib.version_compare(self.ninja_version, '<1.10.0'):
@ -2306,6 +2311,13 @@ class NinjaBackend(backends.Backend):
options = self._rsp_options(compiler)
self.add_rule(NinjaRule(rule, command, args, description, **options, extra=pool))
if self.environment.machines[for_machine].is_aix():
rule = 'AIX_LINKER{}'.format(self.get_rule_suffix(for_machine))
description = 'Archiving AIX shared library'
cmdlist = compiler.get_command_to_archive_shlib()
args = []
options = {}
self.add_rule(NinjaRule(rule, cmdlist, args, description, **options, extra=None))
args = self.environment.get_build_command() + \
['--internal',
@ -3378,6 +3390,11 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
else:
dependencies = target.get_dependencies()
internal = self.build_target_link_arguments(linker, dependencies)
#In AIX since shared libraries are archived the dependencies must
#depend on .a file with the .so and not directly on the .so file.
if self.environment.machines[target.for_machine].is_aix():
for i, val in enumerate(internal):
internal[i] = linker.get_archive_name(val)
commands += internal
# Only non-static built targets need link args and link dependencies
if not isinstance(target, build.StaticLibrary):
@ -3581,6 +3598,11 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
for t in deps.values():
# Add the first output of each target to the 'all' target so that
# they are all built
#Add archive file if shared library in AIX for build all.
if isinstance(t, build.SharedLibrary):
if self.environment.machines[t.for_machine].is_aix():
linker, stdlib_args = self.determine_linker_and_stdlib_args(t)
t.get_outputs()[0] = linker.get_archive_name(t.get_outputs()[0])
targetlist.append(os.path.join(self.get_target_dir(t), t.get_outputs()[0]))
elem = NinjaBuildElement(self.all_outputs, targ, 'phony', targetlist)

@ -938,6 +938,12 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
return self.linker.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
def get_archive_name(self, filename: str) -> str:
return self.linker.get_archive_name(filename)
def get_command_to_archive_shlib(self) -> T.List[str]:
return self.linker.get_command_to_archive_shlib()
def thread_flags(self, env: 'Environment') -> T.List[str]:
return []

@ -357,6 +357,12 @@ class MachineInfo(HoldableObject):
"""
return self.system == 'gnu'
def is_aix(self) -> bool:
"""
Machine is aix?
"""
return self.system == 'aix'
def is_irix(self) -> bool:
"""Machine is IRIX?"""
return self.system.startswith('irix')

@ -16,6 +16,7 @@ from __future__ import annotations
import abc
import os
import typing as T
import re
from .base import ArLikeLinker, RSPFileSyntax
from .. import mesonlib
@ -541,6 +542,14 @@ class DynamicLinker(metaclass=abc.ABCMeta):
suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]:
return []
def get_archive_name(self, filename: str) -> str:
#Only used by AIX.
return str()
def get_command_to_archive_shlib(self) -> T.List[str]:
#Only used by AIX.
return []
class PosixDynamicLinkerMixin:
@ -1440,6 +1449,21 @@ class AIXDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def get_allow_undefined_args(self) -> T.List[str]:
return self._apply_prefix(['-berok'])
def get_archive_name(self, filename: str) -> str:
# In AIX we allow the shared library name to have the lt_version and so_version.
# But the archive name must just be .a .
# For Example shared object can have the name libgio.so.0.7200.1 but the archive
# must have the name libgio.a having libgio.a (libgio.so.0.7200.1) in the
# archive. This regular expression is to do the same.
filename = re.sub('[.][a]([.]?([0-9]+))*([.]?([a-z]+))*', '.a', filename.replace('.so', '.a'))
return filename
def get_command_to_archive_shlib(self) -> T.List[str]:
# Archive shared library object and remove the shared library object,
# since it already exists in the archive.
command = ['ar', '-q', '-v', '$out', '$in', '&&', 'rm', '-f', '$in']
return command
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
# AIX's linker always links the whole archive: "The ld command
# processes all input files in the same manner, whether they are

@ -23,11 +23,12 @@ import shutil
import subprocess
import sys
import typing as T
import re
from . import build, coredata, environment
from .backend.backends import InstallData
from .mesonlib import (MesonException, Popen_safe, RealPathAction, is_windows,
setup_vsenv, pickle_load, is_osx, OptionKey)
is_aix, setup_vsenv, pickle_load, is_osx, OptionKey)
from .scripts import depfixer, destdir_join
from .scripts.meson_exe import run_exe
try:
@ -709,6 +710,12 @@ class Installer:
def install_targets(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None:
for t in d.targets:
# In AIX, we archive our shared libraries. When we install any package in AIX we need to
# install the archive in which the shared library exists. The below code does the same.
# We change the .so files having lt_version or so_version to archive file install.
if is_aix():
if '.so' in t.fname:
t.fname = re.sub('[.][a]([.]?([0-9]+))*([.]?([a-z]+))*', '.a', t.fname.replace('.so', '.a'))
if not self.should_install(t):
continue
if not os.path.exists(t.fname):

Loading…
Cancel
Save