Fix static archives stripping (#5905)

* Do not strip static archives

Stripping static archives without more fine-grained options (e.g. `-g`)
leads to failures such as

    ld: libfoo.a: error adding symbols: archive has no index; run ranlib to add one

because GNU strip removes *every* symbol in a static archive by default.
Given that static archives are not final build artifacts (unlike
executables and shared libraries), stripping them gains little and only
causes more edge case failures.

* Gentoo's portage only strips debug information:
  86f211e3a5/bin/estrip (L322)
* Fedora also only strips debug information:
  e9c13c6565/scripts/brp-strip-static-archive (L18)
* Debian also only does some very light stripping:
  72ed1d3261/dh_strip (L374)

Fixes #4138

* Add test case for static archive stripping
pull/5906/head
David Seifert 5 years ago committed by Jussi Pakkanen
parent c9042fc3ee
commit e19a49b895
  1. 15
      mesonbuild/backend/backends.py
  2. 27
      run_unittests.py
  3. 4
      test cases/unit/68 static archive stripping/app/appA.c
  4. 4
      test cases/unit/68 static archive stripping/app/appB.c
  5. 7
      test cases/unit/68 static archive stripping/app/meson.build
  6. 5
      test cases/unit/68 static archive stripping/lib/libA.c
  7. 1
      test cases/unit/68 static archive stripping/lib/libA.h
  8. 5
      test cases/unit/68 static archive stripping/lib/libB.c
  9. 1
      test cases/unit/68 static archive stripping/lib/libB.h
  10. 23
      test cases/unit/68 static archive stripping/lib/meson.build

@ -1089,7 +1089,20 @@ class Backend:
install_mode = t.get_custom_install_mode()
# Install the target output(s)
if isinstance(t, build.BuildTarget):
should_strip = self.get_option_for_target('strip', t)
# In general, stripping static archives is tricky and full of pitfalls.
# Wholesale stripping of static archives with a command such as
#
# strip libfoo.a
#
# is broken, as GNU's strip will remove *every* symbol in a static
# archive. One solution to this nonintuitive behaviour would be
# to only strip local/debug symbols. Unfortunately, strip arguments
# are not specified by POSIX and therefore not portable. GNU's `-g`
# option (i.e. remove debug symbols) is equivalent to Apple's `-S`.
#
# TODO: Create GNUStrip/AppleStrip/etc. hierarchy for more
# fine-grained stripping of static archives.
should_strip = not isinstance(t, build.StaticLibrary) and self.get_option_for_target('strip', t)
# Install primary build output (library/executable/jar, etc)
# Done separately because of strip/aliases/rpath
if outdirs[0] is not False:

@ -5330,6 +5330,33 @@ endian = 'little'
override_envvars={'PKG_CONFIG_PATH': ':'.join(pkg_dir)})
self.build()
@skipIfNoPkgconfig
def test_static_archive_stripping(self):
'''
Check that Meson produces valid static archives with --strip enabled
'''
with tempfile.TemporaryDirectory() as tempdirname:
testdirbase = os.path.join(self.unit_test_dir, '68 static archive stripping')
# build lib
self.new_builddir()
testdirlib = os.path.join(testdirbase, 'lib')
testlibprefix = os.path.join(tempdirname, 'libprefix')
self.init(testdirlib, extra_args=['--prefix=' + testlibprefix,
'--libdir=lib',
'--default-library=static',
'--buildtype=debug',
'--strip'], default_args=False)
self.build()
self.install(use_destdir=False)
# build executable (uses lib, fails if static archive has been stripped incorrectly)
pkg_dir = os.path.join(testlibprefix, 'lib/pkgconfig')
self.new_builddir()
self.init(os.path.join(testdirbase, 'app'),
override_envvars={'PKG_CONFIG_PATH': pkg_dir})
self.build()
@skipIfNoPkgconfig
def test_pkgconfig_formatting(self):
testdir = os.path.join(self.unit_test_dir, '38 pkgconfig format')

@ -0,0 +1,4 @@
#include <stdio.h>
#include <libA.h>
int main() { printf("The answer is: %d\n", libA_func()); }

@ -0,0 +1,4 @@
#include <stdio.h>
#include <libB.h>
int main() { printf("The answer is: %d\n", libB_func()); }

@ -0,0 +1,7 @@
project('app', ['c'])
a = dependency('test-a')
b = dependency('test-b')
executable('appA', files('appA.c'), dependencies : a)
executable('appB', files('appB.c'), dependencies : b)

@ -0,0 +1,5 @@
#include <libA.h>
static int libA_func_impl(void) { return 0; }
int libA_func(void) { return libA_func_impl(); }

@ -0,0 +1,5 @@
#include <libB.h>
static int libB_func_impl(void) { return 0; }
int libB_func(void) { return libB_func_impl(); }

@ -0,0 +1,23 @@
project('lib', ['c'])
pkg = import('pkgconfig')
a = library('test-a', files('libA.c'), install: true)
install_headers(files('libA.h'), subdir: 'libA')
pkg.generate(
a,
version: '0.0',
description: 'test library libA',
filebase: 'test-a',
name: 'test library libA',
subdirs: 'libA')
b = static_library('test-b', files('libB.c'), install: true)
install_headers(files('libB.h'), subdir: 'libB')
pkg.generate(
b,
version: '0.0',
description: 'test library libB',
filebase: 'test-b',
name: 'test library libB',
subdirs: 'libB')
Loading…
Cancel
Save