From 021d242f9ce8e6cd804af0c1eb4179b8c83fd470 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 8 Oct 2020 15:30:24 +0200 Subject: [PATCH] build: use PIE objects for static libraries if b_staticpic=false but b_pie=true If static_library is used as a convenience library (e.g. for link_whole) it should in principle not need position independent code. However, if the executables that the libraries is linked to are PIE, the non-PIC objects in the static library will cause linker errors. To avoid this, obey b_pie for static libraries if either b_staticpic=false or they use "pic: false". Without this patch, QEMU cannot use b_staticpic, which causes a slowdown on some QEMU benchmarks up to 20%. --- mesonbuild/backend/backends.py | 2 +- mesonbuild/build.py | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 23734a8ec43a..a322d5f16000 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -723,7 +723,7 @@ def generate_basic_compiler_args(self, target, compiler, no_warn_args=False): # Set -fPIC for static libraries by default unless explicitly disabled if isinstance(target, build.StaticLibrary) and target.pic: commands += compiler.get_pic_args() - if isinstance(target, build.Executable) and target.pie: + elif isinstance(target, (build.StaticLibrary, build.Executable)) and target.pie: commands += compiler.get_pie_args() # Add compile args needed to find external dependencies. Link args are # added while generating the link command. diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 26b54ffafeb7..472363616628 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -993,13 +993,13 @@ def process_kwargs(self, kwargs, environment): if m.is_darwin() or m.is_windows(): self.pic = True else: - self.pic = self._extract_pic_pie(kwargs, 'pic') - if isinstance(self, Executable): + self.pic = self._extract_pic_pie(kwargs, 'pic', environment, 'b_staticpic') + if isinstance(self, Executable) or (isinstance(self, StaticLibrary) and not self.pic): # Executables must be PIE on Android if self.environment.machines[self.for_machine].is_android(): self.pie = True else: - self.pie = self._extract_pic_pie(kwargs, 'pie') + self.pie = self._extract_pic_pie(kwargs, 'pie', environment, 'b_pie') self.implicit_include_directories = kwargs.get('implicit_include_directories', True) if not isinstance(self.implicit_include_directories, bool): raise InvalidArguments('Implicit_include_directories must be a boolean.') @@ -1017,14 +1017,20 @@ def validate_win_subsystem(self, value: str) -> str: raise InvalidArguments('Invalid value for win_subsystem: {}.'.format(value)) return value - def _extract_pic_pie(self, kwargs, arg): + def _extract_pic_pie(self, kwargs, arg, environment, option): # Check if we have -fPIC, -fpic, -fPIE, or -fpie in cflags all_flags = self.extra_args['c'] + self.extra_args['cpp'] if '-f' + arg.lower() in all_flags or '-f' + arg.upper() in all_flags: mlog.warning("Use the '{}' kwarg instead of passing '{}' manually to {!r}".format(arg, '-f' + arg, self.name)) return True - val = kwargs.get(arg, False) + if arg in kwargs: + val = kwargs[arg] + elif option in environment.coredata.base_options: + val = environment.coredata.base_options[option].value + else: + val = False + if not isinstance(val, bool): raise InvalidArguments('Argument {} to {!r} must be boolean'.format(arg, self.name)) return val @@ -1637,8 +1643,6 @@ class StaticLibrary(BuildTarget): def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): self.typename = 'static library' - if 'pic' not in kwargs and 'b_staticpic' in environment.coredata.base_options: - kwargs['pic'] = environment.coredata.base_options['b_staticpic'].value super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) if 'cs' in self.compilers: raise InvalidArguments('Static libraries not supported for C#.')