aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--authors.txt1
-rwxr-xr-xghwt.py107
-rw-r--r--mesonbuild/backend/backends.py61
-rw-r--r--mesonbuild/backend/ninjabackend.py123
-rw-r--r--mesonbuild/backend/vs2010backend.py32
-rw-r--r--mesonbuild/backend/xcodebackend.py7
-rw-r--r--mesonbuild/build.py12
-rw-r--r--mesonbuild/compilers.py185
-rw-r--r--mesonbuild/coredata.py1
-rw-r--r--mesonbuild/environment.py66
-rw-r--r--mesonbuild/interpreter.py50
-rw-r--r--mesonbuild/mesonlib.py4
-rw-r--r--mesonbuild/mesonmain.py11
-rw-r--r--mesonbuild/mintro.py6
-rw-r--r--mesonbuild/modules/gnome.py10
-rw-r--r--mesonbuild/modules/i18n.py44
-rw-r--r--mesonbuild/scripts/delwithsuffix.py2
-rw-r--r--mesonbuild/scripts/gettext.py65
-rw-r--r--mesonbuild/scripts/gtkdochelper.py12
-rw-r--r--mesonbuild/scripts/meson_exe.py74
-rw-r--r--mesonbuild/scripts/meson_install.py14
-rw-r--r--mesonbuild/scripts/scanbuild.py39
-rw-r--r--mesonbuild/wrap/wrap.py7
-rw-r--r--test cases/common/42 string formatting/meson.build4
-rw-r--r--test cases/common/43 has function/meson.build12
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/meson.build2
-rw-r--r--test cases/frameworks/10 gtk-doc/meson.build4
-rw-r--r--test cases/frameworks/6 gettext/meson.build2
-rw-r--r--test cases/frameworks/6 gettext/po/intltest.pot4
-rw-r--r--test cases/frameworks/6 gettext/po/meson.build3
30 files changed, 681 insertions, 283 deletions
diff --git a/authors.txt b/authors.txt
index d8b0abc..d628368 100644
--- a/authors.txt
+++ b/authors.txt
@@ -33,3 +33,4 @@ Nicolas Schneider
Luke Adams
Rogiel Sulzbach
Tim-Philipp Müller
+Emmanuele Bassi
diff --git a/ghwt.py b/ghwt.py
new file mode 100755
index 0000000..493b1e2
--- /dev/null
+++ b/ghwt.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python3
+
+# Copyright 2016 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import urllib.request, json, sys, os, shutil, subprocess
+import configparser, hashlib
+
+private_repos = {'meson', 'wrapweb', 'meson-ci'}
+
+def gh_get(url):
+ r = urllib.request.urlopen(url)
+ jd = json.loads(r.read().decode('utf-8'))
+ return jd
+
+def list_projects():
+ jd = gh_get('https://api.github.com/orgs/mesonbuild/repos')
+ entries = [entry['name'] for entry in jd]
+ entries = [e for e in entries if e not in private_repos]
+ entries.sort()
+ for i in entries:
+ print(i)
+ return 0
+
+def unpack(sproj, branch, outdir):
+ subprocess.check_call(['git', 'clone', '-b', branch, 'https://github.com/mesonbuild/%s.git' % sproj, outdir])
+ usfile = os.path.join(outdir, 'upstream.wrap')
+ assert(os.path.isfile(usfile))
+ config = configparser.ConfigParser()
+ config.read(usfile)
+ us_url = config['wrap-file']['source_url']
+ us = urllib.request.urlopen(us_url).read()
+ h = hashlib.sha256()
+ h.update(us)
+ dig = h.hexdigest()
+ should = config['wrap-file']['source_hash']
+ if dig != should:
+ print('Incorrect hash on download.')
+ print(' expected:', dig)
+ print(' obtained:', should)
+ return 1
+ spdir = os.path.split(outdir)[0]
+ ofilename = os.path.join(spdir, config['wrap-file']['source_filename'])
+ ofile = open(ofilename, 'wb')
+ ofile.write(us)
+ if 'lead_directory_missing' in config['wrap-file']:
+ os.mkdir(outdir)
+ shutil.unpack_archive(ofilename, outdir)
+ else:
+ shutil.unpack_archive(ofilename, spdir)
+ extdir = os.path.join(spdir, config['wrap-file']['directory'])
+ assert(os.path.isdir(extdir))
+ shutil.move(os.path.join(outdir, '.git'), extdir)
+ subprocess.check_call(['git', 'reset', '--hard'], cwd=extdir)
+ shutil.rmtree(outdir)
+ shutil.move(extdir, outdir)
+ shutil.rmtree(os.path.join(outdir, '.git'))
+ os.unlink(ofilename)
+
+def install(sproj):
+ sproj_dir = os.path.join('subprojects', sproj)
+ if not os.path.isdir('subprojects'):
+ print('Run this in your source root and make sure there is a subprojects directory in it.')
+ return 1
+ if os.path.isdir(sproj_dir):
+ print('Subproject is already there. To update, nuke the dir and reinstall.')
+ return 1
+ blist = gh_get('https://api.github.com/repos/mesonbuild/%s/branches' % sproj)
+ blist = [b['name'] for b in blist]
+ blist = [b for b in blist if b != 'master']
+ blist.sort()
+ branch = blist[-1]
+ print('Using branch', branch)
+ return unpack(sproj, branch, sproj_dir)
+
+def run(args):
+ if len(args) == 0 or args[0] == '-h' or args[0] == '--help':
+ print(sys.argv[0], 'list/install', 'package_name')
+ return 1
+ command = args[0]
+ args = args[1:]
+ if command == 'list':
+ list_projects()
+ return 0
+ elif command == 'install':
+ if len(args) != 1:
+ print('Install requires exactly one argument.')
+ return 1
+ return install(args[0])
+ else:
+ print('Unknown command')
+ return 1
+
+if __name__ == '__main__':
+ print('This is an emergency wrap downloader. Use only when wrapdb is down.')
+ sys.exit(run(sys.argv[1:]))
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 29966b9..d4a0f99 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -34,6 +34,18 @@ class InstallData():
self.install_scripts = []
self.install_subdirs = []
+class ExecutableSerialisation():
+ def __init__(self, name, fname, cmd_args, env, is_cross, exe_wrapper,
+ workdir, extra_paths):
+ self.name = name
+ self.fname = fname
+ self.cmd_args = cmd_args
+ self.env = env
+ self.is_cross = is_cross
+ self.exe_runner = exe_wrapper
+ self.workdir = workdir
+ self.extra_paths = extra_paths
+
class TestSerialisation:
def __init__(self, name, suite, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env,
should_fail, valgrind_args, timeout, workdir, extra_paths):
@@ -154,6 +166,35 @@ class Backend():
raise MesonException('Unknown data type in object list.')
return obj_list
+ def serialise_executable(self, exe, cmd_args, workdir, env={}):
+ import uuid
+ # Can't just use exe.name here; it will likely be run more than once
+ scratch_file = 'meson_exe_{0}_{1}.dat'.format(exe.name,
+ str(uuid.uuid4())[:8])
+ exe_data = os.path.join(self.environment.get_scratch_dir(), scratch_file)
+ with open(exe_data, 'wb') as f:
+ if isinstance(exe, dependencies.ExternalProgram):
+ exe_fullpath = exe.fullpath
+ else:
+ exe_fullpath = [os.path.join(self.environment.get_build_dir(),
+ self.get_target_filename(exe))]
+ is_cross = self.environment.is_cross_build() and \
+ self.environment.cross_info.need_cross_compiler() and \
+ self.environment.cross_info.need_exe_wrapper()
+ if is_cross:
+ exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None)
+ else:
+ exe_wrapper = None
+ if mesonlib.is_windows():
+ extra_paths = self.determine_windows_extra_paths(exe)
+ else:
+ extra_paths = []
+ es = ExecutableSerialisation(exe.name, exe_fullpath, cmd_args, env,
+ is_cross, exe_wrapper, workdir,
+ extra_paths)
+ pickle.dump(es, f)
+ return exe_data
+
def serialise_tests(self):
test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
datafile = open(test_data, 'wb')
@@ -163,6 +204,7 @@ class Backend():
datafile = open(benchmark_data, 'wb')
self.write_benchmark_file(datafile)
datafile.close()
+ return (test_data, benchmark_data)
def has_source_suffix(self, target, suffix):
for s in target.get_sources():
@@ -316,7 +358,9 @@ class Backend():
fname = exe.fullpath
else:
fname = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(t.get_exe()))]
- is_cross = self.environment.is_cross_build() and self.environment.cross_info.need_cross_compiler()
+ is_cross = self.environment.is_cross_build() and \
+ self.environment.cross_info.need_cross_compiler() and \
+ self.environment.cross_info.need_exe_wrapper()
if is_cross:
exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None)
else:
@@ -367,8 +411,9 @@ class Backend():
def exe_object_to_cmd_array(self, exe):
if self.environment.is_cross_build() and \
- isinstance(exe, build.BuildTarget) and exe.is_cross:
- if 'exe_wrapper' not in self.environment.cross_info:
+ self.environment.cross_info.need_exe_wrapper() and \
+ isinstance(exe, build.BuildTarget) and exe.is_cross:
+ if 'exe_wrapper' not in self.environment.cross_info.config:
s = 'Can not use target %s as a generator because it is cross-built\n'
s += 'and no exe wrapper is defined. You might want to set it to native instead.'
s = s % exe.name
@@ -388,6 +433,16 @@ class Backend():
final_args.append(a)
return final_args
+ def get_custom_target_provided_libraries(self, target):
+ libs = []
+ for t in target.get_generated_sources():
+ if not isinstance(t, build.CustomTarget):
+ continue
+ for f in t.output:
+ if self.environment.is_library(f):
+ libs.append(os.path.join(self.get_target_dir(t), f))
+ return libs
+
def eval_custom_target_command(self, target, absolute_paths=False):
if not absolute_paths:
ofilenames = [os.path.join(self.get_target_dir(target), i) for i in target.output]
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index ec07395..4b85565 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -176,9 +176,6 @@ int dummy;
self.generate_phony(outfile)
outfile.write('# Build rules for targets\n\n')
[self.generate_target(t, outfile) for t in self.build.get_targets().values()]
- if len(self.build.pot) > 0:
- outfile.write('# Build rules for localisation.\n\n')
- self.generate_po(outfile)
outfile.write('# Test rules\n\n')
self.generate_tests(outfile)
outfile.write('# Install rules\n\n')
@@ -188,6 +185,7 @@ int dummy;
outfile.write('# Coverage rules\n\n')
self.generate_coverage_rules(outfile)
outfile.write('# Suffix\n\n')
+ self.generate_utils(outfile)
self.generate_ending(outfile)
# Only ovewrite the old build file after the new one has been
# fully created.
@@ -199,7 +197,10 @@ int dummy;
def generate_compdb(self):
ninja_exe = environment.detect_ninja()
builddir = self.environment.get_build_dir()
- jsondb = subprocess.check_output([ninja_exe, '-t', 'compdb', 'c_COMPILER', 'cpp_COMPILER'], cwd=builddir)
+ try:
+ jsondb = subprocess.check_output([ninja_exe, '-t', 'compdb', 'c_COMPILER', 'cpp_COMPILER'], cwd=builddir)
+ except Exception:
+ raise MesonException('Could not create compilation database.')
open(os.path.join(builddir, 'compile_commands.json'), 'wb').write(jsondb)
# Get all generated headers. Any source file might need them so
@@ -341,6 +342,7 @@ int dummy;
def generate_custom_target(self, target, outfile):
(srcs, ofilenames, cmd) = self.eval_custom_target_command(target)
deps = []
+ desc = 'Generating {0} with a {1} command.'
for i in target.get_dependencies():
# FIXME, should not grab element at zero but rather expand all.
if isinstance(i, list):
@@ -364,9 +366,23 @@ int dummy;
tmp = [tmp]
for fname in tmp:
elem.add_dep(os.path.join(self.get_target_dir(d), fname))
+ # Windows doesn't have -rpath, so for EXEs that need DLLs built within
+ # the project, we need to set PATH so the DLLs are found. We use
+ # a serialized executable wrapper for that and check if the
+ # CustomTarget command needs extra paths first.
+ if mesonlib.is_windows() and \
+ self.determine_windows_extra_paths(target.command[0]):
+ exe_data = self.serialise_executable(target.command[0], cmd[1:],
+ # All targets are built from the build dir
+ self.environment.get_build_dir())
+ cmd = [sys.executable, self.environment.get_build_command(),
+ '--internal', 'exe', exe_data]
+ cmd_type = 'meson_exe.py custom'
+ else:
+ cmd_type = 'custom'
elem.add_item('COMMAND', cmd)
- elem.add_item('description', 'Generating %s with a custom command.' % target.name)
+ elem.add_item('description', desc.format(target.name, cmd_type))
elem.write(outfile)
self.processed_targets[target.name + target.type_suffix()] = True
@@ -394,9 +410,11 @@ int dummy;
if isinstance(texe, build.Executable):
abs_exe = os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe))
deps.append(self.get_target_filename(texe))
- if self.environment.is_cross_build() \
- and self.environment.cross_info.config['binaries'].get('exe_wrapper', None) is not None:
- cmd += [self.environment.cross_info.config['binaries']['exe_wrapper']]
+ if self.environment.is_cross_build() and \
+ self.environment.cross_info.need_exe_wrapper():
+ exe_wrap = self.environment.cross_info.config['binaries'].get('exe_wrapper', None)
+ if exe_wrap is not None:
+ cmd += [exe_wrap]
cmd.append(abs_exe)
else:
cmd.append(target.command)
@@ -407,51 +425,33 @@ int dummy;
elem.write(outfile)
self.processed_targets[target.name + target.type_suffix()] = True
- def generate_po(self, outfile):
- for p in self.build.pot:
- (packagename, languages, subdir) = p
- input_file = os.path.join(subdir, 'POTFILES')
- elem = NinjaBuildElement(self.all_outputs, 'pot', 'GEN_POT', [])
- elem.add_item('PACKAGENAME', packagename)
- elem.add_item('OUTFILE', packagename + '.pot')
- elem.add_item('FILELIST', os.path.join(self.environment.get_source_dir(), input_file))
- elem.add_item('OUTDIR', os.path.join(self.environment.get_source_dir(), subdir))
- elem.write(outfile)
- for l in languages:
- infile = os.path.join(self.environment.get_source_dir(), subdir, l + '.po')
- outfilename = os.path.join(subdir, l + '.gmo')
- lelem = NinjaBuildElement(self.all_outputs, outfilename, 'GEN_GMO', infile)
- lelem.add_item('INFILE', infile)
- lelem.add_item('OUTFILE', outfilename)
- lelem.write(outfile)
-
def generate_coverage_rules(self, outfile):
(gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools()
added_rule = False
if gcovr_exe:
added_rule = True
elem = NinjaBuildElement(self.all_outputs, 'coverage-xml', 'CUSTOM_COMMAND', '')
- elem.add_item('COMMAND', [gcovr_exe, '-x', '-r', self.environment.get_build_dir(),\
+ elem.add_item('COMMAND', [gcovr_exe, '-x', '-r', self.environment.get_source_dir(),\
'-o', os.path.join(self.environment.get_log_dir(), 'coverage.xml')])
elem.add_item('DESC', 'Generating XML coverage report.')
elem.write(outfile)
elem = NinjaBuildElement(self.all_outputs, 'coverage-text', 'CUSTOM_COMMAND', '')
- elem.add_item('COMMAND', [gcovr_exe, '-r', self.environment.get_build_dir(),\
+ elem.add_item('COMMAND', [gcovr_exe, '-r', self.environment.get_source_dir(),\
'-o', os.path.join(self.environment.get_log_dir(), 'coverage.txt')])
elem.add_item('DESC', 'Generating text coverage report.')
elem.write(outfile)
if lcov_exe and genhtml_exe:
added_rule = True
- phony_elem = NinjaBuildElement(self.all_outputs, 'coverage-html', 'phony', 'coveragereport/index.html')
- phony_elem.write(outfile)
-
- elem = NinjaBuildElement(self.all_outputs, 'coveragereport/index.html', 'CUSTOM_COMMAND', '')
htmloutdir = os.path.join(self.environment.get_log_dir(), 'coveragereport')
+ covinfo = os.path.join(self.environment.get_log_dir(), 'coverage.info')
+ phony_elem = NinjaBuildElement(self.all_outputs, 'coverage-html', 'phony', os.path.join(htmloutdir, 'index.html'))
+ phony_elem.write(outfile)
+ elem = NinjaBuildElement(self.all_outputs, os.path.join(htmloutdir, 'index.html'), 'CUSTOM_COMMAND', '')
command = [lcov_exe, '--directory', self.environment.get_build_dir(),\
- '--capture', '--output-file', 'coverage.info', '--no-checksum',\
+ '--capture', '--output-file', covinfo, '--no-checksum',\
'&&', genhtml_exe, '--prefix', self.environment.get_build_dir(),\
'--output-directory', htmloutdir, '--title', 'Code coverage',\
- '--legend', '--show-details', 'coverage.info']
+ '--legend', '--show-details', covinfo]
elem.add_item('COMMAND', command)
elem.add_item('DESC', 'Generating HTML coverage report.')
elem.write(outfile)
@@ -475,7 +475,6 @@ int dummy;
self.generate_header_install(d)
self.generate_man_install(d)
self.generate_data_install(d)
- self.generate_po_install(d, elem)
self.generate_custom_install_script(d)
self.generate_subdir_install(d)
elem.write(outfile)
@@ -483,17 +482,6 @@ int dummy;
ofile = open(install_data_file, 'wb')
pickle.dump(d, ofile)
- def generate_po_install(self, d, elem):
- for p in self.build.pot:
- (package_name, languages, subdir) = p
- # FIXME: assumes only one po package per source
- d.po_package_name = package_name
- for lang in languages:
- rel_src = os.path.join(subdir, lang + '.gmo')
- src_file = os.path.join(self.environment.get_build_dir(), rel_src)
- d.po.append((src_file, self.environment.coredata.get_builtin_option('localedir'), lang))
- elem.add_dep(rel_src)
-
def generate_target_install(self, d):
libdir = self.environment.get_libdir()
bindir = self.environment.get_bindir()
@@ -582,10 +570,9 @@ int dummy;
elem.write(outfile)
def generate_tests(self, outfile):
- self.serialise_tests()
+ (test_data, benchmark_data) = self.serialise_tests()
valgrind = environment.find_valgrind()
script_root = self.environment.get_script_dir()
- test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
cmd = [ sys.executable, self.environment.get_build_command(), '--internal', 'test' ]
if not self.environment.coredata.get_builtin_option('stdsplit'):
cmd += ['--no-stdsplit']
@@ -608,7 +595,6 @@ int dummy;
# And then benchmarks.
benchmark_script = os.path.join(script_root, 'meson_benchmark.py')
- benchmark_data = os.path.join(self.environment.get_scratch_dir(), 'meson_benchmark_setup.dat')
cmd = [sys.executable, self.environment.get_build_command(), '--internal', 'benchmark', benchmark_data]
elem = NinjaBuildElement(self.all_outputs, 'benchmark', 'CUSTOM_COMMAND', ['all', 'PHONY'])
elem.add_item('COMMAND', cmd)
@@ -639,25 +625,6 @@ int dummy;
outfile.write(" command = %s %s %s %s %s %s --backend ninja\n" % c)
outfile.write(' description = Regenerating build files\n')
outfile.write(' generator = 1\n\n')
- if len(self.build.pot) > 0:
- self.generate_gettext_rules(outfile)
- outfile.write('\n')
-
- def generate_gettext_rules(self, outfile):
- rule = 'rule GEN_POT\n'
- command = " command = xgettext --package-name=$PACKAGENAME -p $OUTDIR -f $FILELIST -D '%s' -k_ -o $OUTFILE\n" % \
- self.environment.get_source_dir()
- desc = " description = Creating pot file for package $PACKAGENAME.\n"
- outfile.write(rule)
- outfile.write(command)
- outfile.write(desc)
- outfile.write('\n')
- rule = 'rule GEN_GMO\n'
- command = ' command = msgfmt $INFILE -o $OUTFILE\n'
- desc = ' description = Generating gmo file $OUTFILE\n'
- outfile.write(rule)
- outfile.write(command)
- outfile.write(desc)
outfile.write('\n')
def generate_phony(self, outfile):
@@ -1719,16 +1686,6 @@ rule FORTRAN_DEP_HACK
elem.add_item('LINK_ARGS', commands)
return elem
- def get_custom_target_provided_libraries(self, target):
- libs = []
- for t in target.get_generated_sources():
- if not isinstance(t, build.CustomTarget):
- continue
- for f in t.output:
- if self.environment.is_library(f):
- libs.append(os.path.join(self.get_target_dir(t), f))
- return libs
-
def determine_rpath_dirs(self, target):
link_deps = target.get_all_link_deps()
result = []
@@ -1804,6 +1761,16 @@ rule FORTRAN_DEP_HACK
other_deps.append(outfilename)
return (src_deps, other_deps)
+ # For things like scan-build and other helper tools we might have.
+ def generate_utils(self, outfile):
+ cmd = [sys.executable, self.environment.get_build_command(),
+ '--internal', 'scanbuild', self.environment.source_dir, self.environment.build_dir,
+ sys.executable, self.environment.get_build_command()]
+ elem = NinjaBuildElement(self.all_outputs, 'scan-build', 'CUSTOM_COMMAND', 'PHONY')
+ elem.add_item('COMMAND', cmd)
+ elem.add_item('pool', 'console')
+ elem.write(outfile)
+
def generate_ending(self, outfile):
targetlist = [self.get_target_filename(t) for t in self.build.get_targets().values()\
if not isinstance(t, build.RunTarget)]
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 725b8ed..82d0dc9 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -69,13 +69,18 @@ class Vs2010Backend(backends.Backend):
if len(src_conflicts) > 1}
def generate_custom_generator_commands(self, target, parent_node):
- all_output_files = []
+ generator_output_files = []
commands = []
inputs = []
outputs = []
+ custom_target_include_dirs = []
+ custom_target_output_files = []
for genlist in target.get_generated_sources():
if isinstance(genlist, build.CustomTarget):
- all_output_files += [os.path.join(self.get_target_dir(genlist), i) for i in genlist.output]
+ custom_target_output_files += [os.path.join(self.get_target_dir(genlist), i) for i in genlist.output]
+ idir = self.relpath(self.get_target_dir(genlist), self.get_target_dir(target))
+ if idir not in custom_target_include_dirs:
+ custom_target_include_dirs.append(idir)
else:
generator = genlist.get_generator()
exe = generator.get_exe()
@@ -93,7 +98,7 @@ class Vs2010Backend(backends.Backend):
infilename = os.path.join(self.environment.get_source_dir(), curfile)
outfiles = genlist.get_outputs_for(curfile)
outfiles = [os.path.join(target_private_dir, of) for of in outfiles]
- all_output_files += outfiles
+ generator_output_files += outfiles
args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\
for x in base_args]
args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", target_private_dir)
@@ -111,7 +116,7 @@ class Vs2010Backend(backends.Backend):
ET.SubElement(cbs, 'Message').text = 'Generating custom sources.'
pg = ET.SubElement(parent_node, 'PropertyGroup')
ET.SubElement(pg, 'CustomBuildBeforeTargets').text = 'ClCompile'
- return all_output_files
+ return generator_output_files, custom_target_output_files, custom_target_include_dirs
def generate(self, interp):
self.resolve_source_conflicts()
@@ -260,6 +265,8 @@ class Vs2010Backend(backends.Backend):
lang = self.lang_from_source_file(i)
if lang not in languages:
languages.append(lang)
+ elif self.environment.is_library(i):
+ pass
else:
# Everything that is not an object or source file is considered a header.
headers.append(i)
@@ -436,8 +443,12 @@ class Vs2010Backend(backends.Backend):
ET.SubElement(type_config, 'WholeProgramOptimization').text = 'false'
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)
+ generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands(target, root)
(gen_src, gen_hdrs, gen_objs, gen_langs) = self.split_sources(generated_files)
+ (custom_src, custom_hdrs, custom_objs, custom_langs) = self.split_sources(custom_target_output_files)
+ gen_src += custom_src
+ gen_hdrs += custom_hdrs
+ gen_langs += custom_langs
direlem = ET.SubElement(root, 'PropertyGroup')
fver = ET.SubElement(direlem, '_ProjectFileVersion')
fver.text = self.project_file_version
@@ -455,7 +466,7 @@ class Vs2010Backend(backends.Backend):
opt = ET.SubElement(clconf, 'Optimization')
opt.text = 'disabled'
inc_dirs = ['.', self.relpath(self.get_target_private_dir(target), self.get_target_dir(target)),
- proj_to_src_dir]
+ proj_to_src_dir] + generated_files_include_dirs
extra_args = {'c': [], 'cpp': []}
for l, args in self.environment.coredata.external_args.items():
@@ -561,10 +572,14 @@ 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 lib in self.get_custom_target_provided_libraries(target):
+ additional_links.append(self.relpath(lib, self.get_target_dir(target)))
additional_objects = []
for o in self.flatten_object_list(target, down):
assert(isinstance(o, str))
additional_objects.append(o)
+ for o in custom_objs:
+ additional_objects.append(self.relpath(o, self.get_target_dir(target)))
if len(additional_links) > 0:
additional_links.append('%(AdditionalDependencies)')
ET.SubElement(link, 'AdditionalDependencies').text = ';'.join(additional_links)
@@ -773,7 +788,6 @@ if %%errorlevel%% neq 0 goto :VCEnd'''
ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c'
postbuild = ET.SubElement(action, 'PostBuildEvent')
ET.SubElement(postbuild, 'Message')
- test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
test_command = [sys.executable,
self.environment.get_build_command(),
'--internal',
@@ -787,14 +801,12 @@ endlocal & call :cmErrorLevel %%errorlevel%% & goto :cmDone
exit /b %%1
:cmDone
if %%errorlevel%% neq 0 goto :VCEnd'''
+ test_data = self.serialise_tests()[0]
ET.SubElement(postbuild, 'Command').text =\
cmd_templ % ('" "'.join(test_command), test_data)
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
tree = ET.ElementTree(root)
tree.write(ofname, encoding='utf-8', xml_declaration=True)
- datafile = open(test_data, 'wb')
- self.serialise_tests()
- datafile.close()
# ElementTree can not do prettyprinting so do it manually
#doc = xml.dom.minidom.parse(ofname)
#open(ofname, 'w').write(doc.toprettyxml())
diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py
index 6bda826..0ce90ce 100644
--- a/mesonbuild/backend/xcodebackend.py
+++ b/mesonbuild/backend/xcodebackend.py
@@ -64,7 +64,7 @@ class XCodeBackend(backends.Backend):
def generate(self, interp):
self.interpreter = interp
- self.serialise_tests()
+ test_data = self.serialise_tests()[0]
self.generate_filemap()
self.generate_buildmap()
self.generate_buildstylemap()
@@ -92,7 +92,7 @@ class XCodeBackend(backends.Backend):
self.generate_pbx_group()
self.generate_pbx_native_target()
self.generate_pbx_project()
- self.generate_pbx_shell_build_phase()
+ self.generate_pbx_shell_build_phase(test_data)
self.generate_pbx_sources_build_phase()
self.generate_pbx_target_dependency()
self.generate_xc_build_configuration()
@@ -480,7 +480,7 @@ class XCodeBackend(backends.Backend):
self.write_line('};')
self.ofile.write('/* End PBXProject section */\n')
- def generate_pbx_shell_build_phase(self):
+ def generate_pbx_shell_build_phase(self, test_data):
self.ofile.write('\n/* Begin PBXShellScriptBuildPhase section */\n')
self.write_line('%s = {' % self.test_command_id)
self.indent_level += 1
@@ -496,7 +496,6 @@ class XCodeBackend(backends.Backend):
self.write_line('shellPath = /bin/sh;')
script_root = self.environment.get_script_dir()
test_script = os.path.join(script_root, 'meson_test.py')
- test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
cmd = [sys.executable, test_script, test_data, '--wd', self.environment.get_build_dir()]
cmdstr = ' '.join(["'%s'" % i for i in cmd])
self.write_line('shellScript = "%s";' % cmdstr)
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 60b5ec0..9de556c 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -95,7 +95,6 @@ class Build:
self.data = []
self.static_linker = None
self.static_cross_linker = None
- self.pot = []
self.subprojects = {}
self.install_scripts = []
self.postconf_scripts = []
@@ -872,11 +871,12 @@ class CustomTarget:
self.install = kwargs['install']
if not isinstance(self.install, bool):
raise InvalidArguments('"install" must be boolean.')
- 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.')
+ 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.')
else:
self.install = False
self.build_always = kwargs.get('build_always', False)
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index c4e8f0d..241192e 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -420,29 +420,31 @@ class CCompiler(Compiler):
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))
+ def sanity_check_impl(self, work_dir, sname, code):
+ mlog.debug('Sanity testing ' + self.language + ' compiler:', ' '.join(self.exelist))
mlog.debug('Is cross compiler: %s.' % str(self.is_cross))
- source_name = os.path.join(work_dir, 'sanitycheckc.c')
+ extra_flags = []
+ source_name = os.path.join(work_dir, sname)
+ binname = sname.rsplit('.', 1)[0]
if self.is_cross:
- binname = 'sanitycheckc_cross'
- else:
- binname = 'sanitycheckc'
+ binname += '_cross'
+ if self.exe_wrapper is None:
+ # Linking cross built apps is painful. You can't really
+ # tell if you should use -nostdlib or not and for example
+ # on OSX the compiler binary is the same but you need
+ # a ton of compiler flags to differentiate between
+ # arm and x86_64. So just compile.
+ extra_flags = self.get_compile_only_args()
+ # Is a valid executable output for all toolchains and platforms
+ binname += '.exe'
+ # Write binary check source
binary_name = os.path.join(work_dir, binname)
ofile = open(source_name, 'w')
- ofile.write('int main(int argc, char **argv) { int class=0; return class; }\n')
+ ofile.write(code)
ofile.close()
- if self.is_cross and self.exe_wrapper is None:
- # Linking cross built apps is painful. You can't really
- # tell if you should use -nostdlib or not and for example
- # on OSX the compiler binary is the same but you need
- # a ton of compiler flags to differentiate between
- # arm and x86_64. So just compile.
- extra_flags = ['-c']
- else:
- extra_flags = []
- cmdlist = self.exelist + extra_flags + [source_name, '-o', binary_name]
+ # Compile sanity check
+ cmdlist = self.exelist + extra_flags + [source_name] + self.get_output_args(binary_name)
pc = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdo, stde) = pc.communicate()
stdo = stdo.decode()
@@ -454,7 +456,8 @@ class CCompiler(Compiler):
mlog.debug(stde)
mlog.debug('-----')
if pc.returncode != 0:
- raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
+ raise EnvironmentException('Compiler {0} can not compile programs.'.format(self.name_string()))
+ # Run sanity check
if self.is_cross:
if self.exe_wrapper is None:
# Can't check if the binaries run so we have to assume they do
@@ -466,7 +469,11 @@ class CCompiler(Compiler):
pe = subprocess.Popen(cmdlist)
pe.wait()
if pe.returncode != 0:
- raise EnvironmentException('Executables created by C compiler %s are not runnable.' % self.name_string())
+ raise EnvironmentException('Executables created by {0} compiler {1} are not runnable.'.format(self.language, self.name_string()))
+
+ def sanity_check(self, work_dir):
+ code = 'int main(int argc, char **argv) { int class=0; return class; }\n'
+ return self.sanity_check_impl(work_dir, 'sanitycheckc.c', code)
def has_header(self, hname, extra_args=[]):
templ = '''#include<%s>
@@ -526,7 +533,8 @@ int main () {{ {1}; }}'''
ofile = open(srcname, 'w')
ofile.write(code)
ofile.close()
- extra_args = extra_args + self.get_output_args(dstname)
+ extra_args = self.unix_link_flags_to_native(extra_args) + \
+ self.get_output_args(dstname)
p = self.compile(code, srcname, extra_args)
try:
os.remove(dstname)
@@ -545,7 +553,7 @@ int main () {{ {1}; }}'''
ofile.close()
exename = srcname + '.exe' # Is guaranteed to be executable on every platform.
commands = self.get_exelist()
- commands += extra_args
+ commands += self.unix_link_flags_to_native(extra_args)
commands.append(srcname)
commands += self.get_output_args(exename)
p = subprocess.Popen(commands, cwd=os.path.split(srcname)[0], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -585,7 +593,7 @@ int main () {{ {1}; }}'''
element_exists_templ = '''#include <stdio.h>
{0}
int main(int argc, char **argv) {{
- {1};
+ {1} something;
}}
'''
templ = '''#include <stdio.h>
@@ -602,6 +610,10 @@ int temparray[%d-sizeof(%s)];
for i in range(1, 1024):
code = templ % (prefix, i, element)
if self.compiles(code, extra_args):
+ if self.id == 'msvc':
+ # MSVC refuses to construct an array of zero size, so
+ # the test only succeeds when i is sizeof(element) + 1
+ return i - 1
return i
raise EnvironmentException('Cross checking sizeof overflowed.')
@@ -624,6 +636,11 @@ int main(int argc, char **argv) {
return int(res.stdout)
def cross_alignment(self, typename, env, extra_args=[]):
+ type_exists_templ = '''#include <stdio.h>
+int main(int argc, char **argv) {{
+ {0} something;
+}}
+'''
templ = '''#include<stddef.h>
struct tmp {
char c;
@@ -636,9 +653,16 @@ int testarray[%d-offsetof(struct tmp, target)];
extra_args += env.cross_info.config['properties'][self.language + '_args']
except KeyError:
pass
+ extra_args += self.get_no_optimization_args()
+ if not self.compiles(type_exists_templ.format(typename)):
+ return -1
for i in range(1, 1024):
code = templ % (typename, i)
if self.compiles(code, extra_args):
+ if self.id == 'msvc':
+ # MSVC refuses to construct an array of zero size, so
+ # the test only succeeds when i is sizeof(element) + 1
+ return i - 1
return i
raise EnvironmentException('Cross checking offsetof overflowed.')
@@ -669,11 +693,19 @@ int main(int argc, char **argv) {
return align
def has_function(self, funcname, prefix, env, extra_args=[]):
+ """
+ First, this function looks for the symbol in the default libraries
+ provided by the compiler (stdlib + a few others usually). If that
+ fails, it checks if any of the headers specified in the prefix provide
+ an implementation of the function, and if that fails, it checks if it's
+ implemented as a compiler-builtin.
+ """
# Define the symbol to something else in case it is defined by the
# includes or defines listed by the user `{0}` or by the compiler.
# Then, undef the symbol to get rid of it completely.
templ = '''
#define {1} meson_disable_define_of_{1}
+ #include <limits.h>
{0}
#undef {1}
'''
@@ -691,11 +723,14 @@ int main(int argc, char **argv) {
# glibc defines functions that are not available on Linux as stubs that
# fail with ENOSYS (such as e.g. lchmod). In this case we want to fail
# instead of detecting the stub as a valid symbol.
- templ += '''
+ # We always include limits.h above to ensure that these are defined for
+ # stub functions.
+ stubs_fail = '''
#if defined __stub_{1} || defined __stub___{1}
fail fail fail this function is not going to work
#endif
'''
+ templ += stubs_fail
# And finally the actual function call
templ += '''
@@ -714,12 +749,18 @@ int main(int argc, char **argv) {
raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname))
if self.links(templ.format(prefix, funcname), extra_args):
return True
+ # Add -O0 to ensure that the symbol isn't optimized away by the compiler
+ extra_args += self.get_no_optimization_args()
+ # Sometimes the implementation is provided by the header, or the header
+ # redefines the symbol to be something else. In that case, we want to
+ # still detect the function. We still want to fail if __stub_foo or
+ # _stub_foo are defined, of course.
+ if self.links('{0}\n' + stubs_fail + '\nint main() {{ {1}; }}'.format(prefix, funcname), extra_args):
+ return True
# Some functions like alloca() are defined as compiler built-ins which
# are inlined by the compiler, so test for that instead. Built-ins are
# special functions that ignore all includes and defines, so we just
# directly try to link via main().
- # Add -O0 to ensure that the symbol isn't optimized away by the compiler
- extra_args += self.get_no_optimization_args()
return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), extra_args)
def has_member(self, typename, membername, prefix, extra_args=[]):
@@ -783,42 +824,8 @@ class CPPCompiler(CCompiler):
return False
def sanity_check(self, work_dir):
- source_name = os.path.join(work_dir, 'sanitycheckcpp.cc')
- binary_name = os.path.join(work_dir, 'sanitycheckcpp')
- ofile = open(source_name, 'w')
- ofile.write('class breakCCompiler;int main(int argc, char **argv) { return 0; }\n')
- ofile.close()
- if self.is_cross and self.exe_wrapper is None:
- # Skipping link because of the same reason as for C.
- # The comment in CCompiler explains why this is done.
- extra_flags = ['-c']
- else:
- extra_flags = []
- cmdlist = self.exelist + extra_flags + [source_name, '-o', binary_name]
- pc = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdo, stde) = pc.communicate()
- stdo = stdo.decode()
- stde = stde.decode()
- mlog.debug('Sanity check compiler command line:', ' '.join(cmdlist))
- mlog.debug('Sanity check compile stdout:')
- mlog.debug(stdo)
- mlog.debug('-----\nSanity check compile stderr:')
- mlog.debug(stde)
- mlog.debug('-----')
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
- if self.is_cross:
- if self.exe_wrapper is None:
- # Can't check if the binaries run so we have to assume they do
- return
- cmdlist = self.exe_wrapper + [binary_name]
- else:
- cmdlist = [binary_name]
- pe = subprocess.Popen(cmdlist)
- pe.wait()
- if pe.returncode != 0:
- raise EnvironmentException('Executables created by C++ compiler %s are not runnable.' % self.name_string())
+ code = 'class breakCCompiler;int main(int argc, char **argv) { return 0; }\n'
+ return self.sanity_check_impl(work_dir, 'sanitycheckcpp.cc', code)
class ObjCCompiler(CCompiler):
def __init__(self, exelist, version, is_cross, exe_wrap):
@@ -1361,40 +1368,9 @@ class VisualStudioCCompiler(CCompiler):
objname = os.path.splitext(pchname)[0] + '.obj'
return (objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname ])
- def sanity_check(self, work_dir):
- source_name = 'sanitycheckc.c'
- binary_name = 'sanitycheckc'
- ofile = open(os.path.join(work_dir, source_name), 'w')
- ofile.write('int main(int argc, char **argv) { return 0; }\n')
- ofile.close()
- pc = subprocess.Popen(self.exelist + [source_name, '/Fe' + binary_name],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL,
- cwd=work_dir)
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
- pe = subprocess.Popen(os.path.join(work_dir, binary_name))
- pe.wait()
- if pe.returncode != 0:
- raise EnvironmentException('Executables created by C++ compiler %s are not runnable.' % self.name_string())
-
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 []
@@ -1456,24 +1432,6 @@ class VisualStudioCPPCompiler(VisualStudioCCompiler):
return True
return False
- def sanity_check(self, work_dir):
- source_name = 'sanitycheckcpp.cpp'
- binary_name = 'sanitycheckcpp'
- ofile = open(os.path.join(work_dir, source_name), 'w')
- ofile.write('class BreakPlainC;int main(int argc, char **argv) { return 0; }\n')
- ofile.close()
- pc = subprocess.Popen(self.exelist + [source_name, '/Fe' + binary_name],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL,
- cwd=work_dir)
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
- pe = subprocess.Popen(os.path.join(work_dir, binary_name))
- pe.wait()
- if pe.returncode != 0:
- raise EnvironmentException('Executables created by C++ compiler %s are not runnable.' % self.name_string())
-
def get_options(self):
return {'cpp_eh' : coredata.UserComboOption('cpp_eh',
'C++ exception handling type.',
@@ -1730,7 +1688,10 @@ class GnuCPPCompiler(CPPCompiler):
def get_options(self):
opts = {'cpp_std' : coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none', 'c++03', 'c++11', 'c++14'],
- 'none')}
+ 'none'),
+ 'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl',
+ 'STL debug mode',
+ False)}
if self.gcc_type == GCC_MINGW:
opts.update({
'cpp_winlibs': coredata.UserStringArrayOption('c_winlibs', 'Standard Win libraries to link against',
@@ -1743,6 +1704,8 @@ class GnuCPPCompiler(CPPCompiler):
std = options['cpp_std']
if std.value != 'none':
args.append('-std=' + std.value)
+ if options['cpp_debugstl'].value:
+ args.append('-D_GLIBCXX_DEBUG=1')
return args
def get_option_link_args(self, options):
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 39e0da6..8227340 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -229,4 +229,5 @@ forbidden_target_names = {'clean': None,
'benchmark': None,
'install': None,
'build.ninja': None,
+ 'scan-build': None,
}
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 19594c8..5096320 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import os, re, subprocess
+import os, re, subprocess, platform
from . import coredata, mesonlib
from .compilers import *
import configparser
@@ -52,6 +52,33 @@ def detect_ninja():
if p.returncode == 0:
return n
+def detect_cpu_family():
+ """
+ Python is inconsistent in its platform module.
+ It returns different values for the same cpu.
+ For x86 it might return 'x86', 'i686' or somesuch.
+ Do some canonicalization.
+ """
+ trial = platform.machine().lower()
+ if trial.startswith('i') and trial.endswith('86'):
+ return 'x86'
+ if trial.startswith('arm'):
+ return 'arm'
+ if trial == 'amd64':
+ return 'x86_64'
+ # Add fixes here as bugs are reported.
+ return trial
+
+def detect_cpu():
+ trial = platform.machine().lower()
+ if trial == 'amd64':
+ return 'x86_64'
+ # Add fixes here as bugs are reported.
+ return trial
+
+def detect_system():
+ return platform.system().lower()
+
class Environment():
private_dir = 'meson-private'
@@ -131,7 +158,8 @@ class Environment():
coredata.save(self.coredata, cdf)
def get_script_dir(self):
- return os.path.join(os.path.dirname(self.meson_script_file), '../scripts')
+ import mesonbuild.scripts
+ return os.path.dirname(mesonbuild.scripts.__file__)
def get_log_dir(self):
return self.log_dir
@@ -181,7 +209,10 @@ class Environment():
compilers = [self.cross_info.config['binaries']['c']]
ccache = []
is_cross = True
- exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None)
+ if self.cross_info.need_exe_wrapper():
+ exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None)
+ else:
+ exe_wrap = []
elif evar in os.environ:
compilers = os.environ[evar].split()
ccache = []
@@ -246,7 +277,10 @@ class Environment():
if self.is_cross_build() and want_cross:
compilers = [self.cross_info['fortran']]
is_cross = True
- exe_wrap = self.cross_info.get('exe_wrapper', None)
+ if self.cross_info.need_exe_wrapper():
+ exe_wrap = self.cross_info.get('exe_wrapper', None)
+ else:
+ exe_wrap = []
elif evar in os.environ:
compilers = os.environ[evar].split()
is_cross = False
@@ -321,7 +355,10 @@ class Environment():
compilers = [self.cross_info.config['binaries']['cpp']]
ccache = []
is_cross = True
- exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None)
+ if self.cross_info.need_exe_wrapper():
+ exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None)
+ else:
+ exe_wrap = []
elif evar in os.environ:
compilers = os.environ[evar].split()
ccache = []
@@ -384,7 +421,10 @@ class Environment():
if self.is_cross_build() and want_cross:
exelist = [self.cross_info['objc']]
is_cross = True
- exe_wrap = self.cross_info.get('exe_wrapper', None)
+ if self.cross_info.need_exe_wrapper():
+ exe_wrap = self.cross_info.get('exe_wrapper', None)
+ else:
+ exe_wrap = []
else:
exelist = self.get_objc_compiler_exelist()
is_cross = False
@@ -414,7 +454,10 @@ class Environment():
if self.is_cross_build() and want_cross:
exelist = [self.cross_info['objcpp']]
is_cross = True
- exe_wrap = self.cross_info.get('exe_wrapper', None)
+ if self.cross_info.need_exe_wrapper():
+ exe_wrap = self.cross_info.get('exe_wrapper', None)
+ else:
+ exe_wrap = []
else:
exelist = self.get_objcpp_compiler_exelist()
is_cross = False
@@ -726,3 +769,12 @@ class CrossBuildInfo():
# But not when cross compiling a cross compiler.
def need_cross_compiler(self):
return 'host_machine' in self.config
+
+ def need_exe_wrapper(self):
+ if self.has_host() and detect_cpu_family() == 'x86_64' and \
+ self.config['host_machine']['cpu_family'] == 'x86' and \
+ self.config['host_machine']['system'] == detect_system():
+ # Can almost always run 32-bit binaries on 64-bit natively if the
+ # host and build systems are the same
+ return False
+ return True
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index b83f4a3..f269c2f 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -322,24 +322,14 @@ class BuildMachine(InterpreterObject):
'endian' : self.endian_method,
})
- # Python is inconsistent in its platform module.
- # It returns different values for the same cpu.
- # For x86 it might return 'x86', 'i686' or somesuch.
- # Do some canonicalization.
def cpu_family_method(self, args, kwargs):
- trial = platform.machine().lower()
- if trial.startswith('i') and trial.endswith('86'):
- return 'x86'
- if trial.startswith('arm'):
- return 'arm'
- # Add fixes here as bugs are reported.
- return trial
+ return environment.detect_cpu_family()
def cpu_method(self, args, kwargs):
- return platform.machine().lower()
+ return environment.detect_cpu()
def system_method(self, args, kwargs):
- return platform.system().lower()
+ return environment.detect_system()
def endian_method(self, args, kwargs):
return sys.byteorder
@@ -883,9 +873,16 @@ class MesonMain(InterpreterObject):
return self.interpreter.environment.build_dir
def has_exe_wrapper_method(self, args, kwargs):
- if self.is_cross_build_method(None, None) and 'binaries' in self.build.environment.cross_info.config:
- return 'exe_wrap' in self.build.environment.cross_info.config['binaries']
- return True # This is semantically confusing.
+ if self.is_cross_build_method(None, None) and \
+ 'binaries' in self.build.environment.cross_info.config and \
+ self.build.environment.cross_info.need_exe_wrapper():
+ exe_wrap = self.build.environment.cross_info.config['binaries'].get('exe_wrapper', None)
+ if exe_wrap is None:
+ return False
+ # We return True when exe_wrap is defined, when it's not needed, and
+ # when we're compiling natively. The last two are semantically confusing.
+ # Need to revisit this.
+ return True
def is_cross_build_method(self, args, kwargs):
return self.build.environment.is_cross_build()
@@ -1055,6 +1052,7 @@ class Interpreter():
raise InterpreterException('Tried to create target %s which already exists.' % v.name)
self.build.targets[v.name] = v
elif isinstance(v, build.InstallScript):
+ print('x')
self.build.install_scripts.append(v)
elif isinstance(v, build.Data):
self.build.data.append(v)
@@ -1304,15 +1302,7 @@ class Interpreter():
@stringArgs
def func_gettext(self, nodes, args, kwargs):
- if len(args) != 1:
- raise InterpreterException('Gettext requires one positional argument (package name).')
- packagename = args[0]
- languages = kwargs.get('languages', None)
- check_stringlist(languages, 'Argument languages must be a list of strings.')
- # TODO: check that elements are strings
- if len(self.build.pot) > 0:
- raise InterpreterException('More than one gettext definition currently not supported.')
- self.build.pot.append((packagename, languages, self.subdir))
+ raise InterpreterException('Gettext() function has been moved to module i18n. Import it and use i18n.gettext() instead')
def func_option(self, nodes, args, kwargs):
raise InterpreterException('Tried to call option() in build description file. All options must be in the option file.')
@@ -1788,7 +1778,9 @@ class Interpreter():
if self.is_subproject():
newsuite = []
for s in suite:
- newsuite.append(self.subproject.replace(' ', '_').replace('.', '_') + '.' + s)
+ if len(s) > 0:
+ s = '.' + s
+ newsuite.append(self.subproject.replace(' ', '_').replace('.', '_') + s)
suite = newsuite
t = Test(args[0], suite, args[1].held_object, par, cmd_args, env, should_fail, valgrind_args, timeout, workdir)
if is_base_test:
@@ -2145,6 +2137,12 @@ class Interpreter():
return int(obj)
except Exception:
raise InterpreterException('String can not be converted to int: ' + obj)
+ elif method_name == 'join':
+ if len(posargs) != 1:
+ raise InterpreterException('Join() takes exactly one argument.')
+ strlist = posargs[0]
+ check_stringlist(strlist)
+ return obj.join(strlist)
raise InterpreterException('Unknown method "%s" for a string.' % method_name)
def to_native(self, arg):
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 2ac0932..fe831bd 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -252,7 +252,9 @@ def do_mesondefine(line, confdata):
def do_conf_file(src, dst, confdata):
data = open(src).readlines()
- regex = re.compile('@(.*?)@')
+ # Only allow (a-z, A-Z, 0-9, _, -) as valid characters for a define
+ # Also allow escaping '@' with '\@'
+ regex = re.compile(r'[^\\]?@([-a-zA-Z0-9_]+)@')
result = []
for line in data:
if line.startswith('#mesondefine'):
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 3b05afb..4f8314c 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -163,7 +163,10 @@ itself as required.'''
def run_script_command(args):
cmdname = args[0]
cmdargs = args[1:]
- if cmdname == 'test':
+ if cmdname == 'exe':
+ import mesonbuild.scripts.meson_exe as abc
+ cmdfunc = abc.run
+ elif cmdname == 'test':
import mesonbuild.scripts.meson_test as abc
cmdfunc = abc.run
elif cmdname == 'benchmark':
@@ -193,9 +196,15 @@ def run_script_command(args):
elif cmdname == 'symbolextractor':
import mesonbuild.scripts.symbolextractor as abc
cmdfunc = abc.run
+ elif cmdname == 'scanbuild':
+ import mesonbuild.scripts.scanbuild as abc
+ cmdfunc = abc.run
elif cmdname == 'vcstagger':
import mesonbuild.scripts.vcstagger as abc
cmdfunc = abc.run
+ elif cmdname == 'gettext':
+ import mesonbuild.scripts.gettext as abc
+ cmdfunc = abc.run
else:
raise MesonException('Unknown internal command {}.'.format(cmdname))
return cmdfunc(cmdargs)
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index 0881f69..955d12b 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -89,14 +89,14 @@ def list_target_files(target_name, coredata, builddata):
def list_buildoptions(coredata, builddata):
buildtype= {'choices': ['plain', 'debug', 'debugoptimized', 'release'],
'type' : 'combo',
- 'value' : coredata.builtin_options['buildtype'].value,
+ 'value' : coredata.get_builtin_option('buildtype'),
'description' : 'Build type',
'name' : 'type'}
- strip = {'value' : coredata.builtin_options['strip'].value,
+ strip = {'value' : coredata.get_builtin_option('strip'),
'type' : 'boolean',
'description' : 'Strip on install',
'name' : 'strip'}
- unity = {'value' : coredata.builtin_options['unity'].value,
+ unity = {'value' : coredata.get_builtin_option('unity'),
'type' : 'boolean',
'description' : 'Unity build',
'name' : 'unity'}
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 39a6ff7..2c37655 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -289,11 +289,21 @@ class GnomeModule:
'--modulename=' + modulename]
args += self.unpack_args('--htmlargs=', 'html_args', kwargs)
args += self.unpack_args('--scanargs=', 'scan_args', kwargs)
+ args += self.unpack_args('--fixxrefargs=', 'fixxref_args', kwargs)
res = [build.RunTarget(targetname, command[0], command[1:] + args, state.subdir)]
if kwargs.get('install', True):
res.append(build.InstallScript(command + args))
return res
+ def gtkdoc_html_dir(self, state, args, kwarga):
+ if len(args) != 1:
+ raise MesonException('Must have exactly one argument.')
+ modulename = args[0]
+ if not isinstance(modulename, str):
+ raise MesonException('Argument must be a string')
+ return os.path.join('share/gtkdoc/html', modulename)
+
+
def unpack_args(self, arg, kwarg_name, kwargs):
try:
new_args = kwargs[kwarg_name]
diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py
new file mode 100644
index 0000000..51668cb
--- /dev/null
+++ b/mesonbuild/modules/i18n.py
@@ -0,0 +1,44 @@
+# Copyright 2016 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .. import coredata, mesonlib, build
+import sys
+
+class I18nModule:
+
+ def gettext(self, state, args, kwargs):
+ if len(args) != 1:
+ raise coredata.MesonException('Gettext requires one positional argument (package name).')
+ packagename = args[0]
+ languages = mesonlib.stringlistify(kwargs.get('languages', []))
+ if len(languages) == 0:
+ raise coredata.MesonException('List of languages empty.')
+ potargs = [state.environment.get_build_command(), '--internal', 'gettext', 'pot', packagename]
+ pottarget = build.RunTarget(packagename + '-pot', sys.executable, potargs, state.subdir)
+ gmoargs = [state.environment.get_build_command(), '--internal', 'gettext', 'gen_gmo'] + languages
+ gmotarget = build.RunTarget(packagename + '-gmo', sys.executable, gmoargs, state.subdir)
+ installcmd = [sys.executable,
+ state.environment.get_build_command(),
+ '--internal',
+ 'gettext',
+ 'install',
+ state.subdir,
+ packagename,
+ state.environment.coredata.get_builtin_option('localedir'),
+ ] + languages
+ iscript = build.InstallScript(installcmd)
+ return [pottarget, gmotarget, iscript]
+
+def initialize():
+ return I18nModule()
diff --git a/mesonbuild/scripts/delwithsuffix.py b/mesonbuild/scripts/delwithsuffix.py
index 38ab406..e112101 100644
--- a/mesonbuild/scripts/delwithsuffix.py
+++ b/mesonbuild/scripts/delwithsuffix.py
@@ -17,7 +17,7 @@
import os, sys
def run(args):
- if len(sys.argv) != 2:
+ if len(sys.argv) != 3:
print('delwithsuffix.py <root of subdir to process> <suffix to delete>')
sys.exit(1)
diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py
new file mode 100644
index 0000000..adc4483
--- /dev/null
+++ b/mesonbuild/scripts/gettext.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+
+# Copyright 2016 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os, subprocess, shutil
+
+def run_potgen(src_sub, pkgname, langs):
+ listfile = os.path.join(src_sub, 'POTFILES')
+ ofile = os.path.join(src_sub, pkgname + '.pot')
+ return subprocess.call(['xgettext', '--package-name=' + pkgname, '-p', src_sub, listfile,
+ '-D', os.environ['MESON_SOURCE_ROOT'], '-k_', '-o', ofile])
+
+def gen_gmo(src_sub, bld_sub, langs):
+ for l in langs:
+ subprocess.check_call(['msgfmt', os.path.join(src_sub, l + '.po'),
+ '-o', os.path.join(bld_sub, l + '.gmo')])
+ return 0
+
+def do_install(src_sub, bld_sub, dest, pkgname, langs):
+ for l in langs:
+ srcfile = os.path.join(bld_sub, l + '.gmo')
+ outfile = os.path.join(dest, l, 'LC_MESSAGES',
+ pkgname + '.mo')
+ os.makedirs(os.path.split(outfile)[0], exist_ok=True)
+ shutil.copyfile(srcfile, outfile)
+ shutil.copystat(srcfile, outfile)
+ print('Installing %s to %s.' % (srcfile, outfile))
+ return 0
+
+def run(args):
+ subcmd = args[0]
+ if subcmd == 'pot':
+ src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], os.environ['MESON_SUBDIR'])
+ bld_sub = os.path.join(os.environ['MESON_BUILD_ROOT'], os.environ['MESON_SUBDIR'])
+ return run_potgen(src_sub, args[1], args[2:])
+ elif subcmd == 'gen_gmo':
+ src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], os.environ['MESON_SUBDIR'])
+ bld_sub = os.path.join(os.environ['MESON_BUILD_ROOT'], os.environ['MESON_SUBDIR'])
+ return gen_gmo(src_sub, bld_sub, args[1:])
+ elif subcmd == 'install':
+ subdir = args[1]
+ pkgname = args[2]
+ instsubdir = args[3]
+ langs = args[4:]
+ src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], subdir)
+ bld_sub = os.path.join(os.environ['MESON_BUILD_ROOT'], subdir)
+ dest = os.environ.get('DESTDIR') + os.path.join(os.environ['MESON_INSTALL_PREFIX'], instsubdir)
+ if gen_gmo(src_sub, bld_sub, langs) != 0:
+ return 1
+ do_install(src_sub, bld_sub, dest, pkgname, langs)
+ else:
+ print('Unknown subcommand.')
+ return 1
diff --git a/mesonbuild/scripts/gtkdochelper.py b/mesonbuild/scripts/gtkdochelper.py
index 68be8f2..d920b61 100644
--- a/mesonbuild/scripts/gtkdochelper.py
+++ b/mesonbuild/scripts/gtkdochelper.py
@@ -28,9 +28,10 @@ parser.add_argument('--mainfile', dest='mainfile')
parser.add_argument('--modulename', dest='modulename')
parser.add_argument('--htmlargs', dest='htmlargs', default='')
parser.add_argument('--scanargs', dest='scanargs', default='')
+parser.add_argument('--fixxrefargs', dest='fixxrefargs', default='')
def build_gtkdoc(source_root, build_root, doc_subdir, src_subdir,
- main_file, module, html_args, scan_args):
+ main_file, module, html_args, scan_args, fixxref_args):
abs_src = os.path.join(source_root, src_subdir)
abs_out = os.path.join(build_root, doc_subdir)
htmldir = os.path.join(abs_out, 'html')
@@ -76,7 +77,7 @@ def build_gtkdoc(source_root, build_root, doc_subdir, src_subdir,
subprocess.check_call(mkhtml_cmd, cwd=os.path.join(abs_out, 'html'), shell=False)
fixref_cmd = ['gtkdoc-fixxref',
'--module=' + module,
- '--module-dir=html']
+ '--module-dir=html'] + fixxref_args
# print(fixref_cmd)
# sys.exit(1)
subprocess.check_call(fixref_cmd, cwd=abs_out)
@@ -97,6 +98,10 @@ def run(args):
scanargs = options.scanargs.split('@@')
else:
scanargs = []
+ if len(options.fixxrefargs) > 0:
+ fixxrefargs = options.fixxrefargs.split('@@')
+ else:
+ fixxrefargs = []
build_gtkdoc(options.sourcedir,
options.builddir,
options.subdir,
@@ -104,7 +109,8 @@ def run(args):
options.mainfile,
options.modulename,
htmlargs,
- scanargs)
+ scanargs,
+ fixxrefargs)
if 'MESON_INSTALL_PREFIX' in os.environ:
if 'DESTDIR' in os.environ:
diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py
new file mode 100644
index 0000000..f075fa0
--- /dev/null
+++ b/mesonbuild/scripts/meson_exe.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+
+# Copyright 2013-2016 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import sys
+import argparse
+import pickle
+import platform
+import subprocess
+
+import mesonbuild
+
+options = None
+
+parser = argparse.ArgumentParser()
+parser.add_argument('args', nargs='+')
+
+def is_windows():
+ platname = platform.system().lower()
+ return platname == 'windows' or 'mingw' in platname
+
+def run_with_mono(fname):
+ if fname.endswith('.exe') and not is_windows():
+ return True
+ return False
+
+def run_exe(exe):
+ if exe.fname[0].endswith('.jar'):
+ cmd = ['java', '-jar'] + exe.fname
+ elif not exe.is_cross and run_with_mono(exe.fname[0]):
+ cmd = ['mono'] + exe.fname
+ else:
+ if exe.is_cross:
+ if exe.exe_runner is None:
+ raise Exception('BUG: Trying to run cross-compiled exes with no wrapper')
+ else:
+ cmd = [exe.exe_runner] + exe.fname
+ else:
+ cmd = exe.fname
+ child_env = os.environ.copy()
+ child_env.update(exe.env)
+ if len(exe.extra_paths) > 0:
+ child_env['PATH'] = ';'.join(exe.extra_paths + ['']) + child_env['PATH']
+ p = subprocess.Popen(cmd + exe.cmd_args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=child_env,
+ cwd=exe.workdir)
+
+def run(args):
+ global options
+ options = parser.parse_args(args)
+ if len(options.args) != 1:
+ print('Test runner for Meson. Do not run on your own, mmm\'kay?')
+ print(sys.argv[0] + ' [data file]')
+ exe_data_file = options.args[0]
+ exe = pickle.load(open(exe_data_file, 'rb'))
+ run_exe(exe)
+
+if __name__ == '__main__':
+ sys.exit(run(sys.argv[1:]))
diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py
index cc86b62..20a50f7 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -33,7 +33,6 @@ def do_install(datafilename):
install_headers(d)
install_man(d)
install_data(d)
- install_po(d)
run_install_script(d)
def install_subdirs(d):
@@ -51,19 +50,6 @@ def install_subdirs(d):
shutil.copytree(src_dir, final_dst, symlinks=True)
print('Installing subdir %s to %s.' % (src_dir, dst_dir))
-def install_po(d):
- packagename = d.po_package_name
- for f in d.po:
- srcfile = f[0]
- localedir = f[1]
- languagename = f[2]
- outfile = os.path.join(d.fullprefix, localedir, languagename, 'LC_MESSAGES',
- packagename + '.mo')
- os.makedirs(os.path.split(outfile)[0], exist_ok=True)
- shutil.copyfile(srcfile, outfile)
- shutil.copystat(srcfile, outfile)
- print('Installing %s to %s.' % (srcfile, outfile))
-
def install_data(d):
for i in d.data:
fullfilename = i[0]
diff --git a/mesonbuild/scripts/scanbuild.py b/mesonbuild/scripts/scanbuild.py
new file mode 100644
index 0000000..f90c3c7
--- /dev/null
+++ b/mesonbuild/scripts/scanbuild.py
@@ -0,0 +1,39 @@
+# Copyright 2016 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys, os
+import subprocess
+import shutil
+import tempfile
+
+def scanbuild(srcdir, blddir, privdir, logdir, args):
+ with tempfile.TemporaryDirectory(dir=privdir) as scandir:
+ meson_cmd = ['scan-build'] + args
+ build_cmd = ['scan-build', '-o', logdir, 'ninja']
+ rc = subprocess.call(meson_cmd + [srcdir, scandir])
+ if rc != 0:
+ return rc
+ return subprocess.call(build_cmd)
+
+def run(args):
+ srcdir = args[0]
+ blddir = args[1]
+ meson_cmd = args[2:]
+ privdir = os.path.join(blddir, 'meson-private')
+ logdir = os.path.join(blddir, 'meson-logs/scanbuild')
+ shutil.rmtree(logdir, ignore_errors=True)
+ if not shutil.which('scan-build'):
+ print('Scan-build not installed')
+ return 1
+ return scanbuild(srcdir, blddir, privdir, logdir, meson_cmd)
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index ad8f106..6e3383c 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -90,10 +90,11 @@ class Resolver:
def resolve(self, packagename):
fname = os.path.join(self.subdir_root, packagename + '.wrap')
dirname = os.path.join(self.subdir_root, packagename)
+ if os.path.isdir(dirname):
+ # The directory is there? Great, use it.
+ return packagename
if not os.path.isfile(fname):
- if os.path.isdir(dirname):
- # No wrap file but dir exists -> user put it there manually.
- return packagename
+ # No wrap file with this name? Give up.
return None
p = PackageDefinition(fname)
if p.type == 'file':
diff --git a/test cases/common/42 string formatting/meson.build b/test cases/common/42 string formatting/meson.build
index c2ee151..0d17448 100644
--- a/test cases/common/42 string formatting/meson.build
+++ b/test cases/common/42 string formatting/meson.build
@@ -51,3 +51,7 @@ 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')
+
+assert(' '.join(['a', 'b', 'c']) == 'a b c', 'join() array broken')
+assert(''.join(['a', 'b', 'c']) == 'abc', 'empty join() broken')
+assert(' '.join(['a']) == 'a', 'single join broken')
diff --git a/test cases/common/43 has function/meson.build b/test cases/common/43 has function/meson.build
index 3736a3d..c7fe353 100644
--- a/test cases/common/43 has function/meson.build
+++ b/test cases/common/43 has function/meson.build
@@ -3,16 +3,16 @@ project('has function', 'c')
cc = meson.get_compiler('c')
if not cc.has_function('printf', prefix : '#include<stdio.h>')
- error('Existing function not found.')
+ error('"printf" function not found (should always exist).')
endif
# Should also be able to detect it without specifying the header
# We check for a different function here to make sure the result is
# not taken from a cache (ie. the check above)
-assert(cc.has_function('fprintf'), 'Existing function not found without include')
+assert(cc.has_function('fprintf'), '"fprintf" function not found without include (should always exist).')
if cc.has_function('hfkerhisadf', prefix : '#include<stdio.h>')
- error('Found non-existant function.')
+ error('Found non-existent function "hfkerhisadf".')
endif
# With glibc on Linux lchmod is a stub that will always return an error,
@@ -21,9 +21,9 @@ endif
# implemented in glibc it's probably not implemented in any other 'slimmer'
# C library variants either, so the check should be safe either way hopefully.
if host_machine.system() == 'linux' and cc.get_id() == 'gcc'
- assert (cc.has_function('poll', prefix : '#include <poll.h>'), 'couldn\'t detect poll when defined by a header')
+ assert (cc.has_function('poll', prefix : '#include <poll.h>'), 'couldn\'t detect "poll" when defined by a header')
assert (not cc.has_function('lchmod', prefix : '''#include <sys/stat.h>
- #include <unistd.h>'''), 'lchmod check should have failed')
+ #include <unistd.h>'''), '"lchmod" check should have failed')
endif
# For some functions one needs to define _GNU_SOURCE before including the
@@ -31,5 +31,5 @@ endif
# as well without any prefix
if cc.has_header_symbol('sys/socket.h', 'recvmmsg', prefix : '#define _GNU_SOURCE')
# We assume that if recvmmsg exists sendmmsg does too
- assert (cc.has_function('sendmmsg'), 'Failed to detect existing function')
+ assert (cc.has_function('sendmmsg'), 'Failed to detect function "sendmmsg" (should always exist).')
endif
diff --git a/test cases/frameworks/10 gtk-doc/doc/meson.build b/test cases/frameworks/10 gtk-doc/doc/meson.build
index 3172b42..5f08e89 100644
--- a/test cases/frameworks/10 gtk-doc/doc/meson.build
+++ b/test cases/frameworks/10 gtk-doc/doc/meson.build
@@ -1,5 +1,3 @@
-gnome = import('gnome')
-
cdata = configuration_data()
cdata.set('VERSION', '1.0')
configure_file(input : 'version.xml.in',
diff --git a/test cases/frameworks/10 gtk-doc/meson.build b/test cases/frameworks/10 gtk-doc/meson.build
index 9712f21..c6881ab 100644
--- a/test cases/frameworks/10 gtk-doc/meson.build
+++ b/test cases/frameworks/10 gtk-doc/meson.build
@@ -1,5 +1,9 @@
project('gtkdoctest', 'c')
+gnome = import('gnome')
+
+assert(gnome.gtkdoc_html_dir('foobar') == 'share/gtkdoc/html/foobar', 'Gtkdoc install dir is incorrect.')
+
inc = include_directories('include')
# We have to disable this test until this bug fix has landed to
diff --git a/test cases/frameworks/6 gettext/meson.build b/test cases/frameworks/6 gettext/meson.build
index 4384978..6bba7e0 100644
--- a/test cases/frameworks/6 gettext/meson.build
+++ b/test cases/frameworks/6 gettext/meson.build
@@ -1,4 +1,6 @@
project('gettext example', 'c')
+i18n = import('i18n')
+
subdir('po')
subdir('src')
diff --git a/test cases/frameworks/6 gettext/po/intltest.pot b/test cases/frameworks/6 gettext/po/intltest.pot
index 05da67d..d65e2c1 100644
--- a/test cases/frameworks/6 gettext/po/intltest.pot
+++ b/test cases/frameworks/6 gettext/po/intltest.pot
@@ -1,6 +1,6 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
+# This file is distributed under the same license as the intltest package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: intltest\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-09-12 19:04+0300\n"
+"POT-Creation-Date: 2016-03-28 19:59+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/test cases/frameworks/6 gettext/po/meson.build b/test cases/frameworks/6 gettext/po/meson.build
index 3376c84..8ea2c11 100644
--- a/test cases/frameworks/6 gettext/po/meson.build
+++ b/test cases/frameworks/6 gettext/po/meson.build
@@ -1,4 +1,3 @@
langs = ['fi', 'de']
-gettext('intltest',
-languages : langs)
+i18n.gettext('intltest', languages : langs)