From 57cb1f9aad0928e167018ba886e2d8c06225b515 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Mon, 13 Mar 2017 03:45:10 +0530 Subject: Support multiple install dirs for built/custom targets You can now pass a list of strings to the install_dir: kwarg to build_target and custom_target. Custom Targets: =============== Allows you to specify the installation directory for each corresponding output. For example: custom_target('different-install-dirs', output : ['first.file', 'second.file'], ... install : true, install_dir : ['somedir', 'otherdir]) This would install first.file to somedir and second.file to otherdir. If only one install_dir is provided, all outputs are installed there (same behaviour as before). To only install some outputs, pass `false` for the outputs that you don't want installed. For example: custom_target('only-install-second', output : ['first.file', 'second.file'], ... install : true, install_dir : [false, 'otherdir]) This would install second.file to otherdir and not install first.file. Build Targets: ============== With build_target() (which includes executable(), library(), etc), usually there is only one primary output. However some types of targets have multiple outputs. For example, while generating Vala libraries, valac also generates a header and a .vapi file both of which often need to be installed. This allows you to specify installation directories for those too. # This will only install the library (same as before) shared_library('somevalalib', 'somesource.vala', ... install : true) # This will install the library, the header, and the vapi into the # respective directories shared_library('somevalalib', 'somesource.vala', ... install : true, install_dir : ['libdir', 'incdir', 'vapidir']) # This will install the library into the default libdir and # everything else into the specified directories shared_library('somevalalib', 'somesource.vala', ... install : true, install_dir : [true, 'incdir', 'vapidir']) # This will NOT install the library, and will install everything # else into the specified directories shared_library('somevalalib', 'somesource.vala', ... install : true, install_dir : [false, 'incdir', 'vapidir']) true/false can also be used for secondary outputs in the same way. Valac can also generate a GIR file for libraries when the `vala_gir:` keyword argument is passed to library(). In that case, `install_dir:` must be given a list with four elements, one for each output. Includes tests for all these. Closes https://github.com/mesonbuild/meson/issues/705 Closes https://github.com/mesonbuild/meson/issues/891 Closes https://github.com/mesonbuild/meson/issues/892 Closes https://github.com/mesonbuild/meson/issues/1178 Closes https://github.com/mesonbuild/meson/issues/1193 --- mesonbuild/backend/backends.py | 4 +-- mesonbuild/backend/ninjabackend.py | 70 +++++++++++++++++++++++++++++--------- mesonbuild/build.py | 49 +++++++++++++++----------- mesonbuild/interpreter.py | 2 +- mesonbuild/mesonlib.py | 23 ++++++------- mesonbuild/modules/gnome.py | 4 +-- mesonbuild/modules/pkgconfig.py | 5 +-- 7 files changed, 101 insertions(+), 56 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 5517fbd..9b541e9 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -599,7 +599,7 @@ class Backend: for t in target.get_generated_sources(): if not isinstance(t, build.CustomTarget): continue - for f in t.output: + for f in t.get_outputs(): if self.environment.is_library(f): libs.append(os.path.join(self.get_target_dir(t), f)) return libs @@ -640,7 +640,7 @@ class Backend: build_root = self.environment.get_source_dir() outdir = os.path.join(self.environment.get_build_dir(), outdir) outputs = [] - for i in target.output: + for i in target.get_outputs(): outputs.append(os.path.join(outdir, i)) inputs = self.get_custom_target_sources(target) # Evaluate the command list diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index bc51ace..77b2d1d 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -630,15 +630,17 @@ int dummy; for t in self.build.get_targets().values(): if t.should_install(): should_strip = self.get_option_for_target('strip', t) - # Find the installation directory. FIXME: Currently only one - # installation directory is supported for each target - outdir = t.get_custom_install_dir() - if outdir is not None: + # Find the installation directory. + outdirs = t.get_custom_install_dir() + if outdirs[0] is not None and outdirs[0] is not True: + # Either the value is set, or is set to False which means + # we want this specific output out of many outputs to not + # be installed. pass elif isinstance(t, build.SharedLibrary): - # For toolchains/platforms that need an import library for + # On toolchains/platforms that use an import library for # linking (separate from the shared library with all the - # code), we need to install the import library (dll.a/.lib) + # code), we need to install that too (dll.a/.lib). if t.get_import_filename(): # Install the import library. i = [self.get_target_filename_for_linking(t), @@ -647,22 +649,56 @@ int dummy; # doesn't have an install_rpath {}, False, ''] d.targets.append(i) - outdir = self.environment.get_shared_lib_dir() + outdirs[0] = self.environment.get_shared_lib_dir() elif isinstance(t, build.StaticLibrary): - outdir = self.environment.get_static_lib_dir() + outdirs[0] = self.environment.get_static_lib_dir() elif isinstance(t, build.Executable): - outdir = self.environment.get_bindir() + outdirs[0] = self.environment.get_bindir() else: + assert(isinstance(t, build.BuildTarget)) # XXX: Add BuildTarget-specific install dir cases here - outdir = self.environment.get_libdir() + outdirs[0] = self.environment.get_libdir() + # Sanity-check the outputs and install_dirs + num_outdirs, num_out = len(outdirs), len(t.get_outputs()) + if num_outdirs != 1 and num_outdirs != num_out: + raise MesonException('Target {!r} has {} outputs, but only ' + '{} "install_dir"s were specified' + ''.format(t.name, num_out, num_outdirs)) + # Install the target output(s) if isinstance(t, build.BuildTarget): - i = [self.get_target_filename(t), outdir, t.get_aliases(), - should_strip, t.install_rpath] - d.targets.append(i) + # Install primary build output (library/executable/jar, etc) + # Done separately because of strip/aliases/rpath + if outdirs[0] is not False: + i = [self.get_target_filename(t), outdirs[0], + t.get_aliases(), should_strip, t.install_rpath] + d.targets.append(i) + # Install secondary outputs. Only used for Vala right now. + if num_outdirs > 1: + for output, outdir in zip(t.get_outputs()[1:], outdirs[1:]): + # User requested that we not install this output + if outdir is False: + continue + f = os.path.join(self.get_target_dir(t), output) + d.targets.append([f, outdir, {}, False, None]) elif isinstance(t, build.CustomTarget): - for output in t.get_outputs(): - f = os.path.join(self.get_target_dir(t), output) - d.targets.append([f, outdir, {}, False, None]) + # If only one install_dir is specified, assume that all + # outputs will be installed into it. This is for + # backwards-compatibility and because it makes sense to + # avoid repetition since this is a common use-case. + # + # To selectively install only some outputs, pass `false` as + # the install_dir for the corresponding output by index + if num_outdirs == 1 and num_out > 1: + for output in t.get_outputs(): + f = os.path.join(self.get_target_dir(t), output) + d.targets.append([f, outdirs[0], {}, False, None]) + else: + for output, outdir in zip(t.get_outputs(), outdirs): + # User requested that we not install this output + if outdir is False: + continue + f = os.path.join(self.get_target_dir(t), output) + d.targets.append([f, outdir, {}, False, None]) def generate_custom_install_script(self, d): d.install_scripts = self.build.install_scripts @@ -1029,10 +1065,12 @@ int dummy; # Without this, it will write it inside c_out_dir args += ['--vapi', os.path.join('..', target.vala_vapi)] valac_outputs.append(vapiname) + target.outputs += [target.vala_header, target.vala_vapi] if isinstance(target.vala_gir, str): girname = os.path.join(self.get_target_dir(target), target.vala_gir) args += ['--gir', os.path.join('..', target.vala_gir)] valac_outputs.append(girname) + target.outputs.append(target.vala_gir) if self.get_option_for_target('werror', target): args += valac.get_werror_args() for d in target.get_external_deps(): diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 1246f3e..ef5ea5f 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -19,7 +19,7 @@ from . import environment from . import dependencies from . import mlog from .mesonlib import File, MesonException -from .mesonlib import flatten, stringlistify, classify_unity_sources +from .mesonlib import flatten, typeslistify, stringlistify, classify_unity_sources from .mesonlib import get_filenames_templates_dict, substitute_values from .environment import for_windows, for_darwin from .compilers import is_object, clike_langs, sort_clike, lang_suffixes @@ -318,6 +318,9 @@ class BuildTarget(Target): self.name_prefix_set = False self.name_suffix_set = False self.filename = 'no_name' + # The list of all files outputted by this target. Useful in cases such + # as Vala which generates .vapi and .h besides the compiled output. + self.outputs = [self.filename] self.need_install = False self.pch = {} self.extra_args = {} @@ -544,7 +547,7 @@ class BuildTarget(Target): return result def get_custom_install_dir(self): - return self.custom_install_dir + return self.install_dir def process_kwargs(self, kwargs, environment): super().process_kwargs(kwargs) @@ -591,7 +594,7 @@ class BuildTarget(Target): if not isinstance(self, Executable): self.vala_header = kwargs.get('vala_header', self.name + '.h') self.vala_vapi = kwargs.get('vala_vapi', self.name + '.vapi') - self.vala_gir = kwargs.get('vala_gir', None) + self.vala_gir = kwargs.get('vala_gir', None) dlist = stringlistify(kwargs.get('d_args', [])) self.add_compiler_args('d', dlist) self.link_args = kwargs.get('link_args', []) @@ -617,10 +620,10 @@ class BuildTarget(Target): if not isinstance(deplist, list): deplist = [deplist] self.add_deps(deplist) - self.custom_install_dir = kwargs.get('install_dir', None) - if self.custom_install_dir is not None: - if not isinstance(self.custom_install_dir, str): - raise InvalidArguments('Custom_install_dir must be a string') + # If an item in this list is False, the output corresponding to + # the list index of that item will not be installed + self.install_dir = typeslistify(kwargs.get('install_dir', [None]), + (str, bool)) main_class = kwargs.get('main_class', '') if not isinstance(main_class, str): raise InvalidArguments('Main class must be a string') @@ -691,7 +694,7 @@ class BuildTarget(Target): return self.filename def get_outputs(self): - return [self.filename] + return self.outputs def get_extra_args(self, language): return self.extra_args.get(language, []) @@ -1004,6 +1007,7 @@ class Executable(BuildTarget): self.filename = self.name if self.suffix: self.filename += '.' + self.suffix + self.outputs = [self.filename] def type_suffix(self): return "@exe" @@ -1031,6 +1035,7 @@ class StaticLibrary(BuildTarget): else: self.suffix = 'a' self.filename = self.prefix + self.name + '.' + self.suffix + self.outputs = [self.filename] def type_suffix(self): return "@sta" @@ -1147,6 +1152,7 @@ class SharedLibrary(BuildTarget): if self.suffix is None: self.suffix = suffix self.filename = self.filename_tpl.format(self) + self.outputs = [self.filename] def process_kwargs(self, kwargs, environment): super().process_kwargs(kwargs, environment) @@ -1321,13 +1327,13 @@ class CustomTarget(Target): self.sources = [self.sources] if 'output' not in kwargs: raise InvalidArguments('Missing keyword argument "output".') - self.output = kwargs['output'] - if not isinstance(self.output, list): - self.output = [self.output] + self.outputs = kwargs['output'] + if not isinstance(self.outputs, list): + self.outputs = [self.outputs] # This will substitute values from the input into output and return it. inputs = get_sources_string_names(self.sources) values = get_filenames_templates_dict(inputs, []) - for i in self.output: + for i in self.outputs: if not(isinstance(i, str)): raise InvalidArguments('Output argument not a string.') if '/' in i: @@ -1342,9 +1348,9 @@ class CustomTarget(Target): m = "Output cannot contain @PLAINNAME@ or @BASENAME@ when " \ "there is more than one input (we can't know which to use)" raise InvalidArguments(m) - self.output = substitute_values(self.output, values) + self.outputs = substitute_values(self.outputs, values) self.capture = kwargs.get('capture', False) - if self.capture and len(self.output) != 1: + if self.capture and len(self.outputs) != 1: raise InvalidArguments('Capturing can only output to a single file.') if 'command' not in kwargs: raise InvalidArguments('Missing keyword argument "command".') @@ -1366,12 +1372,14 @@ class CustomTarget(Target): raise InvalidArguments('"install" must be boolean.') if self.install: if 'install_dir' not in kwargs: - raise InvalidArguments('"install_dir" not specified.') - self.install_dir = kwargs['install_dir'] - if not(isinstance(self.install_dir, str)): - raise InvalidArguments('"install_dir" must be a string.') + raise InvalidArguments('"install_dir" must be specified ' + 'when installing a target') + # If an item in this list is False, the output corresponding to + # the list index of that item will not be installed + self.install_dir = typeslistify(kwargs['install_dir'], (str, bool)) else: self.install = False + self.install_dir = [None] self.build_always = kwargs.get('build_always', False) if not isinstance(self.build_always, bool): raise InvalidArguments('Argument build_always must be a boolean.') @@ -1404,10 +1412,10 @@ class CustomTarget(Target): return self.install_dir def get_outputs(self): - return self.output + return self.outputs def get_filename(self): - return self.output[0] + return self.outputs[0] def get_sources(self): return self.sources @@ -1466,6 +1474,7 @@ class Jar(BuildTarget): if not s.endswith('.java'): raise InvalidArguments('Jar source %s is not a java file.' % s) self.filename = self.name + '.jar' + self.outputs = [self.filename] self.java_args = kwargs.get('java_args', []) def get_main_class(self): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 0c6d980..945de6b 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2221,7 +2221,7 @@ class Interpreter(InterpreterBase): if 'install_mode' not in kwargs: return None install_mode = [] - mode = mesonlib.stringintlistify(kwargs.get('install_mode', [])) + mode = mesonlib.typeslistify(kwargs.get('install_mode', []), (str, int)) for m in mode: # We skip any arguments that are set to `false` if m is False: diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 7a5b962..ef169c1 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -454,25 +454,22 @@ def replace_if_different(dst, dst_tmp): else: os.unlink(dst_tmp) -def stringintlistify(item): - if isinstance(item, (str, int)): +def typeslistify(item, types): + ''' + Ensure that type(@item) is one of @types or a + list of items all of which are of type @types + ''' + if isinstance(item, types): item = [item] if not isinstance(item, list): - raise MesonException('Item must be a list, a string, or an int') + raise MesonException('Item must be a list or one of {!r}'.format(types)) for i in item: - if not isinstance(i, (str, int, type(None))): - raise MesonException('List item must be a string or an int') + if i is not None and not isinstance(i, types): + raise MesonException('List item must be one of {!r}'.format(types)) return item def stringlistify(item): - if isinstance(item, str): - item = [item] - if not isinstance(item, list): - raise MesonException('Item is not a list') - for i in item: - if not isinstance(i, str): - raise MesonException('List item not a string.') - return item + return typeslistify(item, str) def expand_arguments(args): expended_args = [] diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 4b366bf..2f5bfb9 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -999,7 +999,7 @@ class GnomeModule(ExtensionModule): target.get_subdir()) outdir = os.path.join(state.environment.get_build_dir(), target.get_subdir()) - outfile = target.output[0][:-5] # Strip .vapi + outfile = target.get_outputs()[0][:-5] # Strip .vapi ret.append('--vapidir=' + outdir) ret.append('--girdir=' + outdir) ret.append('--pkg=' + outfile) @@ -1066,7 +1066,7 @@ class GnomeModule(ExtensionModule): link_with += self._get_vapi_link_with(i.held_object) subdir = os.path.join(state.environment.get_build_dir(), i.held_object.get_subdir()) - gir_file = os.path.join(subdir, i.held_object.output[0]) + gir_file = os.path.join(subdir, i.held_object.get_outputs()[0]) cmd.append(gir_file) else: raise MesonException('Input must be a str or GirTarget') diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index e46c239..e79371f 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -76,8 +76,9 @@ class PkgConfigModule(ExtensionModule): if isinstance(l, str): yield l else: - if l.custom_install_dir: - yield '-L${prefix}/%s ' % l.custom_install_dir + install_dir = l.get_custom_install_dir()[0] + if install_dir: + yield '-L${prefix}/%s ' % install_dir else: yield '-L${libdir}' lname = self._get_lname(l, msg, pcfile) -- cgit v1.1 From 98b1ce1cd9f3220ec6a06ef2bfa122518a9245ed Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 14 Mar 2017 15:15:13 +0530 Subject: Fix custom directory installation of import library When install_dir was set for a shared_library, the import library would not be installed at all, which is unintended. Instead, install it into the custom directory if it is set, otherwise install it in the default import library installation directory. Includes a test for this. --- mesonbuild/backend/ninjabackend.py | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 77b2d1d..464cdcb 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -632,23 +632,13 @@ int dummy; should_strip = self.get_option_for_target('strip', t) # Find the installation directory. outdirs = t.get_custom_install_dir() + custom_install_dir = False if outdirs[0] is not None and outdirs[0] is not True: # Either the value is set, or is set to False which means # we want this specific output out of many outputs to not # be installed. - pass + custom_install_dir = True elif isinstance(t, build.SharedLibrary): - # On toolchains/platforms that use an import library for - # linking (separate from the shared library with all the - # code), we need to install that too (dll.a/.lib). - if t.get_import_filename(): - # Install the import library. - i = [self.get_target_filename_for_linking(t), - self.environment.get_import_lib_dir(), - # It has no aliases, should not be stripped, and - # doesn't have an install_rpath - {}, False, ''] - d.targets.append(i) outdirs[0] = self.environment.get_shared_lib_dir() elif isinstance(t, build.StaticLibrary): outdirs[0] = self.environment.get_static_lib_dir() @@ -672,6 +662,24 @@ int dummy; i = [self.get_target_filename(t), outdirs[0], t.get_aliases(), should_strip, t.install_rpath] d.targets.append(i) + # On toolchains/platforms that use an import library for + # linking (separate from the shared library with all the + # code), we need to install that too (dll.a/.lib). + if isinstance(t, build.SharedLibrary) and t.get_import_filename(): + if custom_install_dir: + # If the DLL is installed into a custom directory, + # install the import library into the same place so + # it doesn't go into a surprising place + implib_install_dir = outdirs[0] + else: + implib_install_dir = self.environment.get_import_lib_dir() + # Install the import library. + i = [self.get_target_filename_for_linking(t), + implib_install_dir, + # It has no aliases, should not be stripped, and + # doesn't have an install_rpath + {}, False, ''] + d.targets.append(i) # Install secondary outputs. Only used for Vala right now. if num_outdirs > 1: for output, outdir in zip(t.get_outputs()[1:], outdirs[1:]): -- cgit v1.1 From a4255d74f54f6d74b12f0cadcaa29a7584079503 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 14 Mar 2017 19:17:24 +0530 Subject: Don't generate import library for shared modules Also add a test for this on all platforms. --- mesonbuild/build.py | 1 + 1 file changed, 1 insertion(+) (limited to 'mesonbuild') diff --git a/mesonbuild/build.py b/mesonbuild/build.py index ef5ea5f..973d8e9 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1246,6 +1246,7 @@ class SharedModule(SharedLibrary): if 'soversion' in kwargs: raise MesonException('Shared modules must not specify the soversion kwarg.') super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) + self.import_filename = None class CustomTarget(Target): known_kwargs = {'input': True, -- cgit v1.1 From aa3480dabaaf8fe164ae9fa5115cc092277245f5 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Thu, 16 Mar 2017 20:33:50 +0530 Subject: Reduce an indent level in the install for loop if not t.should_install(): continue No logic changes at all. Also improve the message when erroring out about insufficient install_dir: list elements. --- mesonbuild/backend/ninjabackend.py | 156 +++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 77 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 464cdcb..9378a56 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -628,85 +628,87 @@ int dummy; def generate_target_install(self, d): for t in self.build.get_targets().values(): - if t.should_install(): + if not t.should_install(): + continue + # Find the installation directory. + outdirs = t.get_custom_install_dir() + custom_install_dir = False + if outdirs[0] is not None and outdirs[0] is not True: + # Either the value is set, or is set to False which means + # we want this specific output out of many outputs to not + # be installed. + custom_install_dir = True + elif isinstance(t, build.SharedLibrary): + outdirs[0] = self.environment.get_shared_lib_dir() + elif isinstance(t, build.StaticLibrary): + outdirs[0] = self.environment.get_static_lib_dir() + elif isinstance(t, build.Executable): + outdirs[0] = self.environment.get_bindir() + else: + assert(isinstance(t, build.BuildTarget)) + # XXX: Add BuildTarget-specific install dir cases here + outdirs[0] = self.environment.get_libdir() + # Sanity-check the outputs and install_dirs + num_outdirs, num_out = len(outdirs), len(t.get_outputs()) + if num_outdirs != 1 and num_outdirs != num_out: + m = 'Target {!r} has {} outputs: {!r}, but only {} "install_dir"s were found.\n' \ + "Pass 'false' for outputs that should not be installed and 'true' for\n" \ + 'using the default installation directory for an output.' + raise MesonException(m.format(t.name, num_out, t.get_outputs(), num_outdirs)) + # Install the target output(s) + if isinstance(t, build.BuildTarget): should_strip = self.get_option_for_target('strip', t) - # Find the installation directory. - outdirs = t.get_custom_install_dir() - custom_install_dir = False - if outdirs[0] is not None and outdirs[0] is not True: - # Either the value is set, or is set to False which means - # we want this specific output out of many outputs to not - # be installed. - custom_install_dir = True - elif isinstance(t, build.SharedLibrary): - outdirs[0] = self.environment.get_shared_lib_dir() - elif isinstance(t, build.StaticLibrary): - outdirs[0] = self.environment.get_static_lib_dir() - elif isinstance(t, build.Executable): - outdirs[0] = self.environment.get_bindir() - else: - assert(isinstance(t, build.BuildTarget)) - # XXX: Add BuildTarget-specific install dir cases here - outdirs[0] = self.environment.get_libdir() - # Sanity-check the outputs and install_dirs - num_outdirs, num_out = len(outdirs), len(t.get_outputs()) - if num_outdirs != 1 and num_outdirs != num_out: - raise MesonException('Target {!r} has {} outputs, but only ' - '{} "install_dir"s were specified' - ''.format(t.name, num_out, num_outdirs)) - # Install the target output(s) - if isinstance(t, build.BuildTarget): - # Install primary build output (library/executable/jar, etc) - # Done separately because of strip/aliases/rpath - if outdirs[0] is not False: - i = [self.get_target_filename(t), outdirs[0], - t.get_aliases(), should_strip, t.install_rpath] + # Install primary build output (library/executable/jar, etc) + # Done separately because of strip/aliases/rpath + if outdirs[0] is not False: + i = [self.get_target_filename(t), outdirs[0], + t.get_aliases(), should_strip, t.install_rpath] + d.targets.append(i) + # On toolchains/platforms that use an import library for + # linking (separate from the shared library with all the + # code), we need to install that too (dll.a/.lib). + if isinstance(t, build.SharedLibrary) and t.get_import_filename(): + if custom_install_dir: + # If the DLL is installed into a custom directory, + # install the import library into the same place so + # it doesn't go into a surprising place + implib_install_dir = outdirs[0] + else: + implib_install_dir = self.environment.get_import_lib_dir() + # Install the import library. + i = [self.get_target_filename_for_linking(t), + implib_install_dir, + # It has no aliases, should not be stripped, and + # doesn't have an install_rpath + {}, False, ''] d.targets.append(i) - # On toolchains/platforms that use an import library for - # linking (separate from the shared library with all the - # code), we need to install that too (dll.a/.lib). - if isinstance(t, build.SharedLibrary) and t.get_import_filename(): - if custom_install_dir: - # If the DLL is installed into a custom directory, - # install the import library into the same place so - # it doesn't go into a surprising place - implib_install_dir = outdirs[0] - else: - implib_install_dir = self.environment.get_import_lib_dir() - # Install the import library. - i = [self.get_target_filename_for_linking(t), - implib_install_dir, - # It has no aliases, should not be stripped, and - # doesn't have an install_rpath - {}, False, ''] - d.targets.append(i) - # Install secondary outputs. Only used for Vala right now. - if num_outdirs > 1: - for output, outdir in zip(t.get_outputs()[1:], outdirs[1:]): - # User requested that we not install this output - if outdir is False: - continue - f = os.path.join(self.get_target_dir(t), output) - d.targets.append([f, outdir, {}, False, None]) - elif isinstance(t, build.CustomTarget): - # If only one install_dir is specified, assume that all - # outputs will be installed into it. This is for - # backwards-compatibility and because it makes sense to - # avoid repetition since this is a common use-case. - # - # To selectively install only some outputs, pass `false` as - # the install_dir for the corresponding output by index - if num_outdirs == 1 and num_out > 1: - for output in t.get_outputs(): - f = os.path.join(self.get_target_dir(t), output) - d.targets.append([f, outdirs[0], {}, False, None]) - else: - for output, outdir in zip(t.get_outputs(), outdirs): - # User requested that we not install this output - if outdir is False: - continue - f = os.path.join(self.get_target_dir(t), output) - d.targets.append([f, outdir, {}, False, None]) + # Install secondary outputs. Only used for Vala right now. + if num_outdirs > 1: + for output, outdir in zip(t.get_outputs()[1:], outdirs[1:]): + # User requested that we not install this output + if outdir is False: + continue + f = os.path.join(self.get_target_dir(t), output) + d.targets.append([f, outdir, {}, False, None]) + elif isinstance(t, build.CustomTarget): + # If only one install_dir is specified, assume that all + # outputs will be installed into it. This is for + # backwards-compatibility and because it makes sense to + # avoid repetition since this is a common use-case. + # + # To selectively install only some outputs, pass `false` as + # the install_dir for the corresponding output by index + if num_outdirs == 1 and num_out > 1: + for output in t.get_outputs(): + f = os.path.join(self.get_target_dir(t), output) + d.targets.append([f, outdirs[0], {}, False, None]) + else: + for output, outdir in zip(t.get_outputs(), outdirs): + # User requested that we not install this output + if outdir is False: + continue + f = os.path.join(self.get_target_dir(t), output) + d.targets.append([f, outdir, {}, False, None]) def generate_custom_install_script(self, d): d.install_scripts = self.build.install_scripts -- cgit v1.1