aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2017-04-19 15:32:24 -0700
committerJussi Pakkanen <jpakkane@gmail.com>2017-05-08 20:59:46 +0200
commit7053d9abfdef64c1f507173609fad4c9866441eb (patch)
tree0eaa78e007a8c69066dfa152490edc64e01da636
parentccab7d64f474f00e010b2c6601e63d8034c5552a (diff)
downloadmeson-7053d9abfdef64c1f507173609fad4c9866441eb.zip
meson-7053d9abfdef64c1f507173609fad4c9866441eb.tar.gz
meson-7053d9abfdef64c1f507173609fad4c9866441eb.tar.bz2
Allow link_depends to take strings, Files or generated objects. Closes #1172
Currently only strings can be passed to the link_depends argument of executable and *library, which solves many cases, but not every one. This patch allows generated sources and Files to be passed as well. On the implementation side, it uses a helper method to keep the more complex logic separated from the __init__ method. This also requires that Targets set their link_depends paths as Files, and the backend is responsible for converting to strings when it wants them. This adds tests for the following cases: - Using a file in a subdir - Using a configure_file as an input - Using a custom_target as an input It does not support using a generator as an input, since currently that would require calling the generator twice, once for the -Wl argument, and once for the link_depends. Also updates the docs.
-rw-r--r--docs/markdown/Reference-manual.md2
-rw-r--r--mesonbuild/backend/ninjabackend.py10
-rw-r--r--mesonbuild/build.py41
-rw-r--r--test cases/linuxlike/3 linker script/bob.map.in6
-rw-r--r--test cases/linuxlike/3 linker script/copy.py5
-rw-r--r--test cases/linuxlike/3 linker script/meson.build48
-rw-r--r--test cases/linuxlike/3 linker script/sub/foo.map6
-rw-r--r--test cases/linuxlike/3 linker script/sub/meson.build6
8 files changed, 111 insertions, 13 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 276c9c9..00a891b 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -233,7 +233,7 @@ Executable supports the following keyword arguments. Note that just like the pos
- `<languagename>_pch` precompiled header file to use for the given language
- `<languagename>_args` compiler flags to use for the given language; eg: `cpp_args` for C++
- `link_args` flags to use during linking. You can use UNIX-style flags here for all platforms.
-- `link_depends` an extra file in the source tree that the link step depends on such as a symbol visibility map. The purpose is to automatically trigger a re-link (but not a re-compile) of the target when this file changes.
+- `link_depends` strings, files, or custom targets the link step depends on such as a symbol visibility map. The purpose is to automatically trigger a re-link (but not a re-compile) of the target when this file changes.
- `include_directories` one or more objects created with the `include_directories` function
- `dependencies` one or more objects created with [`dependency`](#dependency) or [`find_library`](#compiler-object) (for external deps) or [`declare_dependency`](#declare_dependency) (for deps built by the project)
- `gui_app` when set to true flags this target as a GUI application on platforms where this makes a difference (e.g. Windows)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index f4c78a1..bbae408 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2316,8 +2316,8 @@ rule FORTRAN_DEP_HACK
# current compiler.
commands = commands.to_native()
dep_targets = [self.get_dependency_filename(t) for t in dependencies]
- dep_targets += [os.path.join(self.environment.source_dir,
- target.subdir, t) for t in target.link_depends]
+ dep_targets.extend([self.get_dependency_filename(t)
+ for t in target.link_depends])
elem = NinjaBuildElement(self.all_outputs, outname, linker_rule, obj_list)
elem.add_dep(dep_targets + custom_target_libraries)
elem.add_item('LINK_ARGS', commands)
@@ -2335,6 +2335,12 @@ rule FORTRAN_DEP_HACK
def get_dependency_filename(self, t):
if isinstance(t, build.SharedLibrary):
return os.path.join(self.get_target_private_dir(t), self.get_target_filename(t) + '.symbols')
+ elif isinstance(t, mesonlib.File):
+ if t.is_built:
+ return t.relative_name()
+ else:
+ return t.absolute_path(self.environment.get_source_dir(),
+ self.environment.get_build_dir())
return self.get_target_filename(t)
def generate_shlib_aliases(self, target, outdir):
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 1f1018f..0d58394 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -503,6 +503,34 @@ class BuildTarget(Target):
assert(len(self.compilers) == 1)
return
+ def process_link_depends(self, sources, environment):
+ """Process the link_depends keyword argument.
+
+ This is designed to handle strings, Files, and the output of Custom
+ Targets. Notably it doesn't handle generator() returned objects, since
+ adding them as a link depends would inherently cause them to be
+ generated twice, since the output needs to be passed to the ld_args and
+ link_depends.
+ """
+ if not isinstance(sources, list):
+ sources = [sources]
+ for s in sources:
+ if hasattr(s, 'held_object'):
+ s = s.held_object
+
+ if isinstance(s, File):
+ self.link_depends.append(s)
+ elif isinstance(s, str):
+ self.link_depends.append(
+ File.from_source_file(environment.source_dir, self.subdir, s))
+ elif hasattr(s, 'get_outputs'):
+ self.link_depends.extend(
+ [File.from_built_file(s.subdir, p) for p in s.get_outputs()])
+ else:
+ raise InvalidArguments(
+ 'Link_depends arguments must be strings, Files, '
+ 'or a Custom Target, or lists thereof.')
+
def get_original_kwargs(self):
return self.kwargs
@@ -616,12 +644,7 @@ class BuildTarget(Target):
for i in self.link_args:
if not isinstance(i, str):
raise InvalidArguments('Link_args arguments must be strings.')
- self.link_depends = kwargs.get('link_depends', [])
- if not isinstance(self.link_depends, list):
- self.link_depends = [self.link_depends]
- for i in self.link_depends:
- if not isinstance(i, str):
- raise InvalidArguments('Link_depends arguments must be strings.')
+ self.process_link_depends(kwargs.get('link_depends', []), environment)
# Target-specific include dirs must be added BEFORE include dirs from
# internal deps (added inside self.add_deps()) to override them.
inclist = kwargs.get('include_directories', [])
@@ -1264,13 +1287,11 @@ class SharedLibrary(BuildTarget):
self.vs_module_defs = File.from_absolute_file(path)
else:
self.vs_module_defs = File.from_source_file(environment.source_dir, self.subdir, path)
- # link_depends can be an absolute path or relative to self.subdir
- self.link_depends.append(path)
+ self.link_depends.append(self.vs_module_defs)
elif isinstance(path, File):
# When passing a generated file.
self.vs_module_defs = path
- # link_depends can be an absolute path or relative to self.subdir
- self.link_depends.append(path.absolute_path(environment.source_dir, environment.build_dir))
+ self.link_depends.append(path)
else:
raise InvalidArguments(
'Shared library vs_module_defs must be either a string, '
diff --git a/test cases/linuxlike/3 linker script/bob.map.in b/test cases/linuxlike/3 linker script/bob.map.in
new file mode 100644
index 0000000..f695e4a
--- /dev/null
+++ b/test cases/linuxlike/3 linker script/bob.map.in
@@ -0,0 +1,6 @@
+V1_0_0 {
+ global:
+ "@in@";
+ local:
+ *;
+};
diff --git a/test cases/linuxlike/3 linker script/copy.py b/test cases/linuxlike/3 linker script/copy.py
new file mode 100644
index 0000000..49e7a85
--- /dev/null
+++ b/test cases/linuxlike/3 linker script/copy.py
@@ -0,0 +1,5 @@
+import shutil
+import sys
+
+if __name__ == '__main__':
+ shutil.copy(sys.argv[1], sys.argv[2])
diff --git a/test cases/linuxlike/3 linker script/meson.build b/test cases/linuxlike/3 linker script/meson.build
index 30761c6..63765e7 100644
--- a/test cases/linuxlike/3 linker script/meson.build
+++ b/test cases/linuxlike/3 linker script/meson.build
@@ -1,8 +1,56 @@
project('linker script', 'c')
+# Static map file
mapfile = 'bob.map'
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
l = shared_library('bob', 'bob.c', link_args : vflag, link_depends : mapfile)
e = executable('prog', 'prog.c', link_with : l)
test('core', e)
+
+# configure_file
+conf = configuration_data()
+conf.set('in', 'bobMcBob')
+m = configure_file(
+ input : 'bob.map.in',
+ output : 'bob-conf.map',
+ configuration : conf,
+)
+vflag = '-Wl,--version-script,@0@'.format(m)
+
+l = shared_library('bob-conf', 'bob.c', link_args : vflag, link_depends : m)
+e = executable('prog-conf', 'prog.c', link_with : l)
+test('core', e)
+
+# custom_target
+python = find_program('python3')
+m = custom_target(
+ 'bob-ct.map',
+ command : [python, '@INPUT0@', '@INPUT1@', 'bob-ct.map'],
+ input : ['copy.py', 'bob.map'],
+ output : 'bob-ct.map',
+ depend_files : 'bob.map',
+)
+vflag = '-Wl,--version-script,@0@'.format(m.full_path())
+
+l = shared_library('bob-ct', ['bob.c', m], link_args : vflag, link_depends : m)
+e = executable('prog-ct', 'prog.c', link_with : l)
+test('core', e)
+
+# File
+mapfile = files('bob.map')
+vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile[0])
+
+l = shared_library('bob-files', 'bob.c', link_args : vflag, link_depends : mapfile)
+e = executable('prog-files', 'prog.c', link_with : l)
+test('core', e)
+
+subdir('sub')
+
+# With map file in subdir
+mapfile = 'sub/foo.map'
+vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
+
+l = shared_library('bar', 'bob.c', link_args : vflag, link_depends : mapfile)
+e = executable('prog-bar', 'prog.c', link_with : l)
+test('core', e)
diff --git a/test cases/linuxlike/3 linker script/sub/foo.map b/test cases/linuxlike/3 linker script/sub/foo.map
new file mode 100644
index 0000000..e07a780
--- /dev/null
+++ b/test cases/linuxlike/3 linker script/sub/foo.map
@@ -0,0 +1,6 @@
+V1_0_0 {
+ global:
+ "bobMcBob";
+ local:
+ *;
+};
diff --git a/test cases/linuxlike/3 linker script/sub/meson.build b/test cases/linuxlike/3 linker script/sub/meson.build
new file mode 100644
index 0000000..93199f3
--- /dev/null
+++ b/test cases/linuxlike/3 linker script/sub/meson.build
@@ -0,0 +1,6 @@
+mapfile = 'foo.map'
+vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
+
+l = shared_library('foo', '../bob.c', link_args : vflag, link_depends : mapfile)
+e = executable('prog-foo', '../prog.c', link_with : l)
+test('core', e)