aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/build.py
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2017-03-13 03:45:10 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2017-04-04 14:59:13 +0530
commit57cb1f9aad0928e167018ba886e2d8c06225b515 (patch)
treefd5a35a19ef7d4f384b3f14ea21494fd0a139aae /mesonbuild/build.py
parent99649e66908693c58fa0c015dbcce19ad8f55b19 (diff)
downloadmeson-57cb1f9aad0928e167018ba886e2d8c06225b515.zip
meson-57cb1f9aad0928e167018ba886e2d8c06225b515.tar.gz
meson-57cb1f9aad0928e167018ba886e2d8c06225b515.tar.bz2
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
Diffstat (limited to 'mesonbuild/build.py')
-rw-r--r--mesonbuild/build.py49
1 files changed, 29 insertions, 20 deletions
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):