aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--mesonbuild/backend/backends.py13
-rw-r--r--mesonbuild/backend/vs2010backend.py106
-rw-r--r--mesonbuild/build.py10
-rw-r--r--mesonbuild/compilers.py40
-rw-r--r--mesonbuild/coredata.py2
-rw-r--r--mesonbuild/dependencies.py19
-rw-r--r--mesonbuild/environment.py3
-rw-r--r--mesonbuild/interpreter.py89
-rw-r--r--mesonbuild/mconf.py1
-rw-r--r--mesonbuild/mesonlib.py4
-rw-r--r--mesonbuild/mesonmain.py2
-rw-r--r--mesonbuild/optinterpreter.py2
-rw-r--r--mesonbuild/scripts/meson_install.py16
-rw-r--r--test cases/common/42 string formatting/meson.build6
-rw-r--r--test cases/common/68 number arithmetic/meson.build3
-rw-r--r--test cases/common/91 plusassign/meson.build25
-rw-r--r--test cases/frameworks/4 qt5/meson.build22
-rw-r--r--test cases/linuxlike/2 external library/meson.build5
19 files changed, 256 insertions, 118 deletions
diff --git a/README.md b/README.md
index cd20b77..bd166eb 100644
--- a/README.md
+++ b/README.md
@@ -18,8 +18,10 @@ options here>`.
Meson is also available from
[PyPi](https://pypi.python.org/pypi/meson), so it can be installed
-with `pip install meson` (this does not require a source checkout, pip
-will download the package automatically).
+with `pip3 install meson` (this does not require a source checkout,
+pip will download the package automatically). The exact command to
+type to install with pip can very between systems, be sure to use the
+Python 3 version of pip.
####Running
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 5c2f709..3a24f30 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -142,7 +142,7 @@ class Backend():
return os.path.relpath(os.path.join('dummyprefixdir', todir),\
os.path.join('dummyprefixdir', fromdir))
- def flatten_object_list(self, target, proj_dir_to_build_root=''):
+ def flatten_object_list(self, target, proj_dir_to_build_root='', include_dir_names=True):
obj_list = []
for obj in target.get_objects():
if isinstance(obj, str):
@@ -150,7 +150,7 @@ class Backend():
self.build_to_src, target.get_subdir(), obj)
obj_list.append(o)
elif isinstance(obj, build.ExtractedObjects):
- obj_list += self.determine_ext_objs(obj, proj_dir_to_build_root)
+ obj_list += self.determine_ext_objs(obj, proj_dir_to_build_root, include_dir_names)
else:
raise MesonException('Unknown data type in object list.')
return obj_list
@@ -207,7 +207,7 @@ class Backend():
return c
raise RuntimeError('Unreachable code')
- def determine_ext_objs(self, extobj, proj_dir_to_build_root=''):
+ def determine_ext_objs(self, extobj, proj_dir_to_build_root='', include_dir_names=True):
result = []
targetdir = self.get_target_private_dir(extobj.target)
suffix = '.' + self.environment.get_object_suffix()
@@ -221,7 +221,12 @@ class Backend():
if pathsegs[0] == 'subprojects':
pathsegs = pathsegs[2:]
fixedpath = os.sep.join(pathsegs)
- objbase = osrc.fname.replace('/', '_').replace('\\', '_')
+ if include_dir_names:
+ objbase = osrc_base.replace('/', '_').replace('\\', '_')
+ else:
+ # vs2010 backend puts all obj files without directory prefixes into build dir, so just
+ # use the file name without a directory (will be stripped by os.path.basename() below).
+ objbase = osrc_base
objname = os.path.join(proj_dir_to_build_root,
targetdir, os.path.basename(objbase) + suffix)
result.append(objname)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 0d7ac06..84ef8c3 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -36,7 +36,7 @@ class Vs2010Backend(backends.Backend):
super().__init__(build)
self.project_file_version = '10.0.30319.1'
# foo.c compiles to foo.obj, not foo.c.obj
- self.source_suffix_in_obj = False
+ self.source_suffix_in_objs = False
def generate_custom_generator_commands(self, target, parent_node):
all_output_files = []
@@ -116,14 +116,14 @@ class Vs2010Backend(backends.Backend):
result = {}
for o in obj_list:
if isinstance(o, build.ExtractedObjects):
- result[o.target.get_basename()] = True
+ result[o.target.get_id()] = True
return result.keys()
def determine_deps(self, p):
all_deps = {}
target = self.build.targets[p[0]]
if isinstance(target, build.CustomTarget):
- for d in target.dependencies:
+ for d in target.get_target_dependencies():
all_deps[d.get_id()] = True
return all_deps
if isinstance(target, build.RunTarget):
@@ -220,14 +220,21 @@ class Vs2010Backend(backends.Backend):
sources = []
headers = []
objects = []
+ languages = []
for i in srclist:
if self.environment.is_header(i):
headers.append(i)
elif self.environment.is_object(i):
objects.append(i)
- else:
+ elif self.environment.is_source(i):
sources.append(i)
- return (sources, headers, objects)
+ lang = self.lang_from_source_file(i)
+ if lang not in languages:
+ languages.append(lang)
+ else:
+ # Everything that is not an object or source file is considered a header.
+ headers.append(i)
+ return (sources, headers, objects, languages)
def target_to_build_root(self, target):
if target.subdir == '':
@@ -312,16 +319,20 @@ class Vs2010Backend(backends.Backend):
tree = ET.ElementTree(root)
tree.write(ofname, encoding='utf-8', xml_declaration=True)
+ @classmethod
+ def lang_from_source_file(cls, src):
+ ext = src.split('.')[-1]
+ if ext in compilers.c_suffixes:
+ return 'c'
+ if ext in compilers.cpp_suffixes:
+ return 'cpp'
+ raise MesonException('Could not guess language from source file %s.' % src)
+
def add_pch(self, inc_cl, proj_to_src_dir, pch_sources, source_file):
if len(pch_sources) <= 1:
# We only need per file precompiled headers if we have more than 1 language.
return
- if source_file.split('.')[-1] in compilers.c_suffixes:
- lang = 'c'
- elif source_file.split('.')[-1] in compilers.cpp_suffixes:
- lang = 'cpp'
- else:
- return
+ lang = Vs2010Backend.lang_from_source_file(source_file)
header = os.path.join(proj_to_src_dir, pch_sources[lang][0])
pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile')
pch_file.text = header
@@ -330,6 +341,13 @@ class Vs2010Backend(backends.Backend):
pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile')
pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % lang
+ def add_additional_options(self, source_file, parent_node, extra_args, has_additional_options_set):
+ if has_additional_options_set:
+ # We only need per file options if they were not set per project.
+ return
+ lang = Vs2010Backend.lang_from_source_file(source_file)
+ ET.SubElement(parent_node, "AdditionalOptions").text = ' '.join(extra_args[lang]) + ' %(AdditionalOptions)'
+
def gen_vcxproj(self, target, ofname, guid, compiler):
mlog.debug('Generating vcxproj %s.' % target.name)
entrypoint = 'WinMainCRTStartup'
@@ -353,7 +371,7 @@ class Vs2010Backend(backends.Backend):
down = self.target_to_build_root(target)
proj_to_src_root = os.path.join(down, self.build_to_src)
proj_to_src_dir = os.path.join(proj_to_src_root, target.subdir)
- (sources, headers, objects) = self.split_sources(target.sources)
+ (sources, headers, objects, languages) = self.split_sources(target.sources)
buildtype = self.buildtype
project_name = target.name
target_name = target.name
@@ -386,7 +404,7 @@ class Vs2010Backend(backends.Backend):
ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props')
generated_files = self.generate_custom_generator_commands(target, root)
- (gen_src, gen_hdrs, gen_objs) = self.split_sources(generated_files)
+ (gen_src, gen_hdrs, gen_objs, gen_langs) = self.split_sources(generated_files)
direlem = ET.SubElement(root, 'PropertyGroup')
fver = ET.SubElement(direlem, '_ProjectFileVersion')
fver.text = self.project_file_version
@@ -408,28 +426,44 @@ class Vs2010Backend(backends.Backend):
if cur_dir == '':
cur_dir= '.'
inc_dirs.append(cur_dir)
- extra_args = []
- # SUCKS, VS can not handle per-language type flags, so just use
- # them all.
- extra_args += compiler.get_buildtype_args(self.buildtype)
- for l in self.environment.coredata.external_args.values():
- for a in l:
- extra_args.append(a)
- for l in self.build.global_args.values():
- for a in l:
- extra_args.append(a)
- for l in target.extra_args.values():
- for a in l:
- extra_args.append(a)
+
+ extra_args = {'c': [], 'cpp': []}
+ for l, args in self.environment.coredata.external_args.items():
+ if l in extra_args:
+ extra_args[l] += args
+ for l, args in self.build.global_args.items():
+ if l in extra_args:
+ extra_args[l] += args
+ for l, args in target.extra_args.items():
+ if l in extra_args:
+ extra_args[l] += args
+ general_args = compiler.get_buildtype_args(self.buildtype)
# FIXME all the internal flags of VS (optimization etc) are represented
# by their own XML elements. In theory we should split all flags to those
# that have an XML element and those that don't and serialise them
# properly. This is a crapton of work for no real gain, so just dump them
# here.
- extra_args = compiler.get_option_compile_args(self.environment.coredata.compiler_options)
- if len(extra_args) > 0:
- extra_args.append('%(AdditionalOptions)')
- ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(extra_args)
+ general_args += compiler.get_option_compile_args(self.environment.coredata.compiler_options)
+ for d in target.get_external_deps():
+ try:
+ general_args += d.compile_args
+ except AttributeError:
+ pass
+
+ languages += gen_langs
+ has_language_specific_args = any(l != extra_args['c'] for l in extra_args.values())
+ additional_options_set = False
+ if not has_language_specific_args or len(languages) == 1:
+ if len(languages) == 0:
+ extra_args = []
+ else:
+ extra_args = extra_args[languages[0]]
+ extra_args = general_args + extra_args
+ if len(extra_args) > 0:
+ extra_args.append('%(AdditionalOptions)')
+ ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(extra_args)
+ additional_options_set = True
+
for d in target.include_dirs:
for i in d.incdirs:
curdir = os.path.join(d.curdir, i)
@@ -490,9 +524,10 @@ class Vs2010Backend(backends.Backend):
rel_path = self.relpath(lobj.subdir, target.subdir)
linkname = os.path.join(rel_path, lobj.get_import_filename())
additional_links.append(linkname)
- for o in self.flatten_object_list(target, down):
+ additional_objects = []
+ for o in self.flatten_object_list(target, down, include_dir_names=False):
assert(isinstance(o, str))
- additional_links.append(o)
+ additional_objects.append(o)
if len(additional_links) > 0:
additional_links.append('%(AdditionalDependencies)')
ET.SubElement(link, 'AdditionalDependencies').text = ';'.join(additional_links)
@@ -530,10 +565,12 @@ class Vs2010Backend(backends.Backend):
relpath = s.rel_to_builddir(proj_to_src_root)
inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath)
self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s)
+ self.add_additional_options(s, inc_cl, extra_args, additional_options_set)
for s in gen_src:
relpath = self.relpath(s, target.subdir)
inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath)
self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s)
+ self.add_additional_options(s, inc_cl, extra_args, additional_options_set)
for lang in pch_sources:
header, impl, suffix = pch_sources[lang]
relpath = os.path.join(proj_to_src_dir, impl)
@@ -546,14 +583,17 @@ class Vs2010Backend(backends.Backend):
# MSBuild searches for the header relative from the implementation, so we have to use
# just the file name instead of the relative path to the file.
pch_file.text = os.path.split(header)[1]
+ self.add_additional_options(impl, inc_cl, extra_args, additional_options_set)
- if len(objects) > 0:
+ if len(objects) + len(additional_objects) > 0:
# Do not add gen_objs to project file. Those are automatically used by MSBuild, because they are part of
# the CustomBuildStep Outputs.
inc_objs = ET.SubElement(root, 'ItemGroup')
for s in objects:
relpath = s.rel_to_builddir(proj_to_src_root)
ET.SubElement(inc_objs, 'Object', Include=relpath)
+ for s in additional_objects:
+ ET.SubElement(inc_objs, 'Object', Include=s)
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
# Reference the regen target.
ig = ET.SubElement(root, 'ItemGroup')
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 315e4bc..ab9d0d5 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -806,6 +806,16 @@ class CustomTarget:
def get_id(self):
return self.name + self.type_suffix()
+ def get_target_dependencies(self):
+ deps = self.dependencies[:]
+ deps += self.extra_depends
+ for c in self.sources:
+ if hasattr(c, 'held_object'):
+ c = c.held_object
+ if isinstance(c, BuildTarget) or isinstance(c, CustomTarget):
+ deps.append(c)
+ return deps
+
def process_kwargs(self, kwargs):
self.sources = kwargs.get('input', [])
if not isinstance(self.sources, list):
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index f3ddf8d..cc554c4 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -190,7 +190,7 @@ class Compiler():
def unix_compile_flags_to_native(self, args):
return args
- def find_library(self, libname):
+ def find_library(self, libname, extra_dirs):
raise EnvironmentException('Language {} does not support library finding.'.format(self.language))
class CCompiler(Compiler):
@@ -298,6 +298,9 @@ class CCompiler(Compiler):
def get_pch_name(self, header_name):
return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix()
+ def get_linker_search_args(self, dirname):
+ return ['-L'+dirname]
+
def sanity_check(self, work_dir):
mlog.debug('Sanity testing C compiler:', ' '.join(self.exelist))
mlog.debug('Is cross compiler: %s.' % str(self.is_cross))
@@ -566,14 +569,17 @@ void bar() {
'''
return self.compiles(templ % (prefix, typename), extra_args)
- def find_library(self, libname):
+ def find_library(self, libname, extra_dirs):
code = '''int main(int argc, char **argv) {
return 0;
}
'''
- linkarg = '-l' + libname
- if self.links(code, extra_args=[linkarg]):
- return linkarg
+ args = []
+ for i in extra_dirs:
+ args += self.get_linker_search_args(i)
+ args.append('-l' + libname)
+ if self.links(code, extra_args=args):
+ return args
return None
def thread_flags(self):
@@ -1144,6 +1150,9 @@ class VisualStudioCCompiler(CCompiler):
def get_linker_output_args(self, outputname):
return ['/OUT:' + outputname]
+ def get_linker_search_args(self, dirname):
+ return ['/LIBPATH:' + dirname]
+
def get_pic_args(self):
return [] # PIC is handled by the loader on Windows
@@ -1175,6 +1184,19 @@ class VisualStudioCCompiler(CCompiler):
def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
return []
+ def find_library(self, libname, extra_dirs):
+ code = '''int main(int argc, char **argv) {
+ return 0;
+}
+ '''
+ args = []
+ for i in extra_dirs:
+ args += self.get_linker_search_args(i)
+ args.append(libname + '.lib')
+ if self.links(code, extra_args=args):
+ return args
+ return None
+
# FIXME, no idea what these should be.
def thread_flags(self):
return []
@@ -1198,7 +1220,13 @@ class VisualStudioCCompiler(CCompiler):
i = '/LIBPATH:' + i[2:]
# Translate GNU-style -lfoo library name to the import library
if i.startswith('-l'):
- i = i[2:] + '.lib'
+ name = i[2:]
+ if name in ('m', 'c'):
+ # With MSVC, these are provided by the C runtime which is
+ # linked in by default
+ continue
+ else:
+ i = name + '.lib'
result.append(i)
return result
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 2a73577..9e927e3 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -28,6 +28,7 @@ builtin_options = {'buildtype': True,
'unity': True,
'prefix': True,
'libdir' : True,
+ 'libexecdir' : True,
'bindir' : True,
'includedir' : True,
'datadir' : True,
@@ -159,6 +160,7 @@ class CoreData():
def init_builtins(self, options):
self.builtin_options['prefix'] = UserStringOption('prefix', 'Installation prefix', options.prefix)
self.builtin_options['libdir'] = UserStringOption('libdir', 'Library dir', options.libdir)
+ self.builtin_options['libexecdir'] = UserStringOption('libexecdir', 'Library executables dir', options.libexecdir)
self.builtin_options['bindir'] = UserStringOption('bindir', 'Executable dir', options.bindir)
self.builtin_options['includedir'] = UserStringOption('includedir', 'Include dir', options.includedir)
self.builtin_options['datadir'] = UserStringOption('datadir', 'Data directory', options.datadir)
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index ee2dd62..b9f5c89 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -385,30 +385,29 @@ class ExternalProgram():
return self.name
class ExternalLibrary(Dependency):
- def __init__(self, name, fullpath=None, silent=False):
+ def __init__(self, name, link_args=None, silent=False):
super().__init__()
self.name = name
# Rename fullpath to link_args once standalone find_library() gets removed.
- if fullpath is not None:
- if isinstance(fullpath, list):
- self.fullpath = fullpath
+ if link_args is not None:
+ if isinstance(link_args, list):
+ self.link_args = link_args
else:
- self.fullpath = [fullpath]
+ self.link_args = [link_args]
else:
- self.fullpath = fullpath
+ self.link_args = link_args
if not silent:
if self.found():
- mlog.log('Library', mlog.bold(name), 'found:', mlog.green('YES'),
- '(%s)' % self.fullpath)
+ mlog.log('Library', mlog.bold(name), 'found:', mlog.green('YES'))
else:
mlog.log('Library', mlog.bold(name), 'found:', mlog.red('NO'))
def found(self):
- return self.fullpath is not None
+ return self.link_args is not None
def get_link_args(self):
if self.found():
- return self.fullpath
+ return self.link_args
return []
class BoostDependency(Dependency):
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 1586248..61954af 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -590,6 +590,9 @@ class Environment():
def get_libdir(self):
return self.coredata.get_builtin_option('libdir')
+ def get_libexecdir(self):
+ return self.coredata.get_builtin_option('libexecdir')
+
def get_bindir(self):
return self.coredata.get_builtin_option('bindir')
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 2ade18a..04bfa07 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -27,8 +27,6 @@ from functools import wraps
import importlib
-find_lib_deprecation_printed = False
-
class InterpreterException(coredata.MesonException):
pass
@@ -762,8 +760,14 @@ class CompilerHolder(InterpreterObject):
required = kwargs.get('required', True)
if not isinstance(required, bool):
raise InterpreterException('required must be boolean.')
- linkarg = self.compiler.find_library(libname)
- lib = dependencies.ExternalLibrary(libname, linkarg)
+ search_dirs = kwargs.get('dirs', [])
+ for i in search_dirs:
+ if not os.path.isabs(i):
+ raise InvalidCode('Search directory %s is not an absolute path.' % i)
+ linkargs = self.compiler.find_library(libname, search_dirs)
+ if required and linkargs is None:
+ raise InterpreterException('Library %s not found'.format(libname))
+ lib = dependencies.ExternalLibrary(libname, linkargs)
return ExternalLibraryHolder(lib)
class ModuleState:
@@ -921,7 +925,7 @@ class Interpreter():
mesonfile = os.path.join(self.source_root, self.subdir, environment.build_filename)
if not os.path.isfile(mesonfile):
raise InvalidArguments('Missing Meson file in %s' % mesonfile)
- code = open(mesonfile).read()
+ code = open(mesonfile, encoding='utf8').read()
if len(code.strip()) == 0:
raise InvalidCode('Builder file is empty.')
assert(isinstance(code, str))
@@ -1542,40 +1546,7 @@ class Interpreter():
return progobj
def func_find_library(self, node, args, kwargs):
- global find_lib_deprecation_printed
- if not find_lib_deprecation_printed:
- find_lib_deprecation_printed = True
- mlog.log(mlog.red('DEPRECATION:'), 'find_library() is deprecated, use the corresponding method in compiler object instead.')
- self.validate_arguments(args, 1, [str])
- required = kwargs.get('required', True)
- if not isinstance(required, bool):
- raise InvalidArguments('"required" argument must be a boolean.')
- libname = args[0]
- # We do not cache found libraries because they can come
- # and go between invocations wildly. As an example we
- # may find the 64 bit version but need instead the 32 bit
- # one that is not installed. If we cache the found path
- # then we will never found the new one if it get installed.
- # This causes a bit of a slowdown as libraries are rechecked
- # on every regen, but since it is a fast operation it should be
- # ok.
- if 'dirs' in kwargs:
- search_dirs = kwargs['dirs']
- if not isinstance(search_dirs, list):
- search_dirs = [search_dirs]
- for i in search_dirs:
- if not isinstance(i, str):
- raise InvalidCode('Directory entry is not a string.')
- if not os.path.isabs(i):
- raise InvalidCode('Search directory %s is not an absolute path.' % i)
- else:
- search_dirs = None
- result = self.environment.find_library(libname, search_dirs)
- extlib = dependencies.ExternalLibrary(libname, result)
- libobj = ExternalLibraryHolder(extlib)
- if required and not libobj.found():
- raise InvalidArguments('External library "%s" not found.' % libname)
- return libobj
+ mlog.log(mlog.red('DEPRECATION:'), 'find_library() is removed, use the corresponding method in compiler object instead.')
def func_dependency(self, node, args, kwargs):
self.validate_arguments(args, 1, [str])
@@ -1812,7 +1783,7 @@ class Interpreter():
absname = os.path.join(self.environment.get_source_dir(), buildfilename)
if not os.path.isfile(absname):
raise InterpreterException('Nonexistant build def file %s.' % buildfilename)
- code = open(absname).read()
+ code = open(absname, encoding='utf8').read()
assert(isinstance(code, str))
try:
codeblock = mparser.Parser(code).parse()
@@ -2046,6 +2017,30 @@ class Interpreter():
reduced_pos = [reduced_pos]
return (reduced_pos, reduced_kw)
+ def bool_method_call(self, obj, method_name, args):
+ obj = self.to_native(obj)
+ (posargs, _) = self.reduce_arguments(args)
+ if method_name == 'to_string':
+ if len(posargs) == 0:
+ if obj == True:
+ return 'true'
+ else:
+ return 'false'
+ elif len(posargs) == 2 and isinstance(posargs[0], str) and isinstance(posargs[1], str):
+ if obj == True:
+ return posargs[0]
+ else:
+ return posargs[1]
+ else:
+ raise InterpreterException('bool.to_string() must have either no arguments or exactly two string arguments.')
+ elif method_name == 'to_int':
+ if obj == True:
+ return 1
+ else:
+ return 0
+ else:
+ raise InterpreterException('Unknown method "%s" for a boolean.' % method_name)
+
def string_method_call(self, obj, method_name, args):
obj = self.to_native(obj)
(posargs, _) = self.reduce_arguments(args)
@@ -2118,6 +2113,8 @@ class Interpreter():
obj = obj.get_value()
if isinstance(obj, str):
return self.string_method_call(obj, method_name, args)
+ if isinstance(obj, bool):
+ return self.bool_method_call(obj, method_name, args)
if isinstance(obj, list):
return self.array_method_call(obj, method_name, self.reduce_arguments(args)[0])
if not isinstance(obj, InterpreterObject):
@@ -2198,8 +2195,16 @@ class Interpreter():
# Remember that all variables are immutable. We must always create a
# full new variable and then assign it.
old_variable = self.get_variable(varname)
- if not isinstance(old_variable, list):
- raise InvalidArguments('The += operator currently only works with arrays.')
+ if isinstance(old_variable, str):
+ if not isinstance(addition, str):
+ raise InvalidArguments('The += operator requires a string on the right hand side if the variable on the left is a string')
+ new_value = old_variable + addition
+ elif isinstance(old_variable, int):
+ if not isinstance(addition, int):
+ raise InvalidArguments('The += operator requires an int on the right hand side if the variable on the left is an int')
+ new_value = old_variable + addition
+ elif not isinstance(old_variable, list):
+ raise InvalidArguments('The += operator currently only works with arrays, strings or ints ')
# Add other data types here.
else:
if isinstance(addition, list):
diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py
index 03cbe55..72b3fbe 100644
--- a/mesonbuild/mconf.py
+++ b/mesonbuild/mconf.py
@@ -154,6 +154,7 @@ class Conf:
parr = []
parr.append(['prefix', 'Install prefix', self.coredata.get_builtin_option('prefix'), ''])
parr.append(['libdir', 'Library directory', self.coredata.get_builtin_option('libdir'), ''])
+ parr.append(['libexecdir', 'Library executables directory', self.coredata.get_builtin_option('libexecdir'), ''])
parr.append(['bindir', 'Binary directory', self.coredata.get_builtin_option('bindir'), ''])
parr.append(['includedir', 'Header directory', self.coredata.get_builtin_option('includedir'), ''])
parr.append(['datadir', 'Data directory', self.coredata.get_builtin_option('datadir'), ''])
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index ac605bf..2087eee 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -173,6 +173,10 @@ def default_libdir():
return 'lib64'
return 'lib'
+def default_libexecdir():
+ # There is no way to auto-detect this, so it must be set at build time
+ return 'libexec'
+
def get_library_dirs():
if is_windows():
return ['C:/mingw/lib'] # Fixme
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 95e6731..0186006 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -39,6 +39,8 @@ parser.add_argument('--prefix', default=def_prefix, dest='prefix',
help='the installation prefix (default: %(default)s)')
parser.add_argument('--libdir', default=mesonlib.default_libdir(), dest='libdir',
help='the installation subdir of libraries (default: %(default)s)')
+parser.add_argument('--libexecdir', default=mesonlib.default_libexecdir(), dest='libexecdir',
+ help='the installation subdir of library executables (default: %(default)s)')
parser.add_argument('--bindir', default='bin', dest='bindir',
help='the installation subdir of executables (default: %(default)s)')
parser.add_argument('--includedir', default='include', dest='includedir',
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index f0c93ae..30a26ab 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -73,7 +73,7 @@ class OptionInterpreter:
def process(self, option_file):
try:
- ast = mparser.Parser(open(option_file, 'r').read()).parse()
+ ast = mparser.Parser(open(option_file, 'r', encoding='utf8').read()).parse()
except coredata.MesonException as me:
me.file = option_file
raise me
diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py
index 792af6c..8e3d0ca 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -118,10 +118,14 @@ def run_install_script(d):
if platform.system().lower() == 'windows' and suffix != '.bat':
first_line = open(script).readline().strip()
if first_line.startswith('#!'):
- commands = first_line[2:].split('#')[0].strip().split()
- commands[0] = shutil.which(commands[0].split('/')[-1])
- if commands[0] is None:
- raise RuntimeError("Don't know how to run script %s." % script)
+ if shutil.which(first_line[2:]):
+ commands = [first_line[2:]]
+ else:
+ commands = first_line[2:].split('#')[0].strip().split()
+ commands[0] = shutil.which(commands[0].split('/')[-1])
+ if commands[0] is None:
+ commands
+ raise RuntimeError("Don't know how to run script %s." % script)
final_command = commands + [script] + i.cmd_arr[1:]
else:
final_command = i.cmd_arr
@@ -129,8 +133,8 @@ def run_install_script(d):
rc = subprocess.call(final_command, env=child_env)
if rc != 0:
sys.exit(rc)
- except Exception:
- print('Failed to run install script:', i.cmd_arr[0])
+ except:
+ print('Failed to run install script:', *i.cmd_arr)
sys.exit(1)
def is_elf_platform():
diff --git a/test cases/common/42 string formatting/meson.build b/test cases/common/42 string formatting/meson.build
index 99855b3..c2ee151 100644
--- a/test cases/common/42 string formatting/meson.build
+++ b/test cases/common/42 string formatting/meson.build
@@ -45,3 +45,9 @@ assert('#include <foo/bar.h>'.underscorify() == '_include__foo_bar_h_', 'Broken
assert('Do SomeThing 09'.underscorify() == 'Do_SomeThing_09', 'Broken underscorify')
assert('3'.to_int() == 3, 'String int conversion does not work.')
+
+assert(true.to_string() == 'true', 'bool string conversion failed')
+assert(false.to_string() == 'false', 'bool string conversion failed')
+assert(true.to_string('yes', 'no') == 'yes', 'bool string conversion with args failed')
+assert(false.to_string('yes', 'no') == 'no', 'bool string conversion with args failed')
+assert('@0@'.format(true) == 'true', 'bool string formatting failed')
diff --git a/test cases/common/68 number arithmetic/meson.build b/test cases/common/68 number arithmetic/meson.build
index 3872a11..4b98d73 100644
--- a/test cases/common/68 number arithmetic/meson.build
+++ b/test cases/common/68 number arithmetic/meson.build
@@ -32,3 +32,6 @@ assert(not(3 > 4), 'Gt broken')
assert(4 >= 3, 'Gte broken')
assert(not(3 >= 4), 'Gte broken')
assert(3 >= 3, 'Gte broken')
+
+assert(true.to_int() == 1,'bool to_int() broken')
+assert(false.to_int() == 0,'bool to_int() broken')
diff --git a/test cases/common/91 plusassign/meson.build b/test cases/common/91 plusassign/meson.build
index c1e47e0..ac477e7 100644
--- a/test cases/common/91 plusassign/meson.build
+++ b/test cases/common/91 plusassign/meson.build
@@ -43,3 +43,28 @@ x += x
if x.length() != 4
error('Incorrect selfappend.')
endif
+
+# += on strings
+
+bra = 'bra'
+foo = 'A'
+foo += bra
+foo += 'cada'
+foo += bra
+assert (foo == 'Abracadabra', 'string += failure [@0@]'.format(foo))
+assert (bra == 'bra', 'string += modified right argument!')
+foo += ' ' + foo
+assert (foo == 'Abracadabra Abracadabra', 'string += failure [@0@]'.format(foo))
+
+# += on ints
+
+foo = 5
+foo += 6
+assert (foo == 11, 'int += failure [@0@]'.format(foo))
+bar = 99
+foo += bar
+assert (foo == 110, 'int += failure [@0@]'.format(foo))
+assert (bar == 99, 'int += modified right argument"')
+bar += foo + 1
+assert (bar == 210, 'int += failure [@0@]'.format(bar))
+assert (foo == 110, 'int += modified right argument"')
diff --git a/test cases/frameworks/4 qt5/meson.build b/test cases/frameworks/4 qt5/meson.build
index bce9dbd..cfea5ba 100644
--- a/test cases/frameworks/4 qt5/meson.build
+++ b/test cases/frameworks/4 qt5/meson.build
@@ -4,15 +4,15 @@ qt5 = import('qt5')
qt5dep = dependency('qt5', modules : ['Core', 'Gui', 'Widgets'])
prep = qt5.preprocess(
-moc_headers : ['mainWindow.h'], # These need to be fed through the moc tool before use.
-ui_files : 'mainWindow.ui', # XML files that need to be compiled with the uic tol.
-qresources : 'stuff.qrc', # Resource file for rcc compiler.
+ moc_headers : ['mainWindow.h'], # These need to be fed through the moc tool before use.
+ ui_files : 'mainWindow.ui', # XML files that need to be compiled with the uic tol.
+ qresources : 'stuff.qrc', # Resource file for rcc compiler.
)
q5exe = executable('qt5app',
-sources : ['main.cpp', 'mainWindow.cpp', # Sources that don't need preprocessing.
-prep],
-dependencies : qt5dep)
+ sources : ['main.cpp', 'mainWindow.cpp', # Sources that don't need preprocessing.
+ prep],
+ dependencies : qt5dep)
# We need a console test application because some test environments
# do not have an X server.
@@ -20,7 +20,7 @@ dependencies : qt5dep)
qt5core = dependency('qt5', modules : 'Core')
qt5coreapp = executable('q5core', 'q5core.cpp',
-dependencies : qt5core)
+ dependencies : qt5core)
test('qt5test', qt5coreapp)
@@ -28,11 +28,11 @@ test('qt5test', qt5coreapp)
# headers but the user must manually include moc
# files from sources.
manpreprocessed = qt5.preprocess(
-moc_sources : 'manualinclude.cpp',
-moc_headers : 'manualinclude.h')
+ moc_sources : 'manualinclude.cpp',
+ moc_headers : 'manualinclude.h')
q5maninclude = executable('q5maninclude',
-sources : ['manualinclude.cpp', manpreprocessed],
-dependencies : qt5core)
+ sources : ['manualinclude.cpp', manpreprocessed],
+ dependencies : qt5core)
test('q5maninclude', q5maninclude)
diff --git a/test cases/linuxlike/2 external library/meson.build b/test cases/linuxlike/2 external library/meson.build
index f83affc..5839c1a 100644
--- a/test cases/linuxlike/2 external library/meson.build
+++ b/test cases/linuxlike/2 external library/meson.build
@@ -1,8 +1,7 @@
project('external library', 'c')
cc = meson.get_compiler('c')
-zlib = find_library('z') # DEPRECATED
-zlib2 = cc.find_library('z') # The modern way.
+zlib = cc.find_library('z')
# Verify that link testing works.
linkcode = '''#include<zlib.h>
@@ -25,7 +24,7 @@ assert(not cc.links(nolinkcode, name : 'Failing link'), 'Linking succeeded when
e = executable('zprog', 'prog.c', dependencies : zlib)
test('libtest', e)
-e2 = executable('zprog_alt', 'prog.c', dependencies : zlib2)
+e2 = executable('zprog_alt', 'prog.c', dependencies : zlib)
test('libtest_alt', e2)
# Test that ext deps work via an internal dep.