Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions mesonbuild/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -1128,3 +1128,10 @@ def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
# This is how autotools works, and the env vars feature is for
# autotools compatibility.
largs.extend_value(comp_options)

def can_run_host_binaries(self) -> bool:
return not (
self.is_cross_build() and
self.need_exe_wrapper() and
self.exe_wrapper is None
)
11 changes: 2 additions & 9 deletions mesonbuild/interpreter/mesonmain.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,21 +258,14 @@ def global_build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwarg
@FeatureDeprecated('meson.has_exe_wrapper', '0.55.0', 'use meson.can_run_host_binaries instead.')
@InterpreterObject.method('has_exe_wrapper')
def has_exe_wrapper_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
return self._can_run_host_binaries_impl()
return self.build.environment.can_run_host_binaries()

@noPosargs
@noKwargs
@FeatureNew('meson.can_run_host_binaries', '0.55.0')
@InterpreterObject.method('can_run_host_binaries')
def can_run_host_binaries_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
return self._can_run_host_binaries_impl()

def _can_run_host_binaries_impl(self) -> bool:
return not (
self.build.environment.is_cross_build() and
self.build.environment.need_exe_wrapper() and
self.build.environment.exe_wrapper is None
)
return self.build.environment.can_run_host_binaries()

@noPosargs
@noKwargs
Expand Down
62 changes: 45 additions & 17 deletions mesonbuild/linkers/linkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,11 +561,11 @@ def get_output_args(self, target: str) -> T.List[str]:
def get_linker_always_args(self) -> T.List[str]:
return ['-r']

def prepare_rpaths(raw_rpaths: T.Tuple[str, ...], build_dir: str, from_dir: str) -> T.List[str]:
def prepare_rpaths(env: Environment, raw_rpaths: T.Tuple[str, ...], build_dir: str, from_dir: str) -> T.List[str]:
# The rpaths we write must be relative if they point to the build dir,
# because otherwise they have different length depending on the build
# directory. This breaks reproducible builds.
internal_format_rpaths = [evaluate_rpath(p, build_dir, from_dir) for p in raw_rpaths]
internal_format_rpaths = [evaluate_rpath(env, p, build_dir, from_dir) for p in raw_rpaths]
ordered_rpaths = order_rpaths(internal_format_rpaths)
return ordered_rpaths

Expand All @@ -582,11 +582,16 @@ def order_rpaths(rpath_list: T.List[str]) -> T.List[str]:
return sorted(rpath_list, key=os.path.isabs)


def evaluate_rpath(p: str, build_dir: str, from_dir: str) -> str:
def evaluate_rpath(env: Environment, p: str, build_dir: str, from_dir: str) -> str:
if p == from_dir:
return '' # relpath errors out in this case
elif os.path.isabs(p):
return p # These can be outside of build dir.
if env.can_run_host_binaries():
return p # These can be outside of build dir.
# Skip external library if we can't run binaries on host system.
# (cross-compilation and no exe_wrapper)
else:
return ''
else:
return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir))

Expand Down Expand Up @@ -714,7 +719,7 @@ def build_rpath_args(self, env: Environment, build_dir: str, from_dir: str,
return ([], set())
args: T.List[str] = []
origin_placeholder = '$ORIGIN'
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
processed_rpaths = prepare_rpaths(env, rpath_paths, build_dir, from_dir)
# Need to deduplicate rpaths, as macOS's install_name_tool
# is *very* allergic to duplicate -delete_rpath arguments
# when calling depfixer on installation.
Expand All @@ -724,9 +729,13 @@ def build_rpath_args(self, env: Environment, build_dir: str, from_dir: str,
rpath_dirs_to_remove.add(p.encode('utf8'))
# Build_rpath is used as-is (it is usually absolute).
if target.build_rpath != '':
all_paths.add(target.build_rpath)
for p in target.build_rpath.split(':'):
rpath_dirs_to_remove.add(p.encode('utf8'))
paths = target.build_rpath.split(':')
for p in paths:
# Only include relative paths if we can't run binaries on host system.
# (cross-compilation and no exe_wrapper)
if env.can_run_host_binaries() or not os.path.isabs(p):
all_paths.add(p)
rpath_dirs_to_remove.add(p.encode('utf8'))
if extra_paths:
all_paths.update(extra_paths)

Expand Down Expand Up @@ -886,10 +895,15 @@ def build_rpath_args(self, env: Environment, build_dir: str, from_dir: str,
# @loader_path is the equivalent of $ORIGIN on macOS
# https://stackoverflow.com/q/26280738
origin_placeholder = '@loader_path'
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
processed_rpaths = prepare_rpaths(env, rpath_paths, build_dir, from_dir)
all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
if target.build_rpath != '':
all_paths.update(target.build_rpath.split(':'))
paths = target.build_rpath.split(':')
for p in paths:
# Only include relative paths if we can't run binaries on host system.
# (cross-compilation and no exe_wrapper)
if env.can_run_host_binaries() or not os.path.isabs(p):
all_paths.add(p)
if extra_paths:
all_paths.update(extra_paths)
for rp in all_paths:
Expand Down Expand Up @@ -1268,10 +1282,15 @@ def build_rpath_args(self, env: Environment, build_dir: str, from_dir: str,
return ([], set())
args: T.List[str] = []
origin_placeholder = '$ORIGIN'
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
processed_rpaths = prepare_rpaths(env, rpath_paths, build_dir, from_dir)
all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
if target.build_rpath != '':
all_paths.add(target.build_rpath)
paths = target.build_rpath.split(':')
for p in paths:
# Only include relative paths if we can't run binaries on host system.
# (cross-compilation and no exe_wrapper)
if env.can_run_host_binaries() or not os.path.isabs(p):
all_paths.add(p)
if extra_paths:
all_paths.update(extra_paths)
for rp in all_paths:
Expand Down Expand Up @@ -1524,15 +1543,19 @@ def build_rpath_args(self, env: Environment, build_dir: str, from_dir: str,
rpath_paths = target.determine_rpath_dirs()
if not rpath_paths and not target.install_rpath and not target.build_rpath and not extra_paths:
return ([], set())
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
processed_rpaths = prepare_rpaths(env, rpath_paths, build_dir, from_dir)
all_paths = mesonlib.OrderedSet([os.path.join('$ORIGIN', p) for p in processed_rpaths])
rpath_dirs_to_remove: T.Set[bytes] = set()
for p in all_paths:
rpath_dirs_to_remove.add(p.encode('utf8'))
if target.build_rpath != '':
all_paths.add(target.build_rpath)
for p in target.build_rpath.split(':'):
rpath_dirs_to_remove.add(p.encode('utf8'))
paths = target.build_rpath.split(':')
for p in paths:
# Only include relative paths if we can't run binaries on host system.
# (cross-compilation and no exe_wrapper)
if env.can_run_host_binaries() or not os.path.isabs(p):
all_paths.add(p)
rpath_dirs_to_remove.add(p.encode('utf8'))
if extra_paths:
all_paths.update(extra_paths)

Expand Down Expand Up @@ -1598,7 +1621,12 @@ def build_rpath_args(self, env: Environment, build_dir: str, from_dir: str,
if target.install_rpath != '':
all_paths.add(target.install_rpath)
if target.build_rpath != '':
all_paths.add(target.build_rpath)
paths = target.build_rpath.split(':')
for p in paths:
# Only include relative paths if we can't run binaries on host system.
# (cross-compilation and no exe_wrapper)
if env.can_run_host_binaries() or not os.path.isabs(p):
all_paths.add(p)
for p in target.determine_rpath_dirs():
all_paths.add(os.path.join(build_dir, p))
# We should consider allowing the $LIBPATH environment variable
Expand Down
Loading