diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2017-04-19 15:32:24 -0700 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2017-05-08 20:59:46 +0200 |
commit | 7053d9abfdef64c1f507173609fad4c9866441eb (patch) | |
tree | 0eaa78e007a8c69066dfa152490edc64e01da636 | |
parent | ccab7d64f474f00e010b2c6601e63d8034c5552a (diff) | |
download | meson-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.md | 2 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 10 | ||||
-rw-r--r-- | mesonbuild/build.py | 41 | ||||
-rw-r--r-- | test cases/linuxlike/3 linker script/bob.map.in | 6 | ||||
-rw-r--r-- | test cases/linuxlike/3 linker script/copy.py | 5 | ||||
-rw-r--r-- | test cases/linuxlike/3 linker script/meson.build | 48 | ||||
-rw-r--r-- | test cases/linuxlike/3 linker script/sub/foo.map | 6 | ||||
-rw-r--r-- | test cases/linuxlike/3 linker script/sub/meson.build | 6 |
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) |