Merge pull request #856 from centricular/static_library_pic

Add cross-platform PIC support for static libraries
pull/852/head
Jussi Pakkanen 8 years ago committed by GitHub
commit 4781f471c2
  1. 2
      mesonbuild/backend/backends.py
  2. 36
      mesonbuild/build.py
  3. 13
      mesonbuild/compilers.py
  4. 5
      test cases/common/62 exe static shared/meson.build
  5. 7
      test cases/common/62 exe static shared/prog.c
  6. 7
      test cases/common/62 exe static shared/shlib2.c
  7. 12
      test cases/common/62 exe static shared/subdir/exports.h
  8. 11
      test cases/common/62 exe static shared/subdir/shlib.c
  9. 11
      test cases/failing/33 exe static shared/meson.build
  10. 10
      test cases/failing/33 exe static shared/prog.c
  11. 16
      test cases/failing/33 exe static shared/shlib2.c
  12. 3
      test cases/failing/33 exe static shared/stat.c

@ -341,6 +341,8 @@ class Backend():
commands += compiler.get_werror_args() commands += compiler.get_werror_args()
if isinstance(target, build.SharedLibrary): if isinstance(target, build.SharedLibrary):
commands += compiler.get_pic_args() commands += compiler.get_pic_args()
if isinstance(target, build.StaticLibrary) and target.pic:
commands += compiler.get_pic_args()
for dep in target.get_external_deps(): for dep in target.get_external_deps():
# Cflags required by external deps might have UNIX-specific flags, # Cflags required by external deps might have UNIX-specific flags,
# so filter them out if needed # so filter them out if needed

@ -44,12 +44,19 @@ known_basic_kwargs = {'install' : True,
'native' : True, 'native' : True,
} }
known_shlib_kwargs = known_basic_kwargs.copy() # These contain kwargs supported by both static and shared libraries. These are
known_shlib_kwargs.update({'version' : True, # combined here because a library() call might be shared_library() or
'soversion' : True, # static_library() at runtime based on the configuration.
'name_prefix' : True, # FIXME: Find a way to pass that info down here so we can have proper target
'name_suffix' : True, # kwargs checking when specifically using shared_library() or static_library().
'vs_module_defs' : True}) known_lib_kwargs = known_basic_kwargs.copy()
known_lib_kwargs.update({'version' : True, # Only for shared libs
'soversion' : True, # Only for shared libs
'name_prefix' : True,
'name_suffix' : True,
'vs_module_defs' : True, # Only for shared libs
'pic' : True, # Only for static libs
})
def compilers_are_msvc(compilers): def compilers_are_msvc(compilers):
""" """
@ -516,6 +523,16 @@ class BuildTarget():
if not isinstance(name_suffix, str): if not isinstance(name_suffix, str):
raise InvalidArguments('Name suffix must be a string.') raise InvalidArguments('Name suffix must be a string.')
self.suffix = name_suffix self.suffix = name_suffix
if isinstance(self, StaticLibrary):
# You can't disable PIC on OS X. The compiler ignores -fno-PIC.
# PIC is always on for Windows (all code is position-independent
# since library loading is done differently)
if for_darwin(self.is_cross, self.environment) or for_windows(self.is_cross, self.environment):
self.pic = True
else:
self.pic = kwargs.get('pic', False)
if not isinstance(self.pic, bool):
raise InvalidArguments('Argument pic must be boolean')
def get_subdir(self): def get_subdir(self):
return self.subdir return self.subdir
@ -618,6 +635,8 @@ by calling get_variable() on the subproject object.''')
t = t.held_object t = t.held_object
if not isinstance(t, (StaticLibrary, SharedLibrary)): if not isinstance(t, (StaticLibrary, SharedLibrary)):
raise InvalidArguments('Link target is not library.') raise InvalidArguments('Link target is not library.')
if isinstance(self, SharedLibrary) and isinstance(t, StaticLibrary) and not t.pic:
raise InvalidArguments("Can't link a non-PIC static library into a shared library")
if self.is_cross != t.is_cross: if self.is_cross != t.is_cross:
raise InvalidArguments('Tried to mix cross built and native libraries in target %s.' % self.name) raise InvalidArguments('Tried to mix cross built and native libraries in target %s.' % self.name)
self.link_targets.append(t) self.link_targets.append(t)
@ -831,6 +850,9 @@ class StaticLibrary(BuildTarget):
def type_suffix(self): def type_suffix(self):
return "@sta" return "@sta"
def check_unknown_kwargs(self, kwargs):
self.check_unknown_kwargs_int(kwargs, known_lib_kwargs)
class SharedLibrary(BuildTarget): class SharedLibrary(BuildTarget):
def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
self.soversion = None self.soversion = None
@ -988,7 +1010,7 @@ class SharedLibrary(BuildTarget):
self.link_depends.append(path) self.link_depends.append(path)
def check_unknown_kwargs(self, kwargs): def check_unknown_kwargs(self, kwargs):
self.check_unknown_kwargs_int(kwargs, known_shlib_kwargs) self.check_unknown_kwargs_int(kwargs, known_lib_kwargs)
def get_import_filename(self): def get_import_filename(self):
""" """

@ -1934,8 +1934,8 @@ class GnuCompiler:
return defines[define] return defines[define]
def get_pic_args(self): def get_pic_args(self):
if self.gcc_type == GCC_MINGW: if self.gcc_type in (GCC_MINGW, GCC_OSX):
return [] # On Window gcc defaults to fpic being always on. return [] # On Window and OS X, pic is always on.
return ['-fPIC'] return ['-fPIC']
def get_buildtype_args(self, buildtype): def get_buildtype_args(self, buildtype):
@ -2059,6 +2059,11 @@ class ClangCompiler():
self.base_options.append('b_lundef') self.base_options.append('b_lundef')
self.base_options.append('b_asneeded') self.base_options.append('b_asneeded')
def get_pic_args(self):
if self.clang_type in (CLANG_WIN, CLANG_OSX):
return [] # On Window and OS X, pic is always on.
return ['-fPIC']
def get_buildtype_args(self, buildtype): def get_buildtype_args(self, buildtype):
return gnulike_buildtype_args[buildtype] return gnulike_buildtype_args[buildtype]
@ -2174,8 +2179,8 @@ class FortranCompiler(Compiler):
return ' '.join(self.exelist) return ' '.join(self.exelist)
def get_pic_args(self): def get_pic_args(self):
if self.gcc_type == GCC_MINGW: if self.gcc_type in (GCC_MINGW, GCC_OSX):
return [] # On Windows gcc defaults to fpic being always on. return [] # On Window and OS X, pic is always on.
return ['-fPIC'] return ['-fPIC']
def get_std_shared_lib_link_args(self): def get_std_shared_lib_link_args(self):

@ -1,6 +1,7 @@
project('statchain', 'c') project('statchain', 'c')
subdir('subdir') subdir('subdir')
statlib = static_library('stat', 'stat.c', link_with : shlib) statlib = static_library('stat', 'stat.c', link_with : shlib, pic : true)
exe = executable('prog', 'prog.c', link_with : statlib) shlib2 = shared_library('shr2', 'shlib2.c', link_with : statlib)
exe = executable('prog', 'prog.c', link_with : shlib2)
test('runtest', exe) test('runtest', exe)

@ -1,5 +1,10 @@
int shlibfunc2();
int statlibfunc(); int statlibfunc();
int main(int argc, char **argv) { int main(int argc, char **argv) {
return statlibfunc() == 42 ? 0 : 1; if (statlibfunc() != 42)
return 1;
if (shlibfunc2() != 24)
return 1;
return 0;
} }

@ -0,0 +1,7 @@
#include "subdir/exports.h"
int statlibfunc(void);
int DLL_PUBLIC shlibfunc2(void) {
return statlibfunc() - 18;
}

@ -0,0 +1,12 @@
#pragma once
#if defined _WIN32 || defined __CYGWIN__
#define DLL_PUBLIC __declspec(dllexport)
#else
#if defined __GNUC__
#define DLL_PUBLIC __attribute__ ((visibility("default")))
#else
#pragma message ("Compiler does not support symbol visibility.")
#define DLL_PUBLIC
#endif
#endif

@ -1,13 +1,4 @@
#if defined _WIN32 || defined __CYGWIN__ #include "exports.h"
#define DLL_PUBLIC __declspec(dllexport)
#else
#if defined __GNUC__
#define DLL_PUBLIC __attribute__ ((visibility("default")))
#else
#pragma message ("Compiler does not support symbol visibility.")
#define DLL_PUBLIC
#endif
#endif
int DLL_PUBLIC shlibfunc() { int DLL_PUBLIC shlibfunc() {
return 42; return 42;

@ -0,0 +1,11 @@
project('statchain', 'c')
host_system = host_machine.system()
if host_system == 'windows' or host_system == 'darwin'
error('Test only fails on Linux and BSD')
endif
statlib = static_library('stat', 'stat.c', pic : false)
shlib2 = shared_library('shr2', 'shlib2.c', link_with : statlib)
exe = executable('prog', 'prog.c', link_with : shlib2)
test('runtest', exe)

@ -0,0 +1,10 @@
int shlibfunc2();
int statlibfunc();
int main(int argc, char **argv) {
if (statlibfunc() != 42)
return 1;
if (shlibfunc2() != 24)
return 1;
return 0;
}

@ -0,0 +1,16 @@
#if defined _WIN32 || defined __CYGWIN__
#define DLL_PUBLIC __declspec(dllexport)
#else
#if defined __GNUC__
#define DLL_PUBLIC __attribute__ ((visibility("default")))
#else
#pragma message ("Compiler does not support symbol visibility.")
#define DLL_PUBLIC
#endif
#endif
int statlibfunc(void);
int DLL_PUBLIC shlibfunc2(void) {
return 24;
}

@ -0,0 +1,3 @@
int statlibfunc() {
return 42;
}
Loading…
Cancel
Save