aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2018-10-01 20:48:34 -0400
committerJussi Pakkanen <jpakkane@gmail.com>2018-10-20 00:47:27 +0300
commitc453400d597116954b3bb2a9e2c3d60251dc97a2 (patch)
tree9bfe4e1ad5cf6f0fe05e6ebd4ee34c746ca40eac
parent3ad99d27695c3018cf2449a2478b346a5b069c95 (diff)
downloadmeson-c453400d597116954b3bb2a9e2c3d60251dc97a2.zip
meson-c453400d597116954b3bb2a9e2c3d60251dc97a2.tar.gz
meson-c453400d597116954b3bb2a9e2c3d60251dc97a2.tar.bz2
Add 'b_pie' compiler option
On Android executables must be position independent, many distributions enable it by default too for security reasons.
-rw-r--r--docs/markdown/Builtin-options.md1
-rw-r--r--docs/markdown/Reference-manual.md1
-rw-r--r--docs/markdown/snippets/pie.md6
-rw-r--r--mesonbuild/backend/backends.py2
-rw-r--r--mesonbuild/backend/ninjabackend.py2
-rw-r--r--mesonbuild/build.py31
-rw-r--r--mesonbuild/compilers/compilers.py23
7 files changed, 58 insertions, 8 deletions
diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md
index 55d82a5..ce14304 100644
--- a/docs/markdown/Builtin-options.md
+++ b/docs/markdown/Builtin-options.md
@@ -82,6 +82,7 @@ platforms or with all compilers:
| b_pgo | off | off, generate, use | Use profile guided optimization |
| b_sanitize | none | see below | Code sanitizer to use |
| b_staticpic | true | true, false | Build static libraries as position independent |
+| b_pie | false | true, false | Build position-independent executables (since 0.49.0)|
The value of `b_sanitize` can be one of: `none`, `address`, `thread`,
`undefined`, `memory`, `address,undefined`.
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index e4c9303..64ed9d1 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -552,6 +552,7 @@ be passed to [shared and static libraries](#library).
- `d_unittest`, when set to true, the D modules are compiled in debug mode
- `d_module_versions` list of module version identifiers set when compiling D sources
- `d_debug` list of module debug identifiers set when compiling D sources
+- `pie` *(added 0.49.0)* build a position-independent executable
The list of `sources`, `objects`, and `dependencies` is always
flattened, which means you can freely nest and add lists while
diff --git a/docs/markdown/snippets/pie.md b/docs/markdown/snippets/pie.md
new file mode 100644
index 0000000..a9be174
--- /dev/null
+++ b/docs/markdown/snippets/pie.md
@@ -0,0 +1,6 @@
+## Position-independent executables
+
+When `b_pie` option, or `executable()`'s `pie` keyword argument is set to
+`true`, position-independent executables are built. All their objects are built
+with `-fPIE` and the executable is linked with `-pie`. Any static library they
+link must be built with `pic` set to `true` (see `b_staticpic` option).
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 28ef670..f12b357 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -552,6 +552,8 @@ class Backend:
# 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:
+ commands += compiler.get_pie_args()
# Add compile args needed to find external dependencies. Link args are
# added while generating the link command.
# NOTE: We must preserve the order in which external deps are
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index b564311..d8370c2 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2245,6 +2245,8 @@ rule FORTRAN_DEP_HACK%s
# If implib, and that's significant on this platform (i.e. Windows using either GCC or Visual Studio)
if target.import_filename:
commands += linker.gen_import_library_args(os.path.join(self.get_target_dir(target), target.import_filename))
+ if target.pie:
+ commands += linker.get_pie_link_args()
elif isinstance(target, build.SharedLibrary):
if isinstance(target, build.SharedModule):
options = self.environment.coredata.base_options
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 8ba5465..f2a6d9c 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -84,7 +84,7 @@ known_build_target_kwargs = (
rust_kwargs |
cs_kwargs)
-known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic'}
+known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie'}
known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'}
known_shmod_kwargs = known_build_target_kwargs
known_stlib_kwargs = known_build_target_kwargs | {'pic'}
@@ -414,6 +414,8 @@ class BuildTarget(Target):
self.generated = []
self.extra_files = []
self.d_features = {}
+ self.pic = False
+ self.pie = False
# Sources can be:
# 1. Pre-existing source files in the source tree
# 2. Pre-existing sources generated by configure_file in the build tree
@@ -869,13 +871,14 @@ This will become a hard error in a future Meson release.''')
# 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
- elif '-fPIC' in clist + cpplist:
- mlog.warning("Use the 'pic' kwarg instead of passing -fPIC manually to static library {!r}".format(self.name))
- self.pic = True
else:
- self.pic = kwargs.get('pic', False)
- if not isinstance(self.pic, bool):
- raise InvalidArguments('Argument pic to static library {!r} must be boolean'.format(self.name))
+ self.pic = self._extract_pic_pie(kwargs, 'pic')
+ if isinstance(self, Executable):
+ # Executables must be PIE on Android
+ if for_android(self.is_cross, self.environment):
+ self.pie = True
+ else:
+ self.pie = self._extract_pic_pie(kwargs, '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.')
@@ -888,6 +891,18 @@ This will become a hard error in a future Meson release.''')
raise InvalidArguments('GNU symbol visibility arg %s not one of: %s',
self.symbol_visibility, ', '.join(permitted))
+ def _extract_pic_pie(self, kwargs, arg):
+ # 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 not isinstance(val, bool):
+ raise InvalidArguments('Argument {} to {!r} must be boolean'.format(arg, self.name))
+ return val
+
def get_filename(self):
return self.filename
@@ -1307,6 +1322,8 @@ class Executable(BuildTarget):
known_kwargs = known_exe_kwargs
def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
+ if 'pie' not in kwargs and 'b_pie' in environment.coredata.base_options:
+ kwargs['pie'] = environment.coredata.base_options['b_pie'].value
super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
# Unless overridden, executables have no suffix or prefix. Except on
# Windows and with C#/Mono executables where the suffix is 'exe'
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 26eec48..50fda5a 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -331,6 +331,9 @@ base_options = {'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled he
'b_staticpic': coredata.UserBooleanOption('b_staticpic',
'Build static libraries as position independent',
True),
+ 'b_pie': coredata.UserBooleanOption('b_pie',
+ 'Build executables as position independent',
+ False),
'b_bitcode': coredata.UserBooleanOption('b_bitcode',
'Generate and embed bitcode (only macOS and iOS)',
False),
@@ -1180,6 +1183,18 @@ class Compiler:
raise EnvironmentException(
'Language {} does not support function attributes.'.format(self.get_display_language()))
+ def get_pic_args(self):
+ m = 'Language {} does not support position-independent code'
+ raise EnvironmentException(m.format(self.get_display_language()))
+
+ def get_pie_args(self):
+ m = 'Language {} does not support position-independent executable'
+ raise EnvironmentException(m.format(self.get_display_language()))
+
+ def get_pie_link_args(self):
+ m = 'Language {} does not support position-independent executable'
+ raise EnvironmentException(m.format(self.get_display_language()))
+
@enum.unique
class CompilerType(enum.Enum):
@@ -1322,7 +1337,7 @@ class GnuLikeCompiler(abc.ABC):
def __init__(self, compiler_type):
self.compiler_type = compiler_type
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
- 'b_ndebug', 'b_staticpic']
+ 'b_ndebug', 'b_staticpic', 'b_pie']
if not self.compiler_type.is_osx_compiler and not self.compiler_type.is_windows_compiler:
self.base_options.append('b_lundef')
if not self.compiler_type.is_windows_compiler:
@@ -1345,6 +1360,12 @@ class GnuLikeCompiler(abc.ABC):
return [] # On Window and OS X, pic is always on.
return ['-fPIC']
+ def get_pie_args(self):
+ return ['-fPIE']
+
+ def get_pie_link_args(self):
+ return ['-pie']
+
def get_buildtype_args(self, buildtype):
return gnulike_buildtype_args[buildtype]