aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-05-06 13:43:03 +0300
committerJussi Pakkanen <jpakkane@gmail.com>2017-06-03 16:03:53 +0300
commit4828b46b73c0e4874634be0439a1653144e4e0e7 (patch)
tree9fa28ac0611fc901395c6ae95aac673c58c336fa
parent0e9852a457653cb01e477ec041281131b854fa82 (diff)
downloadmeson-4828b46b73c0e4874634be0439a1653144e4e0e7.zip
meson-4828b46b73c0e4874634be0439a1653144e4e0e7.tar.gz
meson-4828b46b73c0e4874634be0439a1653144e4e0e7.tar.bz2
Use relative rpath so builds are reproducible.
-rw-r--r--docs/markdown/Release-notes-for-0.41.0.md6
-rw-r--r--mesonbuild/backend/ninjabackend.py9
-rw-r--r--mesonbuild/compilers.py34
3 files changed, 37 insertions, 12 deletions
diff --git a/docs/markdown/Release-notes-for-0.41.0.md b/docs/markdown/Release-notes-for-0.41.0.md
index 7da9ed7..80bf0b3 100644
--- a/docs/markdown/Release-notes-for-0.41.0.md
+++ b/docs/markdown/Release-notes-for-0.41.0.md
@@ -61,3 +61,9 @@ Targets for building rust now take a `rust_args` keyword.
Code coverage can be generated for tests by passing the `--cov` argument to
the `run_tests.py` test runner. Note, since multiple processes are used,
coverage must be combined before producing a report (`coverage3 combine`.)
+
+## Reproducible builds
+
+All known issues have been fixed and Meson can now build reproducible Debian
+packages out of the box.
+
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 6bd9633..8624d66 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2307,7 +2307,16 @@ rule FORTRAN_DEP_HACK
commands += linker.get_option_link_args(self.environment.coredata.compiler_options)
# Set runtime-paths so we can run executables without needing to set
# LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows.
+ if '/' in target.name or '\\' in target.name:
+ # Target names really should not have slashes in them, but
+ # unfortunately we did not check for that and some downstream projects
+ # now have them. Once slashes are forbidden, remove this bit.
+ target_slashname_workaround_dir = os.path.join(os.path.split(target.name)[0],
+ self.get_target_dir(target))
+ else:
+ target_slashname_workaround_dir = self.get_target_dir(target)
commands += linker.build_rpath_args(self.environment.get_build_dir(),
+ target_slashname_workaround_dir,
self.determine_rpath_dirs(target),
target.install_rpath)
# Add libraries generated by custom targets
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index e7c02b2..69188c5 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -316,10 +316,20 @@ def get_base_link_args(options, linker, is_shared_module):
pass
return args
-def build_unix_rpath_args(build_dir, rpath_paths, install_rpath):
+def build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath):
if not rpath_paths and not install_rpath:
return []
- paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
+ # The rpaths we write must be relative, because otherwise
+ # they have different length depending on the build
+ # directory. This breaks reproducible builds.
+ rel_rpaths = []
+ for p in rpath_paths:
+ if p == from_dir:
+ relative = '' # relpath errors out in this case
+ else:
+ relative = os.path.relpath(p, from_dir)
+ rel_rpaths.append(relative)
+ paths = ':'.join([os.path.join('$ORIGIN', p) for p in rel_rpaths])
if len(paths) < len(install_rpath):
padding = 'X' * (len(install_rpath) - len(paths))
if not paths:
@@ -762,8 +772,8 @@ class CCompiler(Compiler):
# The default behavior is this, override in
# OSX and MSVC.
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
- return build_unix_rpath_args(build_dir, rpath_paths, install_rpath)
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
+ return build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath)
def get_dependency_gen_args(self, outtarget, outfile):
return ['-MMD', '-MQ', outtarget, '-MF', outfile]
@@ -1901,7 +1911,7 @@ class DCompiler(Compiler):
def get_std_exe_link_args(self):
return []
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
# This method is to be used by LDC and DMD.
# GDC can deal with the verbatim flags.
if not rpath_paths and not install_rpath:
@@ -2024,8 +2034,8 @@ class GnuDCompiler(DCompiler):
def get_buildtype_args(self, buildtype):
return d_gdc_buildtype_args[buildtype]
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
- return build_unix_rpath_args(build_dir, rpath_paths, install_rpath)
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
+ return build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath)
def get_unittest_args(self):
return ['-funittest']
@@ -2233,7 +2243,7 @@ class VisualStudioCCompiler(CCompiler):
"The name of the outputted import library"
return ['/IMPLIB:' + implibname]
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
return []
# FIXME, no idea what these should be.
@@ -2973,8 +2983,8 @@ end program prog
def get_std_exe_link_args(self):
return []
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
- return build_unix_rpath_args(build_dir, rpath_paths, install_rpath)
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
+ return build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath)
def module_name_to_filename(self, module_name):
return module_name.lower() + '.mod'
@@ -3154,7 +3164,7 @@ class VisualStudioLinker(StaticLinker):
def get_linker_always_args(self):
return VisualStudioLinker.always_args
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
return []
def thread_link_flags(self):
@@ -3183,7 +3193,7 @@ class ArLinker(StaticLinker):
else:
self.std_args = ['csr']
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
return []
def get_exelist(self):