Merge pull request #856 from centricular/static_library_pic
Add cross-platform PIC support for static libraries
This commit is contained in:
commit
4781f471c2
|
@ -341,6 +341,8 @@ class Backend():
|
|||
commands += compiler.get_werror_args()
|
||||
if isinstance(target, build.SharedLibrary):
|
||||
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():
|
||||
# Cflags required by external deps might have UNIX-specific flags,
|
||||
# so filter them out if needed
|
||||
|
|
|
@ -44,12 +44,19 @@ known_basic_kwargs = {'install' : True,
|
|||
'native' : True,
|
||||
}
|
||||
|
||||
known_shlib_kwargs = known_basic_kwargs.copy()
|
||||
known_shlib_kwargs.update({'version' : True,
|
||||
'soversion' : True,
|
||||
'name_prefix' : True,
|
||||
'name_suffix' : True,
|
||||
'vs_module_defs' : True})
|
||||
# These contain kwargs supported by both static and shared libraries. These are
|
||||
# combined here because a library() call might be shared_library() or
|
||||
# static_library() at runtime based on the configuration.
|
||||
# FIXME: Find a way to pass that info down here so we can have proper target
|
||||
# kwargs checking when specifically using shared_library() or static_library().
|
||||
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):
|
||||
"""
|
||||
|
@ -516,6 +523,16 @@ class BuildTarget():
|
|||
if not isinstance(name_suffix, str):
|
||||
raise InvalidArguments('Name suffix must be a string.')
|
||||
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):
|
||||
return self.subdir
|
||||
|
@ -618,6 +635,8 @@ by calling get_variable() on the subproject object.''')
|
|||
t = t.held_object
|
||||
if not isinstance(t, (StaticLibrary, SharedLibrary)):
|
||||
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:
|
||||
raise InvalidArguments('Tried to mix cross built and native libraries in target %s.' % self.name)
|
||||
self.link_targets.append(t)
|
||||
|
@ -831,6 +850,9 @@ class StaticLibrary(BuildTarget):
|
|||
def type_suffix(self):
|
||||
return "@sta"
|
||||
|
||||
def check_unknown_kwargs(self, kwargs):
|
||||
self.check_unknown_kwargs_int(kwargs, known_lib_kwargs)
|
||||
|
||||
class SharedLibrary(BuildTarget):
|
||||
def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
|
||||
self.soversion = None
|
||||
|
@ -988,7 +1010,7 @@ class SharedLibrary(BuildTarget):
|
|||
self.link_depends.append(path)
|
||||
|
||||
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):
|
||||
"""
|
||||
|
|
|
@ -1934,8 +1934,8 @@ class GnuCompiler:
|
|||
return defines[define]
|
||||
|
||||
def get_pic_args(self):
|
||||
if self.gcc_type == GCC_MINGW:
|
||||
return [] # On Window gcc defaults to fpic being always on.
|
||||
if self.gcc_type in (GCC_MINGW, GCC_OSX):
|
||||
return [] # On Window and OS X, pic is always on.
|
||||
return ['-fPIC']
|
||||
|
||||
def get_buildtype_args(self, buildtype):
|
||||
|
@ -2059,6 +2059,11 @@ class ClangCompiler():
|
|||
self.base_options.append('b_lundef')
|
||||
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):
|
||||
return gnulike_buildtype_args[buildtype]
|
||||
|
||||
|
@ -2174,8 +2179,8 @@ class FortranCompiler(Compiler):
|
|||
return ' '.join(self.exelist)
|
||||
|
||||
def get_pic_args(self):
|
||||
if self.gcc_type == GCC_MINGW:
|
||||
return [] # On Windows gcc defaults to fpic being always on.
|
||||
if self.gcc_type in (GCC_MINGW, GCC_OSX):
|
||||
return [] # On Window and OS X, pic is always on.
|
||||
return ['-fPIC']
|
||||
|
||||
def get_std_shared_lib_link_args(self):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
project('statchain', 'c')
|
||||
|
||||
subdir('subdir')
|
||||
statlib = static_library('stat', 'stat.c', link_with : shlib)
|
||||
exe = executable('prog', 'prog.c', link_with : statlib)
|
||||
statlib = static_library('stat', 'stat.c', link_with : shlib, pic : true)
|
||||
shlib2 = shared_library('shr2', 'shlib2.c', link_with : statlib)
|
||||
exe = executable('prog', 'prog.c', link_with : shlib2)
|
||||
test('runtest', exe)
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
int shlibfunc2();
|
||||
int statlibfunc();
|
||||
|
||||
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__
|
||||
#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
|
||||
#include "exports.h"
|
||||
|
||||
int DLL_PUBLIC shlibfunc() {
|
||||
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…
Reference in New Issue