aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--authors.txt5
-rw-r--r--data/macros.meson11
-rwxr-xr-xghwt.py4
-rw-r--r--man/meson.12
-rw-r--r--man/mesonconf.12
-rw-r--r--man/mesonintrospect.12
-rw-r--r--man/wraptool.12
-rw-r--r--mesonbuild/backend/backends.py107
-rw-r--r--mesonbuild/backend/ninjabackend.py199
-rw-r--r--mesonbuild/backend/vs2010backend.py120
-rw-r--r--mesonbuild/backend/xcodebackend.py36
-rw-r--r--mesonbuild/build.py81
-rw-r--r--mesonbuild/compilers.py383
-rw-r--r--mesonbuild/coredata.py13
-rw-r--r--mesonbuild/dependencies.py51
-rw-r--r--mesonbuild/environment.py50
-rw-r--r--mesonbuild/interpreter.py155
-rw-r--r--mesonbuild/mconf.py9
-rw-r--r--mesonbuild/mesonlib.py24
-rw-r--r--mesonbuild/mesonmain.py11
-rw-r--r--mesonbuild/mintro.py12
-rw-r--r--mesonbuild/modules/gnome.py103
-rw-r--r--mesonbuild/modules/pkgconfig.py73
-rw-r--r--mesonbuild/modules/rpm.py147
-rw-r--r--mesonbuild/mparser.py9
-rw-r--r--mesonbuild/optinterpreter.py11
-rw-r--r--mesonbuild/scripts/__init__.py2
-rw-r--r--mesonbuild/scripts/depfixer.py34
-rw-r--r--mesonbuild/scripts/meson_benchmark.py43
-rw-r--r--mesonbuild/scripts/meson_exe.py12
-rw-r--r--mesonbuild/scripts/meson_install.py41
-rw-r--r--mesonbuild/scripts/meson_test.py58
-rw-r--r--mesonbuild/scripts/regen_checker.py6
-rw-r--r--mesonbuild/scripts/symbolextractor.py9
-rw-r--r--mesonbuild/scripts/vcstagger.py13
-rw-r--r--mesonbuild/wrap/wrap.py85
-rwxr-xr-xmesonbuild/wrap/wraptool.py6
-rwxr-xr-xrun_tests.py24
-rwxr-xr-xtest cases/common/103 manygen/subdir/manygen.py18
-rw-r--r--test cases/common/107 postconf/postconf.py9
-rw-r--r--test cases/common/108 postconf with args/postconf.py9
-rwxr-xr-xtest cases/common/113 generatorcustom/catter.py3
-rwxr-xr-xtest cases/common/113 generatorcustom/gen.py6
-rw-r--r--test cases/common/117 custom target capture/data_source.txt1
-rw-r--r--test cases/common/117 custom target capture/installed_files.txt1
-rw-r--r--test cases/common/117 custom target capture/meson.build16
-rwxr-xr-xtest cases/common/117 custom target capture/my_compiler.py14
-rwxr-xr-xtest cases/common/16 configure file/generator.py10
-rw-r--r--test cases/common/29 pipeline/meson.build5
-rw-r--r--test cases/common/29 pipeline/srcgen.c35
-rw-r--r--test cases/common/38 run program/meson.build14
-rw-r--r--test cases/common/44 has member/meson.build12
-rwxr-xr-xtest cases/common/48 test args/tester.py5
-rw-r--r--test cases/common/52 custom install dirs/installed_files.txt6
-rw-r--r--test cases/common/52 custom install dirs/meson.build6
-rw-r--r--test cases/common/52 custom install dirs/subdir/datafile.dog1
-rwxr-xr-xtest cases/common/56 custom target/depfile/dep.py15
-rw-r--r--test cases/common/56 custom target/depfile/meson.build7
-rw-r--r--test cases/common/56 custom target/meson.build2
-rwxr-xr-xtest cases/common/56 custom target/my_compiler.py7
-rw-r--r--test cases/common/57 custom target chain/installed_files.txt1
-rw-r--r--test cases/common/57 custom target chain/meson.build10
-rwxr-xr-xtest cases/common/57 custom target chain/my_compiler.py7
-rwxr-xr-xtest cases/common/57 custom target chain/my_compiler2.py7
-rwxr-xr-xtest cases/common/57 custom target chain/usetarget/subcomp.py4
-rw-r--r--test cases/common/58 run target/converter.py3
-rwxr-xr-xtest cases/common/58 run target/fakeburner.py3
-rw-r--r--test cases/common/58 run target/meson.build9
-rwxr-xr-xtest cases/common/61 custom target source output/generator.py6
-rw-r--r--test cases/common/64 custom header generator/makeheader.py6
-rwxr-xr-xtest cases/common/65 multiple generators/mygen.py9
-rw-r--r--test cases/common/68 number arithmetic/meson.build21
-rwxr-xr-xtest cases/common/72 build always/version_gen.py9
-rw-r--r--test cases/common/76 configure file in custom target/src/mycompiler.py9
-rwxr-xr-xtest cases/common/78 ctarget dependency/gen1.py6
-rwxr-xr-xtest cases/common/78 ctarget dependency/gen2.py3
-rwxr-xr-xtest cases/common/93 private include/stlib/compiler.py6
-rw-r--r--test cases/common/95 dep fallback/meson.build6
-rwxr-xr-xtest cases/common/98 gen extra/srcgen.py6
-rw-r--r--test cases/d/1 simple/app.d8
-rw-r--r--test cases/d/1 simple/installed_files.txt1
-rw-r--r--test cases/d/1 simple/meson.build4
-rw-r--r--test cases/d/1 simple/utils.d8
-rw-r--r--test cases/d/2 static library/app.d8
-rw-r--r--test cases/d/2 static library/installed_files.txt2
-rw-r--r--test cases/d/2 static library/libstuff.d9
-rw-r--r--test cases/d/2 static library/meson.build5
-rw-r--r--test cases/d/3 shared library/app.d8
-rw-r--r--test cases/d/3 shared library/installed_files.txt2
-rw-r--r--test cases/d/3 shared library/libstuff.d9
-rw-r--r--test cases/d/3 shared library/meson.build12
-rw-r--r--test cases/d/3 shared library/no-installed-files0
-rw-r--r--test cases/d/4 library versions/installed_files.txt9
-rw-r--r--test cases/d/4 library versions/lib.d10
-rw-r--r--test cases/d/4 library versions/meson.build25
-rw-r--r--test cases/d/4 library versions/no-installed-files0
-rw-r--r--test cases/d/5 mixed/app.d8
-rw-r--r--test cases/d/5 mixed/installed_files.txt4
-rw-r--r--test cases/d/5 mixed/libstuff.c18
-rw-r--r--test cases/d/5 mixed/meson.build9
-rw-r--r--test cases/d/6 unittest/app.d34
-rw-r--r--test cases/d/6 unittest/installed_files.txt1
-rw-r--r--test cases/d/6 unittest/meson.build8
-rw-r--r--test cases/failing/31 invalid man extension/meson.build2
-rw-r--r--test cases/failing/32 no man extension/meson.build2
-rw-r--r--test cases/frameworks/11 gir subproject/gir/meson-subsample.c124
-rw-r--r--test cases/frameworks/11 gir subproject/gir/meson-subsample.h21
-rw-r--r--test cases/frameworks/11 gir subproject/gir/meson.build35
-rw-r--r--test cases/frameworks/11 gir subproject/gir/prog.c12
-rwxr-xr-xtest cases/frameworks/11 gir subproject/gir/prog.py6
-rw-r--r--test cases/frameworks/11 gir subproject/installed_files.txt6
-rw-r--r--test cases/frameworks/11 gir subproject/meson.build10
-rw-r--r--test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.c127
-rw-r--r--test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.h26
-rw-r--r--test cases/frameworks/11 gir subproject/subprojects/mesongir/meson.build31
-rw-r--r--test cases/frameworks/6 gettext/src/meson.build3
-rw-r--r--test cases/frameworks/7 gnome/gir/prog.c14
-rw-r--r--test cases/frameworks/9 wxwidgets/meson.build9
-rw-r--r--test cases/osx/2 library versions/exe.orig.c4
-rw-r--r--test cases/osx/2 library versions/installed_files.txt6
-rw-r--r--test cases/osx/2 library versions/meson.build31
-rwxr-xr-xtools/ac_converter.py107
-rwxr-xr-xtools/cmake2meson.py55
124 files changed, 2346 insertions, 777 deletions
diff --git a/README.md b/README.md
index 5e0eae7..95915b0 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ build system.
####Dependencies
- [Python](http://python.org) (version 3.4 or newer)
- - [Ninja](http://martine.github.com/ninja/)
+ - [Ninja](https://ninja-build.org)
####Installing from source
diff --git a/authors.txt b/authors.txt
index 4244917..fbac571 100644
--- a/authors.txt
+++ b/authors.txt
@@ -40,3 +40,8 @@ Noam Meltzer
Vincent Szolnoky
Zhe Wang
Wim Taymans
+Matthias Klumpp
+Elliott Sales de Andrade
+Patrick Griffis
+Iain Lane
+Daniel Brendle
diff --git a/data/macros.meson b/data/macros.meson
index 8aa5555..c89854b 100644
--- a/data/macros.meson
+++ b/data/macros.meson
@@ -7,6 +7,15 @@
export FCFLAGS="%{optflags} -I%{_fmoddir}" ; \
export LDFLAGS="%{__global_ldflags}" ; \
%__meson %{?1} \\\
- --prefix=%{_prefix} \\\
+ --prefix=%{_prefix} \\\
+ --libdir=%{_libdir} \\\
+ --libexecdir=%{_libexecdir} \\\
+ --bindir=%{_bindir} \\\
+ --includedir=%{_includedir} \\\
+ --datadir=%{_datadir} \\\
+ --mandir=%{_mandir} \\\
+ --localedir=%{_datadir}/locale \\\
+ --sysconfdir=%{_sysconfdir} \\\
--buildtype=plain \
+ %{nil} \
}
diff --git a/ghwt.py b/ghwt.py
index 493b1e2..bb0be70 100755
--- a/ghwt.py
+++ b/ghwt.py
@@ -52,8 +52,8 @@ def unpack(sproj, branch, outdir):
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)
+ with open(ofilename, 'wb') as ofile:
+ ofile.write(us)
if 'lead_directory_missing' in config['wrap-file']:
os.mkdir(outdir)
shutil.unpack_archive(ofilename, outdir)
diff --git a/man/meson.1 b/man/meson.1
index 83ac397..f41a945 100644
--- a/man/meson.1
+++ b/man/meson.1
@@ -1,4 +1,4 @@
-.TH MESON "1" "July 2016" "meson 0.33.0" "User Commands"
+.TH MESON "1" "September 2016" "meson 0.34.0" "User Commands"
.SH NAME
meson - a high productivity build system
.SH DESCRIPTION
diff --git a/man/mesonconf.1 b/man/mesonconf.1
index 35f8486..4009c58 100644
--- a/man/mesonconf.1
+++ b/man/mesonconf.1
@@ -1,4 +1,4 @@
-.TH MESONCONF "1" "July 2016" "mesonconf 0.33.0" "User Commands"
+.TH MESONCONF "1" "September 2016" "mesonconf 0.34.0" "User Commands"
.SH NAME
mesonconf - a tool to configure Meson builds
.SH DESCRIPTION
diff --git a/man/mesonintrospect.1 b/man/mesonintrospect.1
index 307b99a..74a006c 100644
--- a/man/mesonintrospect.1
+++ b/man/mesonintrospect.1
@@ -1,4 +1,4 @@
-.TH MESONCONF "1" "July 2016" "mesonintrospect 0.33.0" "User Commands"
+.TH MESONCONF "1" "September 2016" "mesonintrospect 0.34.0" "User Commands"
.SH NAME
mesonintrospect - a tool to extract information about a Meson build
.SH DESCRIPTION
diff --git a/man/wraptool.1 b/man/wraptool.1
index 26d942f..b2168c3 100644
--- a/man/wraptool.1
+++ b/man/wraptool.1
@@ -1,4 +1,4 @@
-.TH WRAPTOOL "1" "July 2016" "meson 0.33.0" "User Commands"
+.TH WRAPTOOL "1" "September 2016" "meson 0.34.0" "User Commands"
.SH NAME
wraptool - source dependency downloader
.SH DESCRIPTION
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 81283dc..6f4501c 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -16,6 +16,7 @@ import os, pickle, re
from .. import build
from .. import dependencies
from .. import mesonlib
+from .. import compilers
import json
import subprocess
from ..mesonlib import MesonException
@@ -36,7 +37,7 @@ class InstallData():
class ExecutableSerialisation():
def __init__(self, name, fname, cmd_args, env, is_cross, exe_wrapper,
- workdir, extra_paths):
+ workdir, extra_paths, capture):
self.name = name
self.fname = fname
self.cmd_args = cmd_args
@@ -45,6 +46,7 @@ class ExecutableSerialisation():
self.exe_runner = exe_wrapper
self.workdir = workdir
self.extra_paths = extra_paths
+ self.capture = capture
class TestSerialisation:
def __init__(self, name, suite, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env,
@@ -143,24 +145,34 @@ class Backend():
langlist = {}
abs_files = []
result = []
- for src in unity_src:
- comp = self.get_compiler_for_source(src, target.is_cross)
- language = comp.get_language()
- suffix = '.' + comp.get_default_suffix()
- if language not in langlist:
- outfilename = os.path.join(self.get_target_private_dir_abs(target), target.name + '-unity' + suffix)
- outfileabs = os.path.join(self.environment.get_build_dir(), outfilename)
- outfileabs_tmp = outfileabs + '.tmp'
- abs_files.append(outfileabs)
- outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp)
- if not os.path.exists(outfileabs_tmp_dir):
- os.makedirs(outfileabs_tmp_dir)
- outfile = open(outfileabs_tmp, 'w')
- langlist[language] = outfile
- result.append(outfilename)
- ofile = langlist[language]
- ofile.write('#include<%s>\n' % src)
- [x.close() for x in langlist.values()]
+
+ def init_language_file(language, suffix):
+ outfilename = os.path.join(self.get_target_private_dir_abs(target),
+ target.name + '-unity' + suffix)
+ outfileabs = os.path.join(self.environment.get_build_dir(),
+ outfilename)
+ outfileabs_tmp = outfileabs + '.tmp'
+ abs_files.append(outfileabs)
+ outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp)
+ if not os.path.exists(outfileabs_tmp_dir):
+ os.makedirs(outfileabs_tmp_dir)
+ result.append(outfilename)
+ return open(outfileabs_tmp, 'w')
+
+ try:
+ for src in unity_src:
+ comp = self.get_compiler_for_source(src, target.is_cross)
+ language = comp.get_language()
+ try:
+ ofile = langlist[language]
+ except KeyError:
+ suffix = '.' + comp.get_default_suffix()
+ ofile = langlist[language] = init_language_file(language,
+ suffix)
+ ofile.write('#include<%s>\n' % src)
+ finally:
+ for x in langlist.values():
+ x.close()
[mesonlib.replace_if_different(x, x + '.tmp') for x in abs_files]
return result
@@ -181,18 +193,25 @@ class Backend():
raise MesonException('Unknown data type in object list.')
return obj_list
- def serialise_executable(self, exe, cmd_args, workdir, env={}):
+ def serialise_executable(self, exe, cmd_args, workdir, env={},
+ capture=None):
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,
+ if isinstance(exe, (dependencies.ExternalProgram,
+ build.BuildTarget, build.CustomTarget)):
+ basename = exe.name
+ else:
+ basename = os.path.basename(exe)
+ scratch_file = 'meson_exe_{0}_{1}.dat'.format(basename,
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
+ elif isinstance(exe, (build.BuildTarget, build.CustomTarget)):
+ exe_fullpath = [self.get_target_filename_abs(exe)]
else:
- exe_fullpath = [os.path.join(self.environment.get_build_dir(),
- self.get_target_filename(exe))]
+ exe_fullpath = [exe]
is_cross = self.environment.is_cross_build() and \
self.environment.cross_info.need_cross_compiler() and \
self.environment.cross_info.need_exe_wrapper()
@@ -204,21 +223,19 @@ class Backend():
extra_paths = self.determine_windows_extra_paths(exe)
else:
extra_paths = []
- es = ExecutableSerialisation(exe.name, exe_fullpath, cmd_args, env,
+ es = ExecutableSerialisation(basename, exe_fullpath, cmd_args, env,
is_cross, exe_wrapper, workdir,
- extra_paths)
+ extra_paths, capture)
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')
- self.write_test_file(datafile)
- datafile.close()
+ with open(test_data, 'wb') as datafile:
+ self.write_test_file(datafile)
benchmark_data = os.path.join(self.environment.get_scratch_dir(), 'meson_benchmark_setup.dat')
- datafile = open(benchmark_data, 'wb')
- self.write_benchmark_file(datafile)
- datafile.close()
+ with open(benchmark_data, 'wb') as datafile:
+ self.write_benchmark_file(datafile)
return (test_data, benchmark_data)
def has_source_suffix(self, target, suffix):
@@ -239,6 +256,9 @@ class Backend():
def has_swift(self, target):
return self.has_source_suffix(target, '.swift')
+ def has_d(self, target):
+ return self.has_source_suffix(target, '.d')
+
def determine_linker(self, target, src):
if isinstance(target, build.StaticLibrary):
if self.build.static_cross_linker is not None:
@@ -361,10 +381,12 @@ class Backend():
def build_target_link_arguments(self, compiler, deps):
args = []
for d in deps:
- if not isinstance(d, build.StaticLibrary) and\
- not isinstance(d, build.SharedLibrary):
+ if not isinstance(d, (build.StaticLibrary, build.SharedLibrary)):
raise RuntimeError('Tried to link with a non-library target "%s".' % d.get_basename())
- args.append(self.get_target_filename_for_linking(d))
+ if isinstance(compiler, compilers.LLVMDCompiler):
+ args.extend(['-L', self.get_target_filename_for_linking(d)])
+ else:
+ args.append(self.get_target_filename_for_linking(d))
# If you have executable e that links to shared lib s1 that links to shared library s2
# you have to specify s2 as well as s1 when linking e even if e does not directly use
# s2. Gcc handles this case fine but Clang does not for some reason. Thus we need to
@@ -434,7 +456,8 @@ class Backend():
mfobj = {'type': 'dependency manifest',
'version': '1.0'}
mfobj['projects'] = self.build.dep_manifest
- open(ifilename, 'w').write(json.dumps(mfobj))
+ with open(ifilename, 'w') as f:
+ f.write(json.dumps(mfobj))
d.data.append([ifilename, ofilename])
def get_regen_filelist(self):
@@ -519,7 +542,7 @@ class Backend():
i = i.held_object
if isinstance(i, str):
fname = [os.path.join(self.build_to_src, target.subdir, i)]
- elif isinstance(i, build.BuildTarget):
+ elif isinstance(i, (build.BuildTarget, build.CustomTarget)):
fname = [self.get_target_filename(i)]
elif isinstance(i, build.GeneratedList):
fname = [os.path.join(self.get_target_private_dir(target), p) for p in i.get_outfilelist()]
@@ -539,7 +562,7 @@ class Backend():
tmp = i.get_filename()[0]
i = os.path.join(self.get_target_dir(i), tmp)
elif isinstance(i, mesonlib.File):
- i = os.path.join(i.subdir, i.fname)
+ i = i.rel_to_builddir(self.build_to_src)
if absolute_paths:
i = os.path.join(self.environment.get_build_dir(), i)
# FIXME: str types are blindly added and ignore the 'absolute_paths' argument
@@ -557,6 +580,14 @@ class Backend():
else:
if '@OUTDIR@' in i:
i = i.replace('@OUTDIR@', outdir)
+ elif '@DEPFILE@' in i:
+ if target.depfile is None:
+ raise MesonException('Custom target %s has @DEPFILE@ but no depfile keyword argument.' % target.name)
+ if absolute_paths:
+ dfilename = os.path.join(self.get_target_private_dir_abs(target), target.depfile)
+ else:
+ dfilename = os.path.join(self.get_target_private_dir(target), target.depfile)
+ i = i.replace('@DEPFILE@', dfilename)
elif '@PRIVATE_OUTDIR_' in i:
match = re.search('@PRIVATE_OUTDIR_(ABS_)?([-a-zA-Z0-9.@:]*)@', i)
source = match.group(0)
@@ -564,12 +595,10 @@ class Backend():
lead_dir = ''
else:
lead_dir = self.environment.get_build_dir()
- target_id = match.group(2)
i = i.replace(source,
os.path.join(lead_dir,
outdir))
cmd.append(i)
- cmd = [i.replace('\\', '/') for i in cmd]
return (srcs, ofilenames, cmd)
def run_postconf_scripts(self):
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index e00fe2f..db9e1b0 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -133,17 +133,18 @@ class NinjaBackend(backends.Backend):
self.all_outputs = {}
self.valgrind = environment.find_valgrind()
- def detect_vs_dep_prefix(self, outfile, tempfilename):
+ def detect_vs_dep_prefix(self, tempfilename):
'''VS writes its dependency in a locale dependent format.
Detect the search prefix to use.'''
# Of course there is another program called 'cl' on
# some platforms. Let's just require that on Windows
# cl points to msvc.
if not mesonlib.is_windows() or shutil.which('cl') is None:
- return outfile
- outfile.close()
- open(os.path.join(self.environment.get_scratch_dir(), 'incdetect.c'),
- 'w').write('''#include<stdio.h>
+ return open(tempfilename, 'a')
+ filename = os.path.join(self.environment.get_scratch_dir(),
+ 'incdetect.c')
+ with open(filename, 'w') as f:
+ f.write('''#include<stdio.h>
int dummy;
''')
@@ -157,9 +158,8 @@ int dummy;
for line in stdo.split(b'\r\n'):
if line.endswith(b'stdio.h'):
matchstr = b':'.join(line.split(b':')[0:2]) + b':'
- binfile = open(tempfilename, 'ab')
- binfile.write(b'msvc_deps_prefix = ' + matchstr + b'\r\n')
- binfile.close()
+ with open(tempfilename, 'ab') as binfile:
+ binfile.write(b'msvc_deps_prefix = ' + matchstr + b'\r\n')
return open(tempfilename, 'a')
raise MesonException('Could not determine vs dep dependency prefix string.')
@@ -167,30 +167,31 @@ int dummy;
self.interpreter = interp
outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename)
tempfilename = outfilename + '~'
- outfile = open(tempfilename, 'w')
- outfile.write('# This is the build file for project "%s"\n' % self.build.get_project())
- outfile.write('# It is autogenerated by the Meson build system.\n')
- outfile.write('# Do not edit by hand.\n\n')
- outfile.write('ninja_required_version = 1.5.1\n\n')
- outfile = self.detect_vs_dep_prefix(outfile, tempfilename)
- self.generate_rules(outfile)
- 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()]
- outfile.write('# Test rules\n\n')
- self.generate_tests(outfile)
- outfile.write('# Install rules\n\n')
- self.generate_install(outfile)
- if 'b_coverage' in self.environment.coredata.base_options and \
- self.environment.coredata.base_options['b_coverage'].value:
- outfile.write('# Coverage rules\n\n')
- self.generate_coverage_rules(outfile)
- outfile.write('# Suffix\n\n')
- self.generate_utils(outfile)
- self.generate_ending(outfile)
+ with open(tempfilename, 'w') as outfile:
+ outfile.write('# This is the build file for project "%s"\n' %
+ self.build.get_project())
+ outfile.write('# It is autogenerated by the Meson build system.\n')
+ outfile.write('# Do not edit by hand.\n\n')
+ outfile.write('ninja_required_version = 1.5.1\n\n')
+ with self.detect_vs_dep_prefix(tempfilename) as outfile:
+ self.generate_rules(outfile)
+ self.generate_phony(outfile)
+ outfile.write('# Build rules for targets\n\n')
+ for t in self.build.get_targets().values():
+ self.generate_target(t, outfile)
+ outfile.write('# Test rules\n\n')
+ self.generate_tests(outfile)
+ outfile.write('# Install rules\n\n')
+ self.generate_install(outfile)
+ if 'b_coverage' in self.environment.coredata.base_options and \
+ self.environment.coredata.base_options['b_coverage'].value:
+ 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.
- outfile.close()
os.replace(tempfilename, outfilename)
self.generate_compdb()
@@ -202,7 +203,8 @@ int dummy;
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)
+ with open(os.path.join(builddir, 'compile_commands.json'), 'wb') as f:
+ f.write(jsondb)
# Get all generated headers. Any source file might need them so
# we need to add an order dependency to them.
@@ -366,7 +368,11 @@ int dummy;
desc = 'Generating {0} with a {1} command.'
if target.build_always:
deps.append('PHONY')
- elem = NinjaBuildElement(self.all_outputs, ofilenames, 'CUSTOM_COMMAND', srcs)
+ if target.depfile is None:
+ rulename = 'CUSTOM_COMMAND'
+ else:
+ rulename = 'CUSTOM_COMMAND_DEP'
+ elem = NinjaBuildElement(self.all_outputs, ofilenames, rulename, srcs)
for i in target.depend_files:
if isinstance(i, mesonlib.File):
deps.append(i.rel_to_builddir(self.build_to_src))
@@ -379,21 +385,30 @@ int dummy;
tmp = [tmp]
for fname in tmp:
elem.add_dep(os.path.join(self.get_target_dir(d), fname))
+ # If the target requires capturing stdout, then use the serialized
+ # executable wrapper to capture that output and save it to a file.
+ #
# 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]):
+ if target.capture or (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())
+ self.environment.get_build_dir(),
+ capture=ofilenames[0] if target.capture else None)
cmd = [sys.executable, self.environment.get_build_command(),
'--internal', 'exe', exe_data]
cmd_type = 'meson_exe.py custom'
else:
cmd_type = 'custom'
+ if target.depfile is not None:
+ rel_dfile = os.path.join(self.get_target_private_dir(target), target.depfile)
+ abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_private_dir(target))
+ os.makedirs(abs_pdir, exist_ok=True)
+ elem.add_item('DEPFILE', rel_dfile)
elem.add_item('COMMAND', cmd)
elem.add_item('description', desc.format(target.name, cmd_type))
elem.write(outfile)
@@ -409,11 +424,13 @@ int dummy;
elif isinstance(i, (build.BuildTarget, build.CustomTarget)):
relfname = self.get_target_filename(i)
arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname))
+ deps.append(relfname)
+ elif isinstance(i, mesonlib.File):
+ arg_strings.append(i.rel_to_builddir(self.build_to_src))
else:
mlog.debug(str(i))
raise MesonException('Unreachable code in generate_run_target.')
- elem = NinjaBuildElement(self.all_outputs, target.name, 'CUSTOM_COMMAND', deps)
- elem.add_dep(deps)
+ elem = NinjaBuildElement(self.all_outputs, target.name, 'CUSTOM_COMMAND', [])
cmd = runnerscript + [self.environment.get_source_dir(), self.environment.get_build_dir(), target.subdir]
texe = target.command
try:
@@ -431,9 +448,13 @@ int dummy;
cmd.append(abs_exe)
elif isinstance(texe, dependencies.ExternalProgram):
cmd += texe.get_command()
+ elif isinstance(texe, build.CustomTarget):
+ deps.append(self.get_target_filename(texe))
+ cmd += [os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe))]
else:
cmd.append(target.command)
cmd += arg_strings
+ elem.add_dep(deps)
elem.add_item('COMMAND', cmd)
elem.add_item('description', 'Running external command %s.' % target.name)
elem.add_item('pool', 'console')
@@ -492,8 +513,8 @@ int dummy;
self.generate_subdir_install(d)
elem.write(outfile)
- ofile = open(install_data_file, 'wb')
- pickle.dump(d, ofile)
+ with open(install_data_file, 'wb') as ofile:
+ pickle.dump(d, ofile)
def generate_target_install(self, d):
should_strip = self.environment.coredata.get_builtin_option('strip')
@@ -643,7 +664,6 @@ int dummy;
velem.write(outfile)
# And then benchmarks.
- benchmark_script = os.path.join(script_root, 'meson_benchmark.py')
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)
@@ -664,6 +684,14 @@ int dummy;
outfile.write(' command = $COMMAND\n')
outfile.write(' description = $DESC\n')
outfile.write(' restat = 1\n\n')
+ # Ninja errors out if you have deps = gcc but no depfile, so we must
+ # have two rules for custom commands.
+ outfile.write('rule CUSTOM_COMMAND_DEP\n')
+ outfile.write(' command = $COMMAND\n')
+ outfile.write(' description = $DESC\n')
+ outfile.write(' deps = gcc\n')
+ outfile.write(' depfile = $DEPFILE\n')
+ outfile.write(' restat = 1\n\n')
outfile.write('rule REGENERATE_BUILD\n')
c = (quote_char + ninja_quote(sys.executable) + quote_char,
quote_char + ninja_quote(self.environment.get_build_command()) + quote_char,
@@ -1358,8 +1386,16 @@ rule FORTRAN_DEP_HACK
infilename = os.path.join(self.build_to_src, curfile)
outfiles = genlist.get_outputs_for(curfile)
outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles]
+ if generator.depfile is None:
+ rulename = 'CUSTOM_COMMAND'
+ args = base_args
+ else:
+ rulename = 'CUSTOM_COMMAND_DEP'
+ depfilename = generator.get_dep_outname(infilename)
+ depfile = os.path.join(self.get_target_private_dir(target), depfilename)
+ args = [x.replace('@DEPFILE@', depfile) for x in base_args]
args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\
- for x in base_args]
+ for x in args]
args = self.replace_outputs(args, self.get_target_private_dir(target), outfilelist)
# We have consumed output files, so drop them from the list of remaining outputs.
if sole_output == '':
@@ -1368,7 +1404,9 @@ rule FORTRAN_DEP_HACK
args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout)
for x in args]
cmdlist = exe_arr + self.replace_extra_args(args, genlist)
- elem = NinjaBuildElement(self.all_outputs, outfiles, 'CUSTOM_COMMAND', infilename)
+ elem = NinjaBuildElement(self.all_outputs, outfiles, rulename, infilename)
+ if generator.depfile is not None:
+ elem.add_item('DEPFILE', depfile)
if len(extra_dependencies) > 0:
elem.add_dep(extra_dependencies)
elem.add_item('DESC', 'Generating $out')
@@ -1393,16 +1431,22 @@ rule FORTRAN_DEP_HACK
# but those are really rare. I hope.
if not compiler.can_compile(s):
continue
- for line in open(os.path.join(self.environment.get_source_dir(), s.subdir, s.fname)):
- modmatch = modre.match(line)
- if modmatch is not None:
- modname = modmatch.group(1)
- if modname.lower() == 'procedure': # MODULE PROCEDURE construct
- continue
- if modname in module_files:
- raise InvalidArguments('Namespace collision: module %s defined in two files %s and %s.' %
- (modname, module_files[modname], s))
- module_files[modname] = s
+ filename = os.path.join(self.environment.get_source_dir(),
+ s.subdir, s.fname)
+ with open(filename) as f:
+ for line in f:
+ modmatch = modre.match(line)
+ if modmatch is not None:
+ modname = modmatch.group(1)
+ if modname.lower() == 'procedure':
+ # MODULE PROCEDURE construct
+ continue
+ if modname in module_files:
+ raise InvalidArguments(
+ 'Namespace collision: module %s defined in '
+ 'two files %s and %s.' %
+ (modname, module_files[modname], s))
+ module_files[modname] = s
self.fortran_deps[target.get_basename()] = module_files
def get_fortran_deps(self, compiler, src, target):
@@ -1410,27 +1454,32 @@ rule FORTRAN_DEP_HACK
usere = re.compile(r"\s*use\s+(\w+)", re.IGNORECASE)
dirname = self.get_target_private_dir(target)
tdeps= self.fortran_deps[target.get_basename()]
- for line in open(src):
- usematch = usere.match(line)
- if usematch is not None:
- usename = usematch.group(1)
- if usename not in tdeps:
- # The module is not provided by any source file. This is due to
- # a) missing file/typo/etc
- # b) using a module provided by the compiler, such as OpenMP
- # There's no easy way to tell which is which (that I know of)
- # so just ignore this and go on. Ideally we would print a
- # warning message to the user but this is a common occurrance,
- # which would lead to lots of distracting noise.
- continue
- mod_source_file = tdeps[usename]
- # Check if a source uses a module it exports itself.
- # Potential bug if multiple targets have a file with
- # the same name.
- if mod_source_file.fname == os.path.split(src)[1]:
- continue
- mod_name = compiler.module_name_to_filename(usematch.group(1))
- mod_files.append(os.path.join(dirname, mod_name))
+ with open(src) as f:
+ for line in f:
+ usematch = usere.match(line)
+ if usematch is not None:
+ usename = usematch.group(1)
+ if usename not in tdeps:
+ # The module is not provided by any source file. This
+ # is due to:
+ # a) missing file/typo/etc
+ # b) using a module provided by the compiler, such as
+ # OpenMP
+ # There's no easy way to tell which is which (that I
+ # know of) so just ignore this and go on. Ideally we
+ # would print a warning message to the user but this is
+ # a common occurrence, which would lead to lots of
+ # distracting noise.
+ continue
+ mod_source_file = tdeps[usename]
+ # Check if a source uses a module it exports itself.
+ # Potential bug if multiple targets have a file with
+ # the same name.
+ if mod_source_file.fname == os.path.split(src)[1]:
+ continue
+ mod_name = compiler.module_name_to_filename(
+ usematch.group(1))
+ mod_files.append(os.path.join(dirname, mod_name))
return mod_files
def get_cross_stdlib_args(self, target, compiler):
@@ -1555,9 +1604,7 @@ rule FORTRAN_DEP_HACK
else:
raise build.InvalidArguments('Invalid source type.')
abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
- if isinstance(src, RawFilename):
- src_filename = src.fname
- elif isinstance(src, File):
+ if isinstance(src, (RawFilename, File)):
src_filename = src.fname
elif os.path.isabs(src):
src_filename = os.path.basename(src)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 669bcf8..eca7473 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -175,14 +175,18 @@ class Vs2010Backend(backends.Backend):
@staticmethod
def touch_regen_timestamp(build_dir):
- open(Vs2010Backend.get_regen_stampfile(build_dir), 'w').close()
+ with open(Vs2010Backend.get_regen_stampfile(build_dir), 'w'):
+ pass
def generate_regen_info(self):
deps = self.get_regen_filelist()
regeninfo = RegenInfo(self.environment.get_source_dir(),
self.environment.get_build_dir(),
deps)
- pickle.dump(regeninfo, open(os.path.join(self.environment.get_scratch_dir(), 'regeninfo.dump'), 'wb'))
+ filename = os.path.join(self.environment.get_scratch_dir(),
+ 'regeninfo.dump')
+ with open(filename, 'wb') as f:
+ pickle.dump(regeninfo, f)
def get_obj_target_deps(self, obj_list):
result = {}
@@ -217,57 +221,66 @@ class Vs2010Backend(backends.Backend):
return all_deps
def generate_solution(self, sln_filename, projlist):
- ofile = open(sln_filename, 'w')
- ofile.write('Microsoft Visual Studio Solution File, Format Version 11.00\n')
- ofile.write('# Visual Studio ' + self.vs_version + '\n')
- prj_templ = prj_line = 'Project("{%s}") = "%s", "%s", "{%s}"\n'
- for p in projlist:
- prj_line = prj_templ % (self.environment.coredata.guid, p[0], p[1], p[2])
- ofile.write(prj_line)
- all_deps = self.determine_deps(p)
- ofile.write('\tProjectSection(ProjectDependencies) = postProject\n')
- regen_guid = self.environment.coredata.regen_guid
- ofile.write('\t\t{%s} = {%s}\n' % (regen_guid, regen_guid))
- for dep in all_deps.keys():
- guid = self.environment.coredata.target_guids[dep]
- ofile.write('\t\t{%s} = {%s}\n' % (guid, guid))
- ofile.write('EndProjectSection\n')
+ with open(sln_filename, 'w') as ofile:
+ ofile.write('Microsoft Visual Studio Solution File, Format '
+ 'Version 11.00\n')
+ ofile.write('# Visual Studio ' + self.vs_version + '\n')
+ prj_templ = prj_line = 'Project("{%s}") = "%s", "%s", "{%s}"\n'
+ for p in projlist:
+ prj_line = prj_templ % (self.environment.coredata.guid,
+ p[0], p[1], p[2])
+ ofile.write(prj_line)
+ all_deps = self.determine_deps(p)
+ ofile.write('\tProjectSection(ProjectDependencies) = '
+ 'postProject\n')
+ regen_guid = self.environment.coredata.regen_guid
+ ofile.write('\t\t{%s} = {%s}\n' % (regen_guid, regen_guid))
+ for dep in all_deps.keys():
+ guid = self.environment.coredata.target_guids[dep]
+ ofile.write('\t\t{%s} = {%s}\n' % (guid, guid))
+ ofile.write('EndProjectSection\n')
+ ofile.write('EndProject\n')
+ test_line = prj_templ % (self.environment.coredata.guid,
+ 'RUN_TESTS', 'RUN_TESTS.vcxproj',
+ self.environment.coredata.test_guid)
+ ofile.write(test_line)
ofile.write('EndProject\n')
- test_line = prj_templ % (self.environment.coredata.guid,
- 'RUN_TESTS', 'RUN_TESTS.vcxproj', self.environment.coredata.test_guid)
- ofile.write(test_line)
- ofile.write('EndProject\n')
- regen_line = prj_templ % (self.environment.coredata.guid,
- 'REGEN', 'REGEN.vcxproj', self.environment.coredata.regen_guid)
- ofile.write(regen_line)
- ofile.write('EndProject\n')
- ofile.write('Global\n')
- ofile.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
- ofile.write('\t\t%s|%s = %s|%s\n' % (self.buildtype, self.platform, self.buildtype, self.platform))
- ofile.write('\tEndGlobalSection\n')
- ofile.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
- ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
- (self.environment.coredata.regen_guid, self.buildtype, self.platform,
- self.buildtype, self.platform))
- ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
- (self.environment.coredata.regen_guid, self.buildtype, self.platform,
- self.buildtype, self.platform))
- for p in projlist:
+ regen_line = prj_templ % (self.environment.coredata.guid,
+ 'REGEN', 'REGEN.vcxproj',
+ self.environment.coredata.regen_guid)
+ ofile.write(regen_line)
+ ofile.write('EndProject\n')
+ ofile.write('Global\n')
+ ofile.write('\tGlobalSection(SolutionConfigurationPlatforms) = '
+ 'preSolution\n')
+ ofile.write('\t\t%s|%s = %s|%s\n' %
+ (self.buildtype, self.platform, self.buildtype,
+ self.platform))
+ ofile.write('\tEndGlobalSection\n')
+ ofile.write('\tGlobalSection(ProjectConfigurationPlatforms) = '
+ 'postSolution\n')
ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
- (p[2], self.buildtype, self.platform,
- self.buildtype, self.platform))
- if not isinstance(self.build.targets[p[0]], build.RunTarget):
- ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
+ (self.environment.coredata.regen_guid, self.buildtype,
+ self.platform, self.buildtype, self.platform))
+ ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
+ (self.environment.coredata.regen_guid, self.buildtype,
+ self.platform, self.buildtype, self.platform))
+ for p in projlist:
+ ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
(p[2], self.buildtype, self.platform,
self.buildtype, self.platform))
- ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
- (self.environment.coredata.test_guid, self.buildtype, self.platform,
- self.buildtype, self.platform))
- ofile.write('\tEndGlobalSection\n')
- ofile.write('\tGlobalSection(SolutionProperties) = preSolution\n')
- ofile.write('\t\tHideSolutionNode = FALSE\n')
- ofile.write('\tEndGlobalSection\n')
- ofile.write('EndGlobal\n')
+ if not isinstance(self.build.targets[p[0]], build.RunTarget):
+ ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' %
+ (p[2], self.buildtype, self.platform,
+ self.buildtype, self.platform))
+ ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
+ (self.environment.coredata.test_guid, self.buildtype,
+ self.platform, self.buildtype, self.platform))
+ ofile.write('\tEndGlobalSection\n')
+ ofile.write('\tGlobalSection(SolutionProperties) = preSolution\n')
+ ofile.write('\t\tHideSolutionNode = FALSE\n')
+ ofile.write('\tEndGlobalSection\n')
+ ofile.write('EndGlobal\n')
def generate_projects(self):
projlist = []
@@ -862,12 +875,15 @@ class Vs2010Backend(backends.Backend):
tree.write(ofname, encoding='utf-8', xml_declaration=True)
# ElementTree can not do prettyprinting so do it manually
doc = xml.dom.minidom.parse(ofname)
- open(ofname, 'w').write(doc.toprettyxml())
+ with open(ofname, 'w') as of:
+ of.write(doc.toprettyxml())
# World of horror! Python insists on not quoting quotes and
# fixing the escaped &quot; into &amp;quot; whereas MSVS
# requires quoted but not fixed elements. Enter horrible hack.
- txt = open(ofname, 'r').read()
- open(ofname, 'w').write(txt.replace('&amp;quot;', '&quot;'))
+ with open(ofname, 'r') as of:
+ txt = of.read()
+ with open(ofname, 'w') as of:
+ of.write(txt.replace('&amp;quot;', '&quot;'))
def gen_regenproj(self, project_name, ofname):
root = ET.Element('Project', {'DefaultTargets': 'Build',
diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py
index e64866d..b157741 100644
--- a/mesonbuild/backend/xcodebackend.py
+++ b/mesonbuild/backend/xcodebackend.py
@@ -82,26 +82,22 @@ class XCodeBackend(backends.Backend):
self.proj_dir = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.xcodeproj')
os.makedirs(self.proj_dir, exist_ok=True)
self.proj_file = os.path.join(self.proj_dir, 'project.pbxproj')
- self.ofile = open(self.proj_file, 'w')
- self.generate_prefix()
- self.generate_pbx_aggregate_target()
- self.generate_pbx_build_file()
- self.generate_pbx_build_style()
- self.generate_pbx_container_item_proxy()
- self.generate_pbx_file_reference()
- self.generate_pbx_group()
- self.generate_pbx_native_target()
- self.generate_pbx_project()
- self.generate_pbx_shell_build_phase(test_data)
- self.generate_pbx_sources_build_phase()
- self.generate_pbx_target_dependency()
- self.generate_xc_build_configuration()
- self.generate_xc_configurationList()
- self.generate_suffix()
-
- # for some reason, the entire file was not being flushed to the disk.
- # closing it explicitly forces a flush and fixes the issue
- self.ofile.close()
+ with open(self.proj_file, 'w') as self.ofile:
+ self.generate_prefix()
+ self.generate_pbx_aggregate_target()
+ self.generate_pbx_build_file()
+ self.generate_pbx_build_style()
+ self.generate_pbx_container_item_proxy()
+ self.generate_pbx_file_reference()
+ self.generate_pbx_group()
+ self.generate_pbx_native_target()
+ self.generate_pbx_project()
+ self.generate_pbx_shell_build_phase(test_data)
+ self.generate_pbx_sources_build_phase()
+ self.generate_pbx_target_dependency()
+ self.generate_xc_build_configuration()
+ self.generate_xc_configurationList()
+ self.generate_suffix()
def get_xcodetype(self, fname):
return self.xcodetypemap[fname.split('.')[-1]]
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 6dd2bde..f95922e 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -17,7 +17,7 @@ from . import environment
from . import dependencies
from . import mlog
import copy, os, re
-from .mesonlib import File, flatten, MesonException
+from .mesonlib import File, flatten, MesonException, stringlistify
from .environment import for_windows, for_darwin
known_basic_kwargs = {'install' : True,
@@ -27,6 +27,7 @@ known_basic_kwargs = {'install' : True,
'cpp_args' : True,
'cs_args' : True,
'vala_args' : True,
+ 'd_args' : True,
'link_args' : True,
'link_depends': True,
'link_with' : True,
@@ -254,11 +255,9 @@ class BuildTarget():
for s in objects:
if hasattr(s, 'held_object'):
s = s.held_object
- if isinstance(s, str):
+ if isinstance(s, (str, ExtractedObjects)):
self.objects.append(s)
- elif isinstance(s, ExtractedObjects):
- self.objects.append(s)
- elif isinstance(s, GeneratedList) or isinstance(s, CustomTarget):
+ elif isinstance(s, (GeneratedList, CustomTarget)):
msg = 'Generated files are not allowed in the \'objects\' kwarg ' + \
'for target {!r}.\nIt is meant only for '.format(self.name) + \
'pre-built object files that are shipped with the\nsource ' + \
@@ -280,7 +279,7 @@ class BuildTarget():
if not s in added_sources:
self.sources.append(s)
added_sources[s] = True
- elif isinstance(s, GeneratedList) or isinstance(s, CustomTarget):
+ elif isinstance(s, (GeneratedList, CustomTarget)):
self.generated.append(s)
else:
msg = 'Bad source of type {!r} in target {!r}.'.format(type(s).__name__, self.name)
@@ -387,6 +386,8 @@ class BuildTarget():
if not isinstance(valalist, list):
valalist = [valalist]
self.add_compiler_args('vala', valalist)
+ dlist = stringlistify(kwargs.get('d_args', []))
+ self.add_compiler_args('d', dlist)
self.link_args = kwargs.get('link_args', [])
if not isinstance(self.link_args, list):
self.link_args = [self.link_args]
@@ -543,7 +544,14 @@ class BuildTarget():
self.external_deps.append(dep)
self.process_sourcelist(dep.get_sources())
else:
- raise InvalidArguments('Argument is not an external dependency')
+ # This is a bit of a hack. We do not want Build to know anything
+ # about the interpreter so we can't import it and use isinstance.
+ # This should be reliable enough.
+ if hasattr(dep, 'subproject'):
+ raise InvalidArguments('''Tried to use subproject object as a dependency.
+You probably wanted to use a dependency declared in it instead. Access it
+by calling get_variable() on the subproject object.''')
+ raise InvalidArguments('Argument is not an external dependency.')
def get_external_deps(self):
return self.external_deps
@@ -554,8 +562,7 @@ class BuildTarget():
for t in target:
if hasattr(t, 'held_object'):
t = t.held_object
- if not isinstance(t, StaticLibrary) and \
- not isinstance(t, SharedLibrary):
+ if not isinstance(t, (StaticLibrary, SharedLibrary)):
raise InvalidArguments('Link target is not library.')
if self.is_cross != t.is_cross:
raise InvalidArguments('Tried to mix cross built and native libraries in target %s.' % self.name)
@@ -620,9 +627,10 @@ class Generator():
exe = args[0]
if hasattr(exe, 'held_object'):
exe = exe.held_object
- if not isinstance(exe, Executable) and not isinstance(exe, dependencies.ExternalProgram):
+ if not isinstance(exe, (Executable, dependencies.ExternalProgram)):
raise InvalidArguments('First generator argument must be an executable.')
self.exe = exe
+ self.depfile = None
self.process_kwargs(kwargs)
def __repr__(self):
@@ -644,7 +652,6 @@ class Generator():
if not isinstance(a, str):
raise InvalidArguments('A non-string object in "arguments" keyword argument.')
self.arglist = args
-
if 'output' not in kwargs:
raise InvalidArguments('Generator must have "output" keyword argument.')
outputs = kwargs['output']
@@ -662,12 +669,26 @@ class Generator():
if '@OUTPUT@' in o:
raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.')
self.outputs = outputs
+ if 'depfile' in kwargs:
+ depfile = kwargs['depfile']
+ if not isinstance(depfile, str):
+ raise InvalidArguments('Depfile must be a string.')
+ if os.path.split(depfile)[1] != depfile:
+ raise InvalidArguments('Depfile must be a plain filename without a subdirectory.')
+ self.depfile = depfile
def get_base_outnames(self, inname):
plainname = os.path.split(inname)[1]
basename = plainname.split('.')[0]
return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs]
+ def get_dep_outname(self, inname):
+ if self.depfile is None:
+ raise InvalidArguments('Tried to get dep name for rule that does not have dependency file defined.')
+ plainname = os.path.split(inname)[1]
+ basename = plainname.split('.')[0]
+ return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname)
+
def get_arglist(self):
return self.arglist
@@ -844,12 +865,10 @@ class SharedLibrary(BuildTarget):
elif for_darwin(is_cross, env):
prefix = 'lib'
suffix = 'dylib'
- if self.soversion:
- # libfoo.X.dylib
- self.filename_tpl = '{0.prefix}{0.name}.{0.soversion}.{0.suffix}'
- else:
- # libfoo.dylib
- self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
+ # libfoo.dylib
+ self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
+ # On OS X, the filename should never have the soversion
+ # See: https://github.com/mesonbuild/meson/pull/680
else:
prefix = 'lib'
suffix = 'so'
@@ -913,6 +932,8 @@ class SharedLibrary(BuildTarget):
self.vs_module_defs = File.from_absolute_file(path)
else:
self.vs_module_defs = File.from_source_file(environment.source_dir, self.subdir, path)
+ # link_depends can be an absolute path or relative to self.subdir
+ self.link_depends.append(path)
def check_unknown_kwargs(self, kwargs):
self.check_unknown_kwargs_int(kwargs, known_shlib_kwargs)
@@ -961,11 +982,13 @@ class CustomTarget:
known_kwargs = {'input' : True,
'output' : True,
'command' : True,
+ 'capture' : False,
'install' : True,
'install_dir' : True,
'build_always' : True,
'depends' : True,
'depend_files' : True,
+ 'depfile' : True,
}
def __init__(self, name, subdir, kwargs):
@@ -974,6 +997,7 @@ class CustomTarget:
self.dependencies = []
self.extra_depends = []
self.depend_files = [] # Files that this target depends on but are not on the command line.
+ self.depfile = None
self.process_kwargs(kwargs)
self.extra_files = []
self.install_rpath = ''
@@ -998,7 +1022,7 @@ class CustomTarget:
for c in self.sources:
if hasattr(c, 'held_object'):
c = c.held_object
- if isinstance(c, BuildTarget) or isinstance(c, CustomTarget) or isinstance(c, GeneratedList):
+ if isinstance(c, (BuildTarget, CustomTarget, GeneratedList)):
deps.append(c)
return deps
@@ -1016,8 +1040,19 @@ class CustomTarget:
raise InvalidArguments('Output argument not a string.')
if '/' in i:
raise InvalidArguments('Output must not contain a path segment.')
+ self.capture = kwargs.get('capture', False)
+ if self.capture and len(self.output) != 1:
+ raise InvalidArguments(
+ 'Capturing can only output to a single file.')
if 'command' not in kwargs:
raise InvalidArguments('Missing keyword argument "command".')
+ if 'depfile' in kwargs:
+ depfile = kwargs['depfile']
+ if not isinstance(depfile, str):
+ raise InvalidArguments('Depfile must be a string.')
+ if os.path.split(depfile)[1] != depfile:
+ raise InvalidArguments('Depfile must be a plain filename without a subdirectory.')
+ self.depfile = depfile
cmd = kwargs['command']
if not(isinstance(cmd, list)):
cmd = [cmd]
@@ -1025,13 +1060,13 @@ class CustomTarget:
for i, c in enumerate(cmd):
if hasattr(c, 'held_object'):
c = c.held_object
- if isinstance(c, str) or isinstance(c, File):
+ if isinstance(c, (str, File)):
final_cmd.append(c)
elif isinstance(c, dependencies.ExternalProgram):
if not c.found():
raise InvalidArguments('Tried to use not found external program in a build rule.')
final_cmd += c.get_command()
- elif isinstance(c, BuildTarget) or isinstance(c, CustomTarget):
+ elif isinstance(c, (BuildTarget, CustomTarget)):
self.dependencies.append(c)
final_cmd.append(c)
elif isinstance(c, list):
@@ -1044,6 +1079,10 @@ class CustomTarget:
else:
raise InvalidArguments('Argument %s in "command" is invalid.' % i)
self.command = final_cmd
+ if self.capture:
+ for c in self.command:
+ if isinstance(c, str) and '@OUTPUT@' in c:
+ raise InvalidArguments('@OUTPUT@ is not allowed when capturing output.')
if 'install' in kwargs:
self.install = kwargs['install']
if not isinstance(self.install, bool):
@@ -1065,7 +1104,7 @@ class CustomTarget:
for ed in extra_deps:
while hasattr(ed, 'held_object'):
ed = ed.held_object
- if not isinstance(ed, CustomTarget) and not isinstance(ed, BuildTarget):
+ if not isinstance(ed, (CustomTarget, BuildTarget)):
raise InvalidArguments('Can only depend on toplevel targets.')
self.extra_depends.append(ed)
depend_files = kwargs.get('depend_files', [])
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index 73f2416..d1f3896 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -23,7 +23,7 @@ from . import coredata
about. To support a new compiler, add its information below.
Also add corresponding autodetection code in environment.py."""
-header_suffixes = ['h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi']
+header_suffixes = ['h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di']
cpp_suffixes = ['cc', 'cpp', 'cxx', 'h', 'hh', 'hpp', 'ipp', 'hxx', 'c++']
c_suffixes = ['c']
clike_suffixes = c_suffixes + cpp_suffixes
@@ -108,6 +108,27 @@ rust_buildtype_args = {'plain' : [],
'minsize' : [],
}
+d_gdc_buildtype_args = {'plain' : [],
+ 'debug' : ['-g', '-O0'],
+ 'debugoptimized' : ['-g', '-O'],
+ 'release' : ['-O3', '-frelease'],
+ 'minsize' : [],
+ }
+
+d_ldc_buildtype_args = {'plain' : [],
+ 'debug' : ['-g', '-O0'],
+ 'debugoptimized' : ['-g', '-O'],
+ 'release' : ['-O3', '-release'],
+ 'minsize' : [],
+ }
+
+d_dmd_buildtype_args = {'plain' : [],
+ 'debug' : ['-g'],
+ 'debugoptimized' : ['-g', '-O'],
+ 'release' : ['-O', '-release'],
+ 'minsize' : [],
+ }
+
mono_buildtype_args = {'plain' : [],
'debug' : ['-debug'],
'debugoptimized': ['-debug', '-optimize+'],
@@ -525,9 +546,8 @@ class CCompiler(Compiler):
binname += '.exe'
# Write binary check source
binary_name = os.path.join(work_dir, binname)
- ofile = open(source_name, 'w')
- ofile.write(code)
- ofile.close()
+ with open(source_name, 'w') as ofile:
+ ofile.write(code)
# 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, cwd=work_dir)
@@ -604,9 +624,8 @@ int main () {{ {1}; }}'''
suflen = len(self.default_suffix)
(fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix)
os.close(fd)
- ofile = open(srcname, 'w')
- ofile.write(code)
- ofile.close()
+ with open(srcname, 'w') as ofile:
+ ofile.write(code)
# Convert flags to the native type of the selected compiler
args = self.unix_link_flags_to_native(extra_args)
# Read c_args/cpp_args/etc from the cross-info file (if needed)
@@ -634,9 +653,8 @@ int main () {{ {1}; }}'''
os.close(fd)
(fd, dstname) = tempfile.mkstemp()
os.close(fd)
- ofile = open(srcname, 'w')
- ofile.write(code)
- ofile.close()
+ with open(srcname, 'w') as ofile:
+ ofile.write(code)
# Convert flags to the native type of the selected compiler
args = self.unix_link_flags_to_native(extra_args)
# Select a CRT if needed since we're linking
@@ -659,9 +677,8 @@ int main () {{ {1}; }}'''
raise CrossNoRunException('Can not run test applications in this cross environment.')
(fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix)
os.close(fd)
- ofile = open(srcname, 'w')
- ofile.write(code)
- ofile.close()
+ with open(srcname, 'w') as ofile:
+ ofile.write(code)
# Convert flags to the native type of the selected compiler
args = self.unix_link_flags_to_native(extra_args)
# Select a CRT if needed since we're linking
@@ -889,16 +906,21 @@ int main(int argc, char **argv) {
# directly try to link via main().
return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), env, args)
- def has_member(self, typename, membername, prefix, env, extra_args=None):
+ def has_members(self, typename, membernames, prefix, env, extra_args=None):
if extra_args is None:
extra_args = []
- templ = '''%s
-void bar() {
- %s foo;
- foo.%s;
-};
+ templ = '''{0}
+void bar() {{
+ {1} {2};
+ {3}
+}};
'''
- return self.compiles(templ % (prefix, typename, membername), env, extra_args)
+ # Create code that accesses all members
+ members = ''
+ for m in membernames:
+ members += 'foo.{};\n'.format(m)
+ code = templ.format(prefix, typename, 'foo', members)
+ return self.compiles(code, env, extra_args)
def has_type(self, typename, prefix, env, extra_args):
templ = '''%s
@@ -979,9 +1001,9 @@ class ObjCCompiler(CCompiler):
extra_flags = self.get_cross_extra_flags(environment, compile=True, link=False)
if self.is_cross:
extra_flags += self.get_compile_only_args()
- ofile = open(source_name, 'w')
- ofile.write('#import<stdio.h>\nint main(int argc, char **argv) { return 0; }\n')
- ofile.close()
+ with open(source_name, 'w') as ofile:
+ ofile.write('#import<stdio.h>\n'
+ 'int main(int argc, char **argv) { return 0; }\n')
pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
pc.wait()
if pc.returncode != 0:
@@ -1013,9 +1035,10 @@ class ObjCPPCompiler(CPPCompiler):
extra_flags = self.get_cross_extra_flags(environment, compile=True, link=False)
if self.is_cross:
extra_flags += self.get_compile_only_args()
- ofile = open(source_name, 'w')
- ofile.write('#import<stdio.h>\nclass MyClass;int main(int argc, char **argv) { return 0; }\n')
- ofile.close()
+ with open(source_name, 'w') as ofile:
+ ofile.write('#import<stdio.h>\n'
+ 'class MyClass;'
+ 'int main(int argc, char **argv) { return 0; }\n')
pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
pc.wait()
if pc.returncode != 0:
@@ -1115,13 +1138,12 @@ class MonoCompiler(Compiler):
src = 'sanity.cs'
obj = 'sanity.exe'
source_name = os.path.join(work_dir, src)
- ofile = open(source_name, 'w')
- ofile.write('''public class Sanity {
+ with open(source_name, 'w') as ofile:
+ ofile.write('''public class Sanity {
static public void Main () {
}
}
''')
- ofile.close()
pc = subprocess.Popen(self.exelist + [src], cwd=work_dir)
pc.wait()
if pc.returncode != 0:
@@ -1227,14 +1249,13 @@ class JavaCompiler(Compiler):
src = 'SanityCheck.java'
obj = 'SanityCheck'
source_name = os.path.join(work_dir, src)
- ofile = open(source_name, 'w')
- ofile.write('''class SanityCheck {
+ with open(source_name, 'w') as ofile:
+ ofile.write('''class SanityCheck {
public static void main(String[] args) {
int i;
}
}
''')
- ofile.close()
pc = subprocess.Popen(self.exelist + [src], cwd=work_dir)
pc.wait()
if pc.returncode != 0:
@@ -1274,11 +1295,10 @@ class ValaCompiler(Compiler):
def sanity_check(self, work_dir, environment):
src = 'valatest.vala'
source_name = os.path.join(work_dir, src)
- ofile = open(source_name, 'w')
- ofile.write('''class SanityCheck : Object {
+ with open(source_name, 'w') as ofile:
+ ofile.write('''class SanityCheck : Object {
}
''')
- ofile.close()
extra_flags = self.get_cross_extra_flags(environment, compile=True, link=False)
pc = subprocess.Popen(self.exelist + extra_flags + ['-C', '-c', src], cwd=work_dir)
pc.wait()
@@ -1318,11 +1338,10 @@ class RustCompiler(Compiler):
def sanity_check(self, work_dir, environment):
source_name = os.path.join(work_dir, 'sanity.rs')
output_name = os.path.join(work_dir, 'rusttest')
- ofile = open(source_name, 'w')
- ofile.write('''fn main() {
+ with open(source_name, 'w') as ofile:
+ ofile.write('''fn main() {
}
''')
- ofile.close()
pc = subprocess.Popen(self.exelist + ['-o', output_name, source_name], cwd=work_dir)
pc.wait()
if pc.returncode != 0:
@@ -1417,10 +1436,9 @@ class SwiftCompiler(Compiler):
src = 'swifttest.swift'
source_name = os.path.join(work_dir, src)
output_name = os.path.join(work_dir, 'swifttest')
- ofile = open(source_name, 'w')
- ofile.write('''1 + 2
+ with open(source_name, 'w') as ofile:
+ ofile.write('''1 + 2
''')
- ofile.close()
extra_flags = self.get_cross_extra_flags(environment, compile=True, link=True)
pc = subprocess.Popen(self.exelist + extra_flags + ['-emit-executable', '-o', output_name, src], cwd=work_dir)
pc.wait()
@@ -1433,6 +1451,268 @@ class SwiftCompiler(Compiler):
suffix = filename.split('.')[-1]
return suffix in ('swift')
+class DCompiler(Compiler):
+ def __init__(self, exelist, version, is_cross):
+ super().__init__(exelist, version)
+ self.id = 'unknown'
+ self.language = 'd'
+ self.is_cross = is_cross
+
+ def sanity_check(self, work_dir, environment):
+ source_name = os.path.join(work_dir, 'sanity.d')
+ output_name = os.path.join(work_dir, 'dtest')
+ with open(source_name, 'w') as ofile:
+ ofile.write('''void main() {
+}
+''')
+ pc = subprocess.Popen(self.exelist + self.get_output_args(output_name) + [source_name], cwd=work_dir)
+ pc.wait()
+ if pc.returncode != 0:
+ raise EnvironmentException('D compiler %s can not compile programs.' % self.name_string())
+ if subprocess.call(output_name) != 0:
+ raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string())
+
+ def needs_static_linker(self):
+ return True
+
+ def name_string(self):
+ return ' '.join(self.exelist)
+
+ def get_exelist(self):
+ return self.exelist
+
+ def get_id(self):
+ return self.id
+
+ def get_language(self):
+ return self.language
+
+ def can_compile(self, fname):
+ suffix = fname.split('.')[-1]
+ return suffix in ('d', 'di')
+
+ def get_linker_exelist(self):
+ return self.exelist[:]
+
+ def depfile_for_object(self, objfile):
+ return objfile + '.' + self.get_depfile_suffix()
+
+ def get_depfile_suffix(self):
+ return 'dep'
+
+ def get_pic_args(self):
+ return ['-fPIC']
+
+ def get_std_shared_lib_link_args(self):
+ return ['-shared']
+
+ def get_soname_args(self, shlib_name, path, soversion):
+ return []
+
+ def get_unittest_args(self):
+ return ['-unittest']
+
+ def get_buildtype_linker_args(self, buildtype):
+ return []
+
+ def get_std_exe_link_args(self):
+ return []
+
+ def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
+ # This method is to be used by LDC and DMD.
+ # GDC can deal with the verbatim flags.
+ if len(rpath_paths) == 0 and len(install_rpath) == 0:
+ return []
+ paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
+ if len(paths) < len(install_rpath):
+ padding = 'X'*(len(install_rpath) - len(paths))
+ if len(paths) == 0:
+ paths = padding
+ else:
+ paths = paths + ':' + padding
+ return ['-L-rpath={}'.format(paths)]
+
+ def translate_args_to_nongnu(self, args):
+ dcargs = []
+ # Translate common arguments to flags the LDC/DMD compilers
+ # can understand.
+ # The flags might have been added by pkg-config files,
+ # and are therefore out of the user's control.
+ for arg in args:
+ if arg == '-pthread':
+ continue
+ if arg.startswith('-Wl,'):
+ linkargs = arg[arg.index(',')+1:].split(',')
+ for la in linkargs:
+ dcargs.append('-L' + la.strip())
+ continue
+ elif arg.startswith('-l'):
+ # translate library link flag
+ dcargs.append('-L' + arg)
+ continue
+ dcargs.append(arg)
+
+ return dcargs
+
+class GnuDCompiler(DCompiler):
+ def __init__(self, exelist, version, is_cross):
+ DCompiler.__init__(self, exelist, version, is_cross)
+ self.id = 'gcc'
+ self.warn_args = {'1': ['-Wall', '-Wdeprecated'],
+ '2': ['-Wall', '-Wextra', '-Wdeprecated'],
+ '3': ['-Wall', '-Wextra', '-Wdeprecated', '-Wpedantic']}
+ self.base_options = ['b_colorout', 'b_sanitize']
+
+ def get_colorout_args(self, colortype):
+ if mesonlib.version_compare(self.version, '>=4.9.0'):
+ return gnu_color_args[colortype][:]
+ return []
+
+ def get_dependency_gen_args(self, outtarget, outfile):
+ # FIXME: Passing -fmake-deps results in a file-not-found message.
+ # Investigate why.
+ return []
+
+ def get_output_args(self, target):
+ return ['-o', target]
+
+ def get_compile_only_args(self):
+ return ['-c']
+
+ def get_linker_output_args(self, target):
+ return ['-o', target]
+
+ def get_include_args(self, path, is_system):
+ return ['-I' + path]
+
+ def get_warn_args(self, level):
+ return self.warn_args[level]
+
+ def get_werror_args(self):
+ return ['-Werror']
+
+ def get_linker_search_args(self, dirname):
+ return ['-L'+dirname]
+
+ def get_buildtype_args(self, buildtype):
+ return d_gdc_buildtype_args[buildtype]
+
+ def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
+ return build_unix_rpath_args(build_dir, rpath_paths, install_rpath)
+
+ def get_unittest_args(self):
+ return ['-funittest']
+
+class LLVMDCompiler(DCompiler):
+ def __init__(self, exelist, version, is_cross):
+ DCompiler.__init__(self, exelist, version, is_cross)
+ self.id = 'llvm'
+ self.base_options = ['b_coverage', 'b_colorout']
+
+ def get_colorout_args(self, colortype):
+ if colortype == 'always':
+ return ['-enable-color']
+ return []
+
+ def get_dependency_gen_args(self, outtarget, outfile):
+ # LDC using the -deps flag returns a non-Makefile dependency-info file, which
+ # the backends can not use. So we disable this feature for now.
+ return []
+
+ def get_output_args(self, target):
+ return ['-of', target]
+
+ def get_compile_only_args(self):
+ return ['-c']
+
+ def get_linker_output_args(self, target):
+ return ['-of', target]
+
+ def get_include_args(self, path, is_system):
+ return ['-I' + path]
+
+ def get_warn_args(self, level):
+ if level == '2':
+ return ['-wi']
+ else:
+ return ['-w']
+
+ def get_coverage_args(self):
+ return ['-cov']
+
+ def get_buildtype_args(self, buildtype):
+ return d_ldc_buildtype_args[buildtype]
+
+ def get_pic_args(self):
+ return ['-relocation-model=pic']
+
+ def get_linker_search_args(self, dirname):
+ # -L is recognized as "add this to the search path" by the linker,
+ # while the compiler recognizes it as "pass to linker". So, the first
+ # -L is for the compiler, telling it to pass the second -L to the linker.
+ return ['-L-L'+dirname]
+
+ def unix_link_flags_to_native(self, args):
+ return self.translate_args_to_nongnu(args)
+
+ def unix_compile_flags_to_native(self, args):
+ return self.translate_args_to_nongnu(args)
+
+class DmdDCompiler(DCompiler):
+ def __init__(self, exelist, version, is_cross):
+ DCompiler.__init__(self, exelist, version, is_cross)
+ self.id = 'dmd'
+ self.base_options = ['b_coverage', 'b_colorout']
+
+ def get_colorout_args(self, colortype):
+ if colortype == 'always':
+ return ['-color=on']
+ return []
+
+ def get_dependency_gen_args(self, outtarget, outfile):
+ # LDC using the -deps flag returns a non-Makefile dependency-info file, which
+ # the backends can not use. So we disable this feature for now.
+ return []
+
+ def get_output_args(self, target):
+ return ['-of' + target]
+
+ def get_werror_args(self):
+ return ['-w']
+
+ def get_compile_only_args(self):
+ return ['-c']
+
+ def get_linker_output_args(self, target):
+ return ['-of' + target]
+
+ def get_include_args(self, path, is_system):
+ return ['-I' + path]
+
+ def get_warn_args(self, level):
+ return []
+
+ def get_coverage_args(self):
+ return ['-cov']
+
+ def get_linker_search_args(self, dirname):
+ # -L is recognized as "add this to the search path" by the linker,
+ # while the compiler recognizes it as "pass to linker". So, the first
+ # -L is for the compiler, telling it to pass the second -L to the linker.
+ return ['-L-L'+dirname]
+
+ def get_buildtype_args(self, buildtype):
+ return d_dmd_buildtype_args[buildtype]
+
+ def get_std_shared_lib_link_args(self):
+ return ['-shared', '-defaultlib=libphobos2.so']
+
+ def unix_link_flags_to_native(self, args):
+ return self.translate_args_to_nongnu(args)
+
+ def unix_compile_flags_to_native(self, args):
+ return self.translate_args_to_nongnu(args)
+
class VisualStudioCCompiler(CCompiler):
std_warn_args = ['/W3']
std_opt_args= ['/O2']
@@ -1586,9 +1866,8 @@ class VisualStudioCCompiler(CCompiler):
code = 'int i;\n'
(fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix)
os.close(fd)
- ofile = open(srcname, 'w')
- ofile.write(code)
- ofile.close()
+ with open(srcname, 'w') as ofile:
+ ofile.write(code)
# Read c_args/cpp_args/etc from the cross-info file (if needed)
extra_args = self.get_cross_extra_flags(env, compile=True, link=False)
extra_args += self.get_compile_only_args()
@@ -1860,6 +2139,9 @@ class ClangCCompiler(CCompiler):
def get_option_link_args(self, options):
return []
+ def has_argument(self, arg, env):
+ return super().has_argument(['-Werror=unknown-warning-option', arg], env)
+
class GnuCPPCompiler(CPPCompiler):
# may need to separate the latter to extra_debug_args or something
std_debug_args = ['-g']
@@ -1882,6 +2164,11 @@ class GnuCPPCompiler(CPPCompiler):
return gnu_color_args[colortype][:]
return []
+ def get_pic_args(self):
+ if self.gcc_type == GCC_MINGW:
+ return [] # On Window gcc defaults to fpic being always on.
+ return ['-fPIC']
+
def get_always_args(self):
return ['-pipe']
@@ -1969,6 +2256,9 @@ class ClangCPPCompiler(CPPCompiler):
def get_option_link_args(self, options):
return []
+ def has_argument(self, arg, env):
+ return super().has_argument(['-Werror=unknown-warning-option', arg], env)
+
class FortranCompiler(Compiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None):
super().__init__(exelist, version)
@@ -2005,12 +2295,11 @@ class FortranCompiler(Compiler):
def sanity_check(self, work_dir, environment):
source_name = os.path.join(work_dir, 'sanitycheckf.f90')
binary_name = os.path.join(work_dir, 'sanitycheckf')
- ofile = open(source_name, 'w')
- ofile.write('''program prog
+ with open(source_name, 'w') as ofile:
+ ofile.write('''program prog
print *, "Fortran compilation is working."
end program prog
''')
- ofile.close()
extra_flags = self.get_cross_extra_flags(environment, compile=True, link=True)
pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
pc.wait()
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 7c8e458..7a6eada 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -15,7 +15,7 @@
import pickle, os, uuid
from .mesonlib import MesonException, default_libdir, default_libexecdir, default_prefix
-version = '0.34.0.dev1'
+version = '0.35.0.dev1'
backendlist = ['ninja', 'vs2010', 'vs2015', 'xcode']
class UserOption:
@@ -154,7 +154,8 @@ class CoreData():
raise RuntimeError('Tried to set unknown builtin option %s.' % optname)
def load(filename):
- obj = pickle.load(open(filename, 'rb'))
+ with open(filename, 'rb') as f:
+ obj = pickle.load(f)
if not isinstance(obj, CoreData):
raise RuntimeError('Core data file is corrupted.')
if obj.version != version:
@@ -165,7 +166,8 @@ def load(filename):
def save(obj, filename):
if obj.version != version:
raise RuntimeError('Fatal version mismatch corruption.')
- pickle.dump(obj, open(filename, 'wb'))
+ with open(filename, 'wb') as f:
+ pickle.dump(obj, f)
def get_builtin_options():
return list(builtin_options.keys())
@@ -211,6 +213,11 @@ builtin_options = {
'datadir' : [ UserStringOption, 'Data file directory.', 'share' ],
'mandir' : [ UserStringOption, 'Manual page directory.', 'share/man' ],
'localedir' : [ UserStringOption, 'Locale data directory.', 'share/locale' ],
+ # Sysconfdir is a bit special. It defaults to ${prefix}/etc but nobody
+ # uses that. Instead they always set it manually to /etc. This default
+ # value is thus pointless and not really used but we set it to this
+ # for consistency with other systems.
+ 'sysconfdir' : [ UserStringOption, 'Sysconf data directory.', 'etc' ],
'werror' : [ UserBooleanOption, 'Treat warnings as errors.', False ],
'warning_level' : [ UserComboOption, 'Compiler warning level to use.', [ '1', '2', '3' ], '1'],
'layout' : [ UserComboOption, 'Build directory layout.', ['mirror', 'flat' ], 'mirror' ],
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index b4f825b..106273c 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -154,7 +154,7 @@ class PkgConfigDependency(Dependency):
out = p.communicate()[0]
if p.returncode != 0:
raise DependencyException('Could not generate cargs for %s:\n\n%s' % \
- (name, out.decode(errors='ignore')))
+ (self.name, out.decode(errors='ignore')))
self.cargs = out.decode().split()
def _set_libs(self):
@@ -166,7 +166,7 @@ class PkgConfigDependency(Dependency):
out = p.communicate()[0]
if p.returncode != 0:
raise DependencyException('Could not generate libs for %s:\n\n%s' % \
- (name, out.decode(errors='ignore')))
+ (self.name, out.decode(errors='ignore')))
self.libs = []
for lib in out.decode().split():
if lib.endswith(".la"):
@@ -228,10 +228,11 @@ class PkgConfigDependency(Dependency):
return self.is_found
def extract_field(self, la_file, fieldname):
- for line in open(la_file):
- arr = line.strip().split('=')
- if arr[0] == fieldname:
- return arr[1][1:-1]
+ with open(la_file) as f:
+ for line in f:
+ arr = line.strip().split('=')
+ if arr[0] == fieldname:
+ return arr[1][1:-1]
return None
def extract_dlname_field(self, la_file):
@@ -374,7 +375,8 @@ class ExternalProgram():
shebang and manually parse it to figure out the interpreter to use
"""
try:
- first_line = open(script).readline().strip()
+ with open(script) as f:
+ first_line = f.readline().strip()
if first_line.startswith('#!'):
commands = first_line[2:].split('#')[0].strip().split()
if mesonlib.is_windows():
@@ -552,12 +554,13 @@ class BoostDependency(Dependency):
except FileNotFoundError:
self.version = None
return
- for line in ifile:
- if line.startswith("#define") and 'BOOST_LIB_VERSION' in line:
- ver = line.split()[-1]
- ver = ver[1:-1]
- self.version = ver.replace('_', '.')
- return
+ with ifile:
+ for line in ifile:
+ if line.startswith("#define") and 'BOOST_LIB_VERSION' in line:
+ ver = line.split()[-1]
+ ver = ver[1:-1]
+ self.version = ver.replace('_', '.')
+ return
self.version = None
def detect_src_modules(self):
@@ -1048,6 +1051,17 @@ class SDL2Dependency(Dependency):
self.is_found = False
self.cargs = []
self.linkargs = []
+ try:
+ pcdep = PkgConfigDependency('sdl2', environment, kwargs)
+ if pcdep.found():
+ self.is_found = True
+ self.cargs = pcdep.get_compile_args()
+ self.linkargs = pcdep.get_link_args()
+ self.version = pcdep.get_version()
+ return
+ except Exception as e:
+ mlog.debug('SDL 2 not found via pkgconfig. Trying next, error was:', str(e))
+ pass
sdlconf = shutil.which('sdl2-config')
if sdlconf:
pc = subprocess.Popen(['sdl2-config', '--cflags'],
@@ -1064,16 +1078,7 @@ class SDL2Dependency(Dependency):
mlog.log('Dependency', mlog.bold('sdl2'), 'found:', mlog.green('YES'), '(%s)' % sdlconf)
self.version = '2' # FIXME
return
- try:
- pcdep = PkgConfigDependency('sdl2', kwargs)
- if pcdep.found():
- self.is_found = True
- self.cargs = pcdep.get_compile_args()
- self.linkargs = pcdep.get_link_args()
- self.version = pcdep.get_version()
- return
- except Exception:
- pass
+ mlog.debug('Could not find sdl2-config binary, trying next.')
if mesonlib.is_osx():
fwdep = ExtraFrameworkDependency('sdl2', kwargs.get('required', True))
if fwdep.found():
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 16af0d1..341e5e8 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -18,6 +18,7 @@ from . import mesonlib
from . import mlog
from .compilers import *
import configparser
+import shutil
build_filename = 'meson.build'
@@ -580,6 +581,48 @@ class Environment():
return RustCompiler(exelist, version)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
+ def detect_d_compiler(self):
+ exelist = None
+ is_cross = False
+ # Search for a D compiler.
+ # We prefer LDC over GDC unless overridden with the DC
+ # environment variable because LDC has a much more
+ # up to date language version at time (2016).
+ if 'DC' in os.environ:
+ exelist = os.environ['DC'].split()
+ elif self.is_cross_build() and want_cross:
+ exelist = [self.cross_info.config['binaries']['d']]
+ is_cross = True
+ elif shutil.which("ldc2"):
+ exelist = ['ldc2']
+ elif shutil.which("ldc"):
+ exelist = ['ldc']
+ elif shutil.which("gdc"):
+ exelist = ['gdc']
+ elif shutil.which("dmd"):
+ exelist = ['dmd']
+ else:
+ raise EnvironmentException('Could not find any supported D compiler.')
+
+ try:
+ p = subprocess.Popen(exelist + ['--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ except OSError:
+ raise EnvironmentException('Could not execute D compiler "%s"' % ' '.join(exelist))
+ (out, _) = p.communicate()
+ out = out.decode(errors='ignore')
+ vmatch = re.search(Environment.version_regex, out)
+ if vmatch:
+ version = vmatch.group(0)
+ else:
+ version = 'unknown version'
+ if 'LLVM D compiler' in out:
+ return LLVMDCompiler(exelist, version, is_cross)
+ elif 'gdc' in out:
+ return GnuDCompiler(exelist, version, is_cross)
+ elif 'Digital Mars' in out:
+ return DmdDCompiler(exelist, version, is_cross)
+ raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
+
def detect_swift_compiler(self):
exelist = ['swiftc']
try:
@@ -712,13 +755,14 @@ def get_args_from_envvars(lang, compiler_is_linker):
if val:
mlog.log('Appending {} from environment: {!r}'.format(var, val))
- if lang not in ('c', 'cpp', 'objc', 'objcpp', 'fortran'):
+ if lang not in ('c', 'cpp', 'objc', 'objcpp', 'fortran', 'd'):
return ([], [])
# Compile flags
cflags_mapping = {'c': 'CFLAGS', 'cpp': 'CXXFLAGS',
'objc': 'OBJCFLAGS', 'objcpp': 'OBJCXXFLAGS',
- 'fortran': 'FFLAGS'}
+ 'fortran': 'FFLAGS',
+ 'd': 'DFLAGS'}
compile_flags = os.environ.get(cflags_mapping[lang], '')
log_var(cflags_mapping[lang], compile_flags)
compile_flags = compile_flags.split()
@@ -755,7 +799,7 @@ class CrossBuildInfo():
raise mesonlib.MesonException('Cross file is missing "binaries".')
def ok_type(self, i):
- return isinstance(i, str) or isinstance(i, int) or isinstance(i, bool)
+ return isinstance(i, (str, int, bool))
def parse_datafile(self, filename):
config = configparser.ConfigParser()
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 8645b68..1ef4133 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -144,6 +144,7 @@ class RunProcess(InterpreterObject):
cwd = os.path.join(source_dir, subdir)
child_env = os.environ.copy()
child_env.update(env)
+ mlog.debug('Running command:', ' '.join(command_array))
try:
return subprocess.Popen(command_array, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=child_env, cwd=cwd)
@@ -454,7 +455,10 @@ class Man(InterpreterObject):
def validate_sources(self):
for s in self.sources:
- num = int(s.split('.')[-1])
+ try:
+ num = int(s.split('.')[-1])
+ except (IndexError, ValueError):
+ num = 0
if num < 1 or num > 8:
raise InvalidArguments('Man file must have a file extension of a number between 1 and 8')
@@ -564,7 +568,7 @@ class SubprojectHolder(InterpreterObject):
def __init__(self, subinterpreter):
super().__init__()
- self.subinterpreter = subinterpreter
+ self.held_object = subinterpreter
self.methods.update({'get_variable' : self.get_variable_method,
})
@@ -574,7 +578,7 @@ class SubprojectHolder(InterpreterObject):
varname = args[0]
if not isinstance(varname, str):
raise InterpreterException('Get_variable takes a string argument.')
- return self.subinterpreter.variables[varname]
+ return self.held_object.variables[varname]
class CompilerHolder(InterpreterObject):
def __init__(self, compiler, env):
@@ -590,6 +594,7 @@ class CompilerHolder(InterpreterObject):
'run' : self.run_method,
'has_function' : self.has_function_method,
'has_member' : self.has_member_method,
+ 'has_members' : self.has_members_method,
'has_type' : self.has_type_method,
'alignment' : self.alignment_method,
'version' : self.version_method,
@@ -597,6 +602,7 @@ class CompilerHolder(InterpreterObject):
'find_library': self.find_library_method,
'has_argument' : self.has_argument_method,
'first_supported_argument' : self.first_supported_argument_method,
+ 'unittest_args' : self.unittest_args_method,
})
def version_method(self, args, kwargs):
@@ -650,6 +656,12 @@ class CompilerHolder(InterpreterObject):
def get_id_method(self, args, kwargs):
return self.compiler.get_id()
+ def unittest_args_method(self, args, kwargs):
+ # At time, only D compilers have this feature.
+ if not hasattr(self.compiler, 'get_unittest_args'):
+ raise InterpreterException('This {} compiler has no unittest arguments.'.format(self.compiler.language))
+ return self.compiler.get_unittest_args()
+
def has_member_method(self, args, kwargs):
if len(args) != 2:
raise InterpreterException('Has_member takes exactly two arguments.')
@@ -658,9 +670,10 @@ class CompilerHolder(InterpreterObject):
membername = args[1]
prefix = kwargs.get('prefix', '')
if not isinstance(prefix, str):
- raise InterpreterException('Prefix argument of has_function must be a string.')
+ raise InterpreterException('Prefix argument of has_member must be a string.')
extra_args = self.determine_args(kwargs)
- had = self.compiler.has_member(typename, membername, prefix, self.environment, extra_args)
+ had = self.compiler.has_members(typename, [membername], prefix,
+ self.environment, extra_args)
if had:
hadtxt = mlog.green('YES')
else:
@@ -669,6 +682,25 @@ class CompilerHolder(InterpreterObject):
'" has member "', mlog.bold(membername), '": ', hadtxt, sep='')
return had
+ def has_members_method(self, args, kwargs):
+ check_stringlist(args)
+ typename = args[0]
+ membernames = args[1:]
+ prefix = kwargs.get('prefix', '')
+ if not isinstance(prefix, str):
+ raise InterpreterException('Prefix argument of has_members must be a string.')
+ extra_args = self.determine_args(kwargs)
+ had = self.compiler.has_members(typename, membernames, prefix,
+ self.environment, extra_args)
+ if had:
+ hadtxt = mlog.green('YES')
+ else:
+ hadtxt = mlog.red('NO')
+ members = mlog.bold(', '.join(['"{}"'.format(m) for m in membernames]))
+ mlog.log('Checking whether type "', mlog.bold(typename),
+ '" has members ', members, ': ', hadtxt, sep='')
+ return had
+
def has_function_method(self, args, kwargs):
if len(args) != 1:
raise InterpreterException('Has_function takes exactly one argument.')
@@ -1004,7 +1036,8 @@ 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, encoding='utf8').read()
+ with open(mesonfile, encoding='utf8') as mf:
+ code = mf.read()
if len(code.strip()) == 0:
raise InvalidCode('Builder file is empty.')
assert(isinstance(code, str))
@@ -1097,7 +1130,7 @@ class Interpreter():
if isinstance(v, build.CustomTarget):
self.add_target(v.name, v)
outvalues.append(CustomTargetHolder(v, self))
- elif isinstance(v, int) or isinstance(v, str):
+ elif isinstance(v, (int, str)):
outvalues.append(v)
elif isinstance(v, build.Executable):
self.add_target(v.name, v)
@@ -1353,9 +1386,19 @@ class Interpreter():
cmd = [cmd]
else:
raise InterpreterException('First argument is of incorrect type.')
- check_stringlist(cargs, 'Run_command arguments must be strings.')
- args = cmd + cargs
+ expanded_args = []
+ for a in mesonlib.flatten(cargs):
+ if isinstance(a, str):
+ expanded_args.append(a)
+ elif isinstance(a, mesonlib.File):
+ if a.is_built:
+ raise InterpreterException('Can not use generated files in run_command.')
+ expanded_args.append(os.path.join(self.environment.get_source_dir(), str(a)))
+ else:
+ raise InterpreterException('Run_command arguments must be strings or the output of files().')
+ args = cmd + expanded_args
in_builddir = kwargs.get('in_builddir', False)
+ mlog.debug('Running command:', ' '.join(args))
if not isinstance(in_builddir, bool):
raise InterpreterException('in_builddir must be boolean.')
return RunProcess(args, self.environment.source_dir, self.environment.build_dir,
@@ -1566,6 +1609,10 @@ class Interpreter():
comp = self.environment.detect_vala_compiler()
if need_cross_compiler:
cross_comp = comp # Vala is too (I think).
+ elif lang == 'd':
+ comp = self.environment.detect_d_compiler()
+ if need_cross_compiler:
+ cross_comp = comp # D as well (AFAIK).
elif lang == 'rust':
comp = self.environment.detect_rust_compiler()
if need_cross_compiler:
@@ -1586,7 +1633,9 @@ class Interpreter():
if cross_comp is not None:
cross_comp.sanity_check(self.environment.get_scratch_dir(), self.environment)
self.coredata.cross_compilers[lang] = cross_comp
- new_options = comp.get_options()
+ new_options = cross_comp.get_options()
+ else:
+ new_options = comp.get_options()
optprefix = lang + '_'
for i in new_options:
if not i.startswith(optprefix):
@@ -1685,14 +1734,23 @@ class Interpreter():
dep = cached_dep
else:
# We need to actually search for this dep
+ exception = None
+ dep = None
try:
dep = dependencies.find_external_dependency(name, self.environment, kwargs)
- except dependencies.DependencyException:
+ except dependencies.DependencyException as e:
+ exception = e
+ pass
+
+ if not dep or not dep.found():
if 'fallback' in kwargs:
- dep = self.dependency_fallback(name, kwargs)
- self.coredata.deps[identifier] = dep.held_object
- return dep
- raise
+ fallback_dep = self.dependency_fallback(name, kwargs)
+ if fallback_dep:
+ return fallback_dep
+
+ if not dep:
+ raise exception
+
self.coredata.deps[identifier] = dep
return DependencyHolder(dep)
@@ -1706,9 +1764,12 @@ class Interpreter():
self.do_subproject(dirname, {})
except:
mlog.log('Also couldn\'t find a fallback subproject in',
- mlog.bold(os.path.join(self.subproject_dir, dirname)),
- 'for the dependency', mlog.bold(name))
- raise
+ mlog.bold(os.path.join(self.subproject_dir, dirname)),
+ 'for the dependency', mlog.bold(name))
+ if kwargs.get('required', True):
+ raise
+ else:
+ return None
dep = self.subprojects[dirname].get_variable_method([varname], {})
if not isinstance(dep, (DependencyHolder, InternalDependencyHolder)):
raise InterpreterException('Fallback variable is not a dependency object.')
@@ -1823,12 +1884,12 @@ class Interpreter():
raise InterpreterException('Run_target needs at least one positional argument.')
cleaned_args = []
- for i in all_args:
+ for i in mesonlib.flatten(all_args):
try:
i = i.held_object
except AttributeError:
pass
- if not isinstance(i, (str, build.BuildTarget, build.CustomTarget, dependencies.ExternalProgram)):
+ if not isinstance(i, (str, build.BuildTarget, build.CustomTarget, dependencies.ExternalProgram, mesonlib.File)):
mlog.debug('Wrong type:', str(i))
raise InterpreterException('Invalid argument to run_target.')
cleaned_args.append(i)
@@ -1962,7 +2023,8 @@ class Interpreter():
if not os.path.isfile(absname):
self.subdir = prev_subdir
raise InterpreterException('Nonexistant build def file %s.' % buildfilename)
- code = open(absname, encoding='utf8').read()
+ with open(absname, encoding='utf8') as f:
+ code = f.read()
assert(isinstance(code, str))
try:
codeblock = mparser.Parser(code).parse()
@@ -2078,11 +2140,7 @@ class Interpreter():
def flatten(self, args):
if isinstance(args, mparser.StringNode):
return args.value
- if isinstance(args, str):
- return args
- if isinstance(args, InterpreterObject):
- return args
- if isinstance(args, int):
+ if isinstance(args, (int, str, InterpreterObject)):
return args
result = []
for a in args:
@@ -2098,8 +2156,8 @@ class Interpreter():
def source_strings_to_files(self, sources):
results = []
for s in sources:
- if isinstance(s, mesonlib.File) or isinstance(s, GeneratedListHolder) or \
- isinstance(s, CustomTargetHolder):
+ if isinstance(s, (mesonlib.File, GeneratedListHolder,
+ CustomTargetHolder)):
pass
elif isinstance(s, str):
s = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s)
@@ -2197,14 +2255,8 @@ class Interpreter():
raise InvalidCode('Unknown function "%s".' % func_name)
def is_assignable(self, value):
- if isinstance(value, InterpreterObject) or \
- isinstance(value, dependencies.Dependency) or\
- isinstance(value, str) or\
- isinstance(value, int) or \
- isinstance(value, list) or \
- isinstance(value, mesonlib.File):
- return True
- return False
+ return isinstance(value, (InterpreterObject, dependencies.Dependency,
+ str, int, list, mesonlib.File))
def assignment(self, node):
assert(isinstance(node, mparser.AssignmentNode))
@@ -2257,6 +2309,22 @@ class Interpreter():
else:
raise InterpreterException('Unknown method "%s" for a boolean.' % method_name)
+ def int_method_call(self, obj, method_name, args):
+ obj = self.to_native(obj)
+ (posargs, _) = self.reduce_arguments(args)
+ if method_name == 'is_even':
+ if len(posargs) == 0:
+ return obj % 2 == 0
+ else:
+ raise InterpreterException('int.is_even() must have no arguments.')
+ elif method_name == 'is_odd':
+ if len(posargs) == 0:
+ return obj % 2 != 0
+ else:
+ raise InterpreterException('int.is_odd() must have no arguments.')
+ else:
+ raise InterpreterException('Unknown method "%s" for an integer.' % method_name)
+
def string_method_call(self, obj, method_name, args):
obj = self.to_native(obj)
(posargs, _) = self.reduce_arguments(args)
@@ -2310,9 +2378,8 @@ class Interpreter():
raise InterpreterException('Unknown method "%s" for a string.' % method_name)
def to_native(self, arg):
- if isinstance(arg, mparser.StringNode) or \
- isinstance(arg, mparser.NumberNode) or \
- isinstance(arg, mparser.BooleanNode):
+ if isinstance(arg, (mparser.StringNode, mparser.NumberNode,
+ mparser.BooleanNode)):
return arg.value
return arg
@@ -2344,6 +2411,8 @@ class Interpreter():
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, int):
+ return self.int_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):
@@ -2465,9 +2534,7 @@ class Interpreter():
return iobject[index]
def is_elementary_type(self, v):
- if isinstance(v, (int, float, str, bool, list)):
- return True
- return False
+ return isinstance(v, (int, float, str, bool, list))
def evaluate_comparison(self, node):
v1 = self.evaluate_statement(node.left)
@@ -2562,6 +2629,10 @@ class Interpreter():
if not isinstance(l, int) or not isinstance(r, int):
raise InvalidCode('Division works only with integers.')
return l // r
+ elif cur.operation == 'mod':
+ if not isinstance(l, int) or not isinstance(r, int):
+ raise InvalidCode('Modulo works only with integers.')
+ return l % r
else:
raise InvalidCode('You broke me.')
diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py
index 4b11c10..afabc62 100644
--- a/mesonbuild/mconf.py
+++ b/mesonbuild/mconf.py
@@ -36,15 +36,18 @@ class Conf:
self.build_file = os.path.join(build_dir, 'meson-private/build.dat')
if not os.path.isfile(self.coredata_file) or not os.path.isfile(self.build_file):
raise ConfException('Directory %s does not seem to be a Meson build directory.' % build_dir)
- self.coredata = pickle.load(open(self.coredata_file, 'rb'))
- self.build = pickle.load(open(self.build_file, 'rb'))
+ with open(self.coredata_file, 'rb') as f:
+ self.coredata = pickle.load(f)
+ with open(self.build_file, 'rb') as f:
+ self.build = pickle.load(f)
if self.coredata.version != coredata.version:
raise ConfException('Version mismatch (%s vs %s)' %
(coredata.version, self.coredata.version))
def save(self):
# Only called if something has changed so overwrite unconditionally.
- pickle.dump(self.coredata, open(self.coredata_file, 'wb'))
+ with open(self.coredata_file, 'wb') as f:
+ pickle.dump(self.coredata, f)
# We don't write the build file because any changes to it
# are erased when Meson is executed the nex time, i.e. the next
# time Ninja is run.
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 1672d95..d06e4eb 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -95,11 +95,7 @@ def is_32bit():
return not(sys.maxsize > 2**32)
def is_debianlike():
- try:
- open('/etc/debian_version', 'r')
- return True
- except FileNotFoundError:
- return False
+ return os.path.isfile('/etc/debian_version')
def exe_exists(arglist):
try:
@@ -114,7 +110,7 @@ def exe_exists(arglist):
def detect_vcs(source_dir):
vcs_systems = [
dict(name = 'git', cmd = 'git', repo_dir = '.git', get_rev = 'git describe --dirty=+', rev_regex = '(.*)', dep = '.git/logs/HEAD'),
- dict(name = 'mercurial', cmd = 'hg', repo_dir = '.hg', get_rev = 'hg id -n', rev_regex = '(.*)', dep = '.hg/dirstate'),
+ dict(name = 'mercurial', cmd = 'hg', repo_dir = '.hg', get_rev = 'hg id -i', rev_regex = '(.*)', dep = '.hg/dirstate'),
dict(name = 'subversion', cmd = 'svn', repo_dir = '.svn', get_rev = 'svn info', rev_regex = 'Revision: (.*)', dep = '.svn/wc.db'),
dict(name = 'bazaar', cmd = 'bzr', repo_dir = '.bzr', get_rev = 'bzr revno', rev_regex = '(.*)', dep = '.bzr'),
]
@@ -261,7 +257,11 @@ def do_mesondefine(line, confdata):
def do_conf_file(src, dst, confdata):
- data = open(src).readlines()
+ try:
+ with open(src) as f:
+ data = f.readlines()
+ except Exception:
+ raise MesonException('Could not read input file %s.' % src)
# 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_]+)@')
@@ -273,7 +273,8 @@ def do_conf_file(src, dst, confdata):
line = do_replacement(regex, line, confdata)
result.append(line)
dst_tmp = dst + '~'
- open(dst_tmp, 'w').writelines(result)
+ with open(dst_tmp, 'w') as f:
+ f.writelines(result)
shutil.copymode(src, dst_tmp)
replace_if_different(dst, dst_tmp)
@@ -303,9 +304,10 @@ def replace_if_different(dst, dst_tmp):
# If contents are identical, don't touch the file to prevent
# unnecessary rebuilds.
try:
- if open(dst, 'r').read() == open(dst_tmp, 'r').read():
- os.unlink(dst_tmp)
- return
+ with open(dst, 'r') as f1, open(dst_tmp, 'r') as f2:
+ if f1.read() == f2.read():
+ os.unlink(dst_tmp)
+ return
except FileNotFoundError:
pass
os.replace(dst_tmp, dst)
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index e002d9a..f35d821 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -47,6 +47,7 @@ add_builtin_argument('includedir')
add_builtin_argument('datadir')
add_builtin_argument('mandir')
add_builtin_argument('localedir')
+add_builtin_argument('sysconfdir')
add_builtin_argument('backend')
add_builtin_argument('buildtype')
add_builtin_argument('strip', action='store_true')
@@ -60,8 +61,8 @@ parser.add_argument('--cross-file', default=None,
help='File describing cross compilation environment.')
parser.add_argument('-D', action='append', dest='projectoptions', default=[],
help='Set project options.')
-parser.add_argument('-v', '--version', action='store_true', dest='print_version', default=False,
- help='Print version information.')
+parser.add_argument('-v', '--version', action='version',
+ version=coredata.version)
parser.add_argument('directories', nargs='*')
class MesonApp():
@@ -168,7 +169,8 @@ itself as required.'''
g.generate(intr)
g.run_postconf_scripts()
dumpfile = os.path.join(env.get_scratch_dir(), 'build.dat')
- pickle.dump(b, open(dumpfile, 'wb'))
+ with open(dumpfile, 'wb') as f:
+ pickle.dump(b, f)
# Write this last since we use the existence of this file to check if
# we generated the build file successfully, so we don't want an error
# that pops up during generation, post-conf scripts, etc to cause us to
@@ -244,9 +246,6 @@ def run(mainfile, args):
handshake = False
args = mesonlib.expand_arguments(args)
options = parser.parse_args(args)
- if options.print_version:
- print(coredata.version)
- return 0
args = options.directories
if len(args) == 0 or len(args) > 2:
# if there's a meson.build in the dir above, and not in the current
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index 629b0fc..2086c37 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -177,10 +177,14 @@ def run(args):
buildfile = os.path.join(bdir, 'meson-private/build.dat')
testfile = os.path.join(bdir, 'meson-private/meson_test_setup.dat')
benchmarkfile = os.path.join(bdir, 'meson-private/meson_benchmark_setup.dat')
- coredata = pickle.load(open(corefile, 'rb'))
- builddata = pickle.load(open(buildfile, 'rb'))
- testdata = pickle.load(open(testfile, 'rb'))
- benchmarkdata = pickle.load(open(benchmarkfile, 'rb'))
+ with open(corefile, 'rb') as f:
+ coredata = pickle.load(f)
+ with open(buildfile, 'rb') as f:
+ builddata = pickle.load(f)
+ with open(testfile, 'rb') as f:
+ testdata = pickle.load(f)
+ with open(benchmarkfile, 'rb') as f:
+ benchmarkdata = pickle.load(f)
if options.list_targets:
list_targets(coredata, builddata)
elif options.target_files is not None:
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index be3c3ac..d6a0fcf 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -19,6 +19,7 @@ from .. import build
import os, sys
import subprocess
from ..mesonlib import MesonException
+from .. import dependencies
from .. import mlog
from .. import mesonlib
@@ -61,6 +62,8 @@ class GnomeModule:
cmd += ['--c-name', kwargs.pop('c_name')]
cmd += ['--generate', '--target', '@OUTPUT@']
+ cmd += mesonlib.stringlistify(kwargs.pop('extra_args', []))
+
kwargs['command'] = cmd
kwargs['input'] = args[1]
kwargs['output'] = args[0] + '.c'
@@ -88,6 +91,33 @@ class GnomeModule:
return stdout.split('\n')[:-1]
+ def get_link_args(self, state, lib, depends):
+ link_command = ['-l%s' % lib.name]
+ if isinstance(lib, build.SharedLibrary):
+ link_command += ['-L%s' %
+ os.path.join(state.environment.get_build_dir(),
+ lib.subdir)]
+ depends.append(lib)
+ return link_command
+
+ def get_include_args(self, state, include_dirs):
+ if not include_dirs:
+ return []
+
+ dirs_str = []
+ for incdirs in include_dirs:
+ if hasattr(incdirs, "held_object"):
+ dirs = incdirs.held_object
+ else:
+ dirs = incdirs
+ for incdir in dirs.get_incdirs():
+ if os.path.isabs(incdir):
+ dirs_str += ['-I%s' % os.path.join(incdir)]
+ else:
+ dirs_str += ['-I%s' % os.path.join(state.environment.get_source_dir(),
+ dirs.curdir, incdir)]
+ return dirs_str
+
def generate_gir(self, state, args, kwargs):
if len(args) != 1:
raise MesonException('Gir takes one argument')
@@ -116,27 +146,16 @@ class GnomeModule:
scan_command += ['--no-libtool', '--namespace='+ns, '--nsversion=' + nsversion, '--warn-all',
'--output', '@OUTPUT@']
- extra_args = kwargs.pop('extra_args', [])
- if not isinstance(extra_args, list):
- extra_args = [extra_args]
+ extra_args = mesonlib.stringlistify(kwargs.pop('extra_args', []))
scan_command += extra_args
-
- for incdirs in girtarget.include_dirs:
- for incdir in incdirs.get_incdirs():
- scan_command += ['-I%s' % os.path.join(state.environment.get_source_dir(), incdir)]
+ scan_command += self.get_include_args(state, girtarget.include_dirs)
if 'link_with' in kwargs:
link_with = kwargs.pop('link_with')
if not isinstance(link_with, list):
link_with = [link_with]
for link in link_with:
- lib = link.held_object
- scan_command += ['-l%s' % lib.name]
- if isinstance(lib, build.SharedLibrary):
- scan_command += ['-L%s' %
- os.path.join(state.environment.get_build_dir(),
- lib.subdir)]
- depends.append(lib)
+ scan_command += self.get_link_args(state, link.held_object, depends)
if 'includes' in kwargs:
includes = kwargs.pop('includes')
@@ -175,24 +194,43 @@ class GnomeModule:
if not isinstance (deps, list):
deps = [deps]
for dep in deps:
- girdir = dep.held_object.get_variable ("girdir")
- if girdir:
- scan_command += ["--add-include-path=%s" % girdir]
- for lib in dep.held_object.libs:
- if os.path.isabs(lib) and dep.held_object.is_libtool:
- scan_command += ["-L%s" % os.path.dirname(lib)]
- libname = os.path.basename(lib)
- if libname.startswith("lib"):
- libname = libname[3:]
- libname = libname.split(".so")[0]
- lib = "-l%s" % libname
- scan_command += [lib]
+ if isinstance(dep.held_object, dependencies.InternalDependency):
+ scan_command += self.get_include_args(state, dep.held_object.include_directories)
+ for lib in dep.held_object.libraries:
+ scan_command += self.get_link_args(state, lib.held_object, depends)
+ for source in dep.held_object.sources:
+ if isinstance(source.held_object, GirTarget):
+ scan_command += ["--add-include-path=%s" %
+ os.path.join(state.environment.get_build_dir(),
+ source.held_object.get_subdir())]
+ elif isinstance(dep.held_object, dependencies.PkgConfigDependency):
+ for lib in dep.held_object.libs:
+ if os.path.isabs(lib) and dep.held_object.is_libtool:
+ scan_command += ["-L%s" % os.path.dirname(lib)]
+ libname = os.path.basename(lib)
+ if libname.startswith("lib"):
+ libname = libname[3:]
+ libname = libname.split(".so")[0]
+ lib = "-l%s" % libname
+ # Hack to avoid passing some compiler options in
+ if lib.startswith("-W"):
+ continue
+ scan_command += [lib]
+
+ girdir = dep.held_object.get_variable ("girdir")
+ if girdir:
+ scan_command += ["--add-include-path=%s" % girdir]
+ else:
+ mlog.log('dependency %s not handled to build gir files' % dep)
+ continue
inc_dirs = None
if kwargs.get('include_directories'):
inc_dirs = kwargs.pop('include_directories')
+
if not isinstance(inc_dirs, list):
inc_dirs = [inc_dirs]
+
for ind in inc_dirs:
if isinstance(ind.held_object, build.IncludeDirs):
scan_command += ['--add-include-path=%s' % inc for inc in ind.held_object.get_incdirs()]
@@ -222,9 +260,16 @@ class GnomeModule:
incd.held_object.get_incdirs()]
if deps:
for dep in deps:
- girdir = dep.held_object.get_variable ("girdir")
- if girdir:
- typelib_cmd += ["--includedir=%s" % girdir]
+ if isinstance(dep.held_object, dependencies.InternalDependency):
+ for source in dep.held_object.sources:
+ if isinstance(source.held_object, GirTarget):
+ typelib_cmd += ["--includedir=%s" %
+ os.path.join(state.environment.get_build_dir(),
+ source.held_object.get_subdir())]
+ elif isinstance(dep.held_object, dependencies.PkgConfigDependency):
+ girdir = dep.held_object.get_variable ("girdir")
+ if girdir:
+ typelib_cmd += ["--includedir=%s" % girdir]
kwargs['output'] = typelib_output
kwargs['command'] = typelib_cmd
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 6ee558b..3bf7658 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -18,42 +18,43 @@ import os
class PkgConfigModule:
- def print_hello(self, state, args, kwargs):
- print('Hello from a Meson module')
-
def generate_pkgconfig_file(self, state, libraries, subdirs, name, description, version, filebase,
pub_reqs, priv_reqs, priv_libs):
+ coredata = state.environment.get_coredata()
outdir = state.environment.scratch_dir
fname = os.path.join(outdir, filebase + '.pc')
- ofile = open(fname, 'w')
- coredata = state.environment.get_coredata()
- ofile.write('prefix=%s\n' % coredata.get_builtin_option('prefix'))
- ofile.write('libdir=${prefix}/%s\n' % coredata.get_builtin_option('libdir'))
- ofile.write('includedir=${prefix}/%s\n\n' % coredata.get_builtin_option('includedir'))
- ofile.write('Name: %s\n' % name)
- if len(description) > 0:
- ofile.write('Description: %s\n' % description)
- if len(version) > 0:
- ofile.write('Version: %s\n' % version)
- if len(pub_reqs) > 0:
- ofile.write('Requires: {}\n'.format(' '.join(pub_reqs)))
- if len(priv_reqs) > 0:
- ofile.write('Requires.private: {}\n'.format(' '.join(priv_reqs)))
- if len(priv_libs) > 0:
- ofile.write('Libraries.private: {}\n'.format(' '.join(priv_libs)))
- ofile.write('Libs: -L${libdir} ')
- for l in libraries:
- if l.custom_install_dir:
- ofile.write('-L${prefix}/%s ' % l.custom_install_dir)
- ofile.write('-l%s ' % l.name)
- ofile.write('\n')
- ofile.write('CFlags: ')
- for h in subdirs:
- if h == '.':
- h = ''
- ofile.write(os.path.join('-I${includedir}', h))
- ofile.write(' ')
- ofile.write('\n')
+ with open(fname, 'w') as ofile:
+ ofile.write('prefix=%s\n' % coredata.get_builtin_option('prefix'))
+ ofile.write('libdir=${prefix}/%s\n' %
+ coredata.get_builtin_option('libdir'))
+ ofile.write('includedir=${prefix}/%s\n\n' %
+ coredata.get_builtin_option('includedir'))
+ ofile.write('Name: %s\n' % name)
+ if len(description) > 0:
+ ofile.write('Description: %s\n' % description)
+ if len(version) > 0:
+ ofile.write('Version: %s\n' % version)
+ if len(pub_reqs) > 0:
+ ofile.write('Requires: {}\n'.format(' '.join(pub_reqs)))
+ if len(priv_reqs) > 0:
+ ofile.write(
+ 'Requires.private: {}\n'.format(' '.join(priv_reqs)))
+ if len(priv_libs) > 0:
+ ofile.write(
+ 'Libraries.private: {}\n'.format(' '.join(priv_libs)))
+ ofile.write('Libs: -L${libdir} ')
+ for l in libraries:
+ if l.custom_install_dir:
+ ofile.write('-L${prefix}/%s ' % l.custom_install_dir)
+ ofile.write('-l%s ' % l.name)
+ ofile.write('\n')
+ ofile.write('CFlags: ')
+ for h in subdirs:
+ if h == '.':
+ h = ''
+ ofile.write(os.path.join('-I${includedir}', h))
+ ofile.write(' ')
+ ofile.write('\n')
def generate(self, state, args, kwargs):
if len(args) > 0:
@@ -65,7 +66,7 @@ class PkgConfigModule:
for l in libs:
if hasattr(l, 'held_object'):
l = l.held_object
- if not (isinstance(l, build.SharedLibrary) or isinstance(l, build.StaticLibrary)):
+ if not isinstance(l, (build.SharedLibrary, build.StaticLibrary)):
raise mesonlib.MesonException('Library argument not a library object.')
processed_libs.append(l)
libs = processed_libs
@@ -86,7 +87,11 @@ class PkgConfigModule:
priv_reqs = mesonlib.stringlistify(kwargs.get('requires_private', []))
priv_libs = mesonlib.stringlistify(kwargs.get('libraries_private', []))
pcfile = filebase + '.pc'
- pkgroot = os.path.join(state.environment.coredata.get_builtin_option('libdir'), 'pkgconfig')
+ pkgroot = kwargs.get('install_dir',None)
+ if pkgroot is None:
+ pkgroot = os.path.join(state.environment.coredata.get_builtin_option('libdir'), 'pkgconfig')
+ if not isinstance(pkgroot, str):
+ raise mesonlib.MesonException('Install_dir must be a string.')
self.generate_pkgconfig_file(state, libs, subdirs, name, description, version, filebase,
pub_reqs, priv_reqs, priv_libs)
return build.Data(False, state.environment.get_scratch_dir(), [pcfile], pkgroot)
diff --git a/mesonbuild/modules/rpm.py b/mesonbuild/modules/rpm.py
index acad204..89194e9 100644
--- a/mesonbuild/modules/rpm.py
+++ b/mesonbuild/modules/rpm.py
@@ -80,82 +80,87 @@ class RPMModule:
files.add('%%{_mandir}/man%u/%s.*' % (int(man_file.split('.')[-1]), man_file))
if len(files_devel) > 0:
devel_subpkg = True
- fn = open('%s.spec' % os.path.join(state.environment.get_build_dir(), proj), 'w+')
- fn.write('Name: %s\n' % proj)
- fn.write('Version: # FIXME\n')
- fn.write('Release: 1%{?dist}\n')
- fn.write('Summary: # FIXME\n')
- fn.write('License: # FIXME\n')
- fn.write('\n')
- fn.write('Source0: %{name}-%{version}.tar.xz # FIXME\n')
- fn.write('\n')
- for compiler in compiler_deps:
- fn.write('BuildRequires: %s\n' % compiler)
- for dep in state.environment.coredata.deps:
- fn.write('BuildRequires: pkgconfig(%s)\n' % dep)
- for lib in state.environment.coredata.ext_libs.values():
- fn.write('BuildRequires: %s # FIXME\n' % lib.fullpath)
- mlog.log('Warning, replace', mlog.bold(lib.fullpath), 'with real package.',
- 'You can use following command to find package which contains this lib:',
- mlog.bold('dnf provides %s' % lib.fullpath))
- for prog in state.environment.coredata.ext_progs.values():
- if not prog.found():
- fn.write('BuildRequires: /usr/bin/%s # FIXME\n' % prog.get_name())
- else:
- fn.write('BuildRequires: %s\n' % ' '.join(prog.fullpath))
- fn.write('BuildRequires: meson\n')
- fn.write('\n')
- fn.write('%description\n')
- fn.write('\n')
- if devel_subpkg:
- fn.write('%package devel\n')
- fn.write('Summary: Development files for %{name}\n')
- fn.write('Requires: %{name}%{?_isa} = %{version}-%{release}\n')
+ filename = os.path.join(state.environment.get_build_dir(),
+ '%s.spec' % proj)
+ with open(filename, 'w+') as fn:
+ fn.write('Name: %s\n' % proj)
+ fn.write('Version: # FIXME\n')
+ fn.write('Release: 1%{?dist}\n')
+ fn.write('Summary: # FIXME\n')
+ fn.write('License: # FIXME\n')
+ fn.write('\n')
+ fn.write('Source0: %{name}-%{version}.tar.xz # FIXME\n')
+ fn.write('\n')
+ for compiler in compiler_deps:
+ fn.write('BuildRequires: %s\n' % compiler)
+ for dep in state.environment.coredata.deps:
+ fn.write('BuildRequires: pkgconfig(%s)\n' % dep)
+ for lib in state.environment.coredata.ext_libs.values():
+ fn.write('BuildRequires: %s # FIXME\n' % lib.fullpath)
+ mlog.log('Warning, replace', mlog.bold(lib.fullpath),
+ 'with real package.',
+ 'You can use following command to find package which '
+ 'contains this lib:',
+ mlog.bold('dnf provides %s' % lib.fullpath))
+ for prog in state.environment.coredata.ext_progs.values():
+ if not prog.found():
+ fn.write('BuildRequires: /usr/bin/%s # FIXME\n' %
+ prog.get_name())
+ else:
+ fn.write('BuildRequires: %s\n' % ' '.join(prog.fullpath))
+ fn.write('BuildRequires: meson\n')
+ fn.write('\n')
+ fn.write('%description\n')
fn.write('\n')
- fn.write('%description devel\n')
- fn.write('Development files for %{name}.\n')
+ if devel_subpkg:
+ fn.write('%package devel\n')
+ fn.write('Summary: Development files for %{name}\n')
+ fn.write('Requires: %{name}%{?_isa} = %{version}-%{release}\n')
+ fn.write('\n')
+ fn.write('%description devel\n')
+ fn.write('Development files for %{name}.\n')
+ fn.write('\n')
+ fn.write('%prep\n')
+ fn.write('%autosetup\n')
+ fn.write('rm -rf rpmbuilddir && mkdir rpmbuilddir\n')
fn.write('\n')
- fn.write('%prep\n')
- fn.write('%autosetup\n')
- fn.write('rm -rf rpmbuilddir && mkdir rpmbuilddir\n')
- fn.write('\n')
- fn.write('%build\n')
- fn.write('pushd rpmbuilddir\n')
- fn.write(' %meson ..\n')
- fn.write(' ninja-build -v\n')
- fn.write('popd\n')
- fn.write('\n')
- fn.write('%install\n')
- fn.write('pushd rpmbuilddir\n')
- fn.write(' DESTDIR=%{buildroot} ninja-build -v install\n')
- fn.write('popd\n')
- if len(to_delete) > 0:
- fn.write('rm -rf %s\n' % ' '.join(to_delete))
- fn.write('\n')
- fn.write('%check\n')
- fn.write('pushd rpmbuilddir\n')
- fn.write(' ninja-build -v test\n')
- fn.write('popd\n')
- fn.write('\n')
- fn.write('%files\n')
- for f in files:
- fn.write('%s\n' % f)
- fn.write('\n')
- if devel_subpkg:
- fn.write('%files devel\n')
- for f in files_devel:
+ fn.write('%build\n')
+ fn.write('pushd rpmbuilddir\n')
+ fn.write(' %meson ..\n')
+ fn.write(' ninja-build -v\n')
+ fn.write('popd\n')
+ fn.write('\n')
+ fn.write('%install\n')
+ fn.write('pushd rpmbuilddir\n')
+ fn.write(' DESTDIR=%{buildroot} ninja-build -v install\n')
+ fn.write('popd\n')
+ if len(to_delete) > 0:
+ fn.write('rm -rf %s\n' % ' '.join(to_delete))
+ fn.write('\n')
+ fn.write('%check\n')
+ fn.write('pushd rpmbuilddir\n')
+ fn.write(' ninja-build -v test\n')
+ fn.write('popd\n')
+ fn.write('\n')
+ fn.write('%files\n')
+ for f in files:
fn.write('%s\n' % f)
fn.write('\n')
- if so_installed:
- fn.write('%post -p /sbin/ldconfig\n')
+ if devel_subpkg:
+ fn.write('%files devel\n')
+ for f in files_devel:
+ fn.write('%s\n' % f)
+ fn.write('\n')
+ if so_installed:
+ fn.write('%post -p /sbin/ldconfig\n')
+ fn.write('\n')
+ fn.write('%postun -p /sbin/ldconfig\n')
+ fn.write('\n')
+ fn.write('%changelog\n')
+ fn.write('* %s meson <meson@example.com> - \n' %
+ datetime.date.today().strftime('%a %b %d %Y'))
+ fn.write('- \n')
fn.write('\n')
- fn.write('%postun -p /sbin/ldconfig\n')
- fn.write('\n')
- fn.write('%changelog\n')
- fn.write('* %s meson <meson@example.com> - \n' % datetime.date.today().strftime('%a %b %d %Y'))
- fn.write('- \n')
- fn.write('\n')
- fn.close()
mlog.log('RPM spec template written to %s.spec.\n' % proj)
def initialize():
diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py
index 2f0eb2d..f593c8e 100644
--- a/mesonbuild/mparser.py
+++ b/mesonbuild/mparser.py
@@ -58,6 +58,7 @@ class Lexer:
('plus', re.compile(r'\+')),
('dash', re.compile(r'-')),
('star', re.compile(r'\*')),
+ ('percent', re.compile(r'\%')),
('fslash', re.compile(r'/')),
('colon', re.compile(r':')),
('equal', re.compile(r'==')),
@@ -434,11 +435,17 @@ class Parser:
return left
def e5sub(self):
- left = self.e5mul()
+ left = self.e5mod()
if self.accept('dash'):
return ArithmeticNode(left.lineno, left.colno, 'sub', left, self.e5sub())
return left
+ def e5mod(self):
+ left = self.e5mul()
+ if self.accept('percent'):
+ return ArithmeticNode(left.lineno, left.colno, 'mod', left, self.e5mod())
+ return left
+
def e5mul(self):
left = self.e5div()
if self.accept('star'):
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index 409f9dc..9f57fd6 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -20,6 +20,7 @@ import os, re
forbidden_option_names = coredata.get_builtin_options()
forbidden_prefixes = {'c_': True,
'cpp_': True,
+ 'd_': True,
'rust_': True,
'fortran_': True,
'objc_': True,
@@ -77,7 +78,8 @@ class OptionInterpreter:
def process(self, option_file):
try:
- ast = mparser.Parser(open(option_file, 'r', encoding='utf8').read()).parse()
+ with open(option_file, 'r', encoding='utf8') as f:
+ ast = mparser.Parser(f.read()).parse()
except mesonlib.MesonException as me:
me.file = option_file
raise me
@@ -97,14 +99,11 @@ class OptionInterpreter:
def reduce_single(self, arg):
if isinstance(arg, str):
return arg
- elif isinstance(arg, mparser.StringNode):
- return arg.value
- elif isinstance(arg, mparser.BooleanNode):
+ elif isinstance(arg, (mparser.StringNode, mparser.BooleanNode,
+ mparser.NumberNode)):
return arg.value
elif isinstance(arg, mparser.ArrayNode):
return [self.reduce_single(curarg) for curarg in arg.args.arguments]
- elif isinstance(arg, mparser.NumberNode):
- return arg.value
else:
raise OptionException('Arguments may only be string, int, bool, or array of those.')
diff --git a/mesonbuild/scripts/__init__.py b/mesonbuild/scripts/__init__.py
index 19c4fc7..b2f2258 100644
--- a/mesonbuild/scripts/__init__.py
+++ b/mesonbuild/scripts/__init__.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python3
-
# Copyright 2016 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py
index cb136f4..7124c6f 100644
--- a/mesonbuild/scripts/depfixer.py
+++ b/mesonbuild/scripts/depfixer.py
@@ -115,11 +115,21 @@ class Elf(DataSizes):
self.bfile = bfile
self.verbose = verbose
self.bf = open(bfile, 'r+b')
- (self.ptrsize, self.is_le) = self.detect_elf_type()
- super().__init__(self.ptrsize, self.is_le)
- self.parse_header()
- self.parse_sections()
- self.parse_dynamic()
+ try:
+ (self.ptrsize, self.is_le) = self.detect_elf_type()
+ super().__init__(self.ptrsize, self.is_le)
+ self.parse_header()
+ self.parse_sections()
+ self.parse_dynamic()
+ except:
+ self.bf.close()
+ raise
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.bf.close()
def detect_elf_type(self):
data = self.bf.read(6)
@@ -308,13 +318,13 @@ def run(args):
print('Don\'t run this unless you know what you are doing.')
print('%s: <binary file> <prefix>' % sys.argv[0])
exit(1)
- e = Elf(args[0])
- if len(args) == 1:
- e.print_rpath()
- e.print_runpath()
- else:
- new_rpath = args[1]
- e.fix_rpath(new_rpath)
+ with Elf(args[0]) as e:
+ if len(args) == 1:
+ e.print_rpath()
+ e.print_runpath()
+ else:
+ new_rpath = args[1]
+ e.fix_rpath(new_rpath)
return 0
if __name__ == '__main__':
diff --git a/mesonbuild/scripts/meson_benchmark.py b/mesonbuild/scripts/meson_benchmark.py
index d1107b6..6d138b0 100644
--- a/mesonbuild/scripts/meson_benchmark.py
+++ b/mesonbuild/scripts/meson_benchmark.py
@@ -52,33 +52,34 @@ def run_benchmarks(options, datafile):
failed_tests = 0
logfile_base = 'meson-logs/benchmarklog'
jsonlogfilename = logfile_base+ '.json'
- jsonlogfile = open(jsonlogfilename, 'w')
- tests = pickle.load(open(datafile, 'rb'))
+ with open(datafile, 'rb') as f:
+ tests = pickle.load(f)
num_tests = len(tests)
if num_tests == 0:
print('No benchmarks defined.')
return 0
iteration_count = 5
wrap = [] # Benchmarks on cross builds are pointless so don't support them.
- for i, test in enumerate(tests):
- runs = []
- durations = []
- failed = False
- for _ in range(iteration_count):
- res = meson_test.run_single_test(wrap, test)
- runs.append(res)
- durations.append(res.duration)
- if res.returncode != 0:
- failed = True
- mean = statistics.mean(durations)
- stddev = statistics.stdev(durations)
- if failed:
- resultstr = 'FAIL'
- failed_tests += 1
- else:
- resultstr = 'OK'
- print_stats(3, num_tests, test.name, resultstr, i, mean, stddev)
- print_json_log(jsonlogfile, runs, test.name, i)
+ with open(jsonlogfilename, 'w') as jsonlogfile:
+ for i, test in enumerate(tests):
+ runs = []
+ durations = []
+ failed = False
+ for _ in range(iteration_count):
+ res = meson_test.run_single_test(wrap, test)
+ runs.append(res)
+ durations.append(res.duration)
+ if res.returncode != 0:
+ failed = True
+ mean = statistics.mean(durations)
+ stddev = statistics.stdev(durations)
+ if failed:
+ resultstr = 'FAIL'
+ failed_tests += 1
+ else:
+ resultstr = 'OK'
+ print_stats(3, num_tests, test.name, resultstr, i, mean, stddev)
+ print_json_log(jsonlogfile, runs, test.name, i)
print('\nFull log written to meson-logs/benchmarklog.json.')
return failed_tests
diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py
index f075fa0..d2ae357 100644
--- a/mesonbuild/scripts/meson_exe.py
+++ b/mesonbuild/scripts/meson_exe.py
@@ -59,6 +59,13 @@ def run_exe(exe):
stderr=subprocess.PIPE,
env=child_env,
cwd=exe.workdir)
+ stdout, stderr = p.communicate()
+ if exe.capture and p.returncode == 0:
+ with open(exe.capture, 'wb') as output:
+ output.write(stdout)
+ if stderr:
+ sys.stderr.buffer.write(stderr)
+ return p.returncode
def run(args):
global options
@@ -67,8 +74,9 @@ def run(args):
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)
+ with open(exe_data_file, 'rb') as f:
+ exe = pickle.load(f)
+ return 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 1924b95..5cf02e6 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -37,9 +37,16 @@ def do_copy(from_file, to_file):
shutil.copystat(from_file, to_file)
append_to_log(to_file)
+def get_destdir_path(d, path):
+ if os.path.isabs(path):
+ output = destdir_join(d.destdir, path)
+ else:
+ output = os.path.join(d.fullprefix, path)
+ return output
+
def do_install(datafilename):
- ifile = open(datafilename, 'rb')
- d = pickle.load(ifile)
+ with open(datafilename, 'rb') as ifile:
+ d = pickle.load(ifile)
d.destdir = os.environ.get('DESTDIR', '')
d.fullprefix = destdir_join(d.destdir, d.prefix)
@@ -56,10 +63,7 @@ def install_subdirs(data):
src_dir = src_dir[:-1]
src_prefix = os.path.join(src_dir, inst_dir)
print('Installing subdir %s to %s.' % (src_prefix, dst_dir))
- if os.path.isabs(dst_dir):
- dst_dir = destdir_join(data.destdir, dst_dir)
- else:
- dst_dir = data.fullprefix + dst_dir
+ dst_dir = get_destdir_path(data, dst_dir)
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
for root, dirs, files in os.walk(src_prefix):
@@ -92,27 +96,23 @@ def install_subdirs(data):
def install_data(d):
for i in d.data:
fullfilename = i[0]
- outfilename = i[1]
- if os.path.isabs(outfilename):
- outdir = destdir_join(d.destdir, os.path.split(outfilename)[0])
- outfilename = destdir_join(d.destdir, outfilename)
- else:
- outdir = os.path.join(d.fullprefix, os.path.split(outfilename)[0])
- outfilename = os.path.join(outdir, os.path.split(outfilename)[1])
+ outfilename = get_destdir_path(d, i[1])
+ outdir = os.path.split(outfilename)[0]
os.makedirs(outdir, exist_ok=True)
print('Installing %s to %s.' % (fullfilename, outdir))
do_copy(fullfilename, outfilename)
def install_man(d):
for m in d.man:
- outfileroot = m[1]
- outfilename = os.path.join(d.fullprefix, outfileroot)
full_source_filename = m[0]
+ outfilename = get_destdir_path(d, m[1])
outdir = os.path.split(outfilename)[0]
os.makedirs(outdir, exist_ok=True)
print('Installing %s to %s.' % (full_source_filename, outdir))
if outfilename.endswith('.gz') and not full_source_filename.endswith('.gz'):
- open(outfilename, 'wb').write(gzip.compress(open(full_source_filename, 'rb').read()))
+ with open(outfilename, 'wb') as of:
+ with open(full_source_filename, 'rb') as sf:
+ of.write(gzip.compress(sf.read()))
shutil.copystat(full_source_filename, outfilename)
append_to_log(outfilename)
else:
@@ -121,8 +121,8 @@ def install_man(d):
def install_headers(d):
for t in d.headers:
fullfilename = t[0]
- outdir = os.path.join(d.fullprefix, t[1])
fname = os.path.split(fullfilename)[1]
+ outdir = get_destdir_path(d, t[1])
outfilename = os.path.join(outdir, fname)
print('Installing %s to %s' % (fname, outdir))
os.makedirs(outdir, exist_ok=True)
@@ -142,7 +142,8 @@ def run_install_script(d):
print('Running custom install script %s' % script)
suffix = os.path.splitext(script)[1].lower()
if platform.system().lower() == 'windows' and suffix != '.bat':
- first_line = open(script, encoding='latin_1', errors='ignore').readline().strip()
+ with open(script, encoding='latin_1', errors='ignore') as f:
+ first_line = f.readline().strip()
if first_line.startswith('#!'):
if shutil.which(first_line[2:]):
commands = [first_line[2:]]
@@ -194,9 +195,9 @@ def check_for_stampfile(fname):
def install_targets(d):
for t in d.targets:
fname = check_for_stampfile(t[0])
- outdir = os.path.join(d.fullprefix, t[1])
- aliases = t[2]
+ outdir = get_destdir_path(d, t[1])
outname = os.path.join(outdir, os.path.split(fname)[-1])
+ aliases = t[2]
should_strip = t[3]
install_rpath = t[4]
print('Installing %s to %s' % (fname, outname))
diff --git a/mesonbuild/scripts/meson_test.py b/mesonbuild/scripts/meson_test.py
index 33b6165..ab21654 100644
--- a/mesonbuild/scripts/meson_test.py
+++ b/mesonbuild/scripts/meson_test.py
@@ -44,13 +44,15 @@ parser.add_argument('args', nargs='+')
class TestRun():
- def __init__(self, res, returncode, should_fail, duration, stdo, stde, cmd):
+ def __init__(self, res, returncode, should_fail, duration, stdo, stde, cmd,
+ env):
self.res = res
self.returncode = returncode
self.duration = duration
self.stdo = stdo
self.stde = stde
self.cmd = cmd
+ self.env = env
self.should_fail = should_fail
def get_log(self):
@@ -58,7 +60,9 @@ class TestRun():
if self.cmd is None:
res += 'NONE\n'
else:
- res += ' '.join(self.cmd) + '\n'
+ res += "\n%s %s\n" %(' '.join(
+ ["%s='%s'" % (k, v) for k, v in self.env.items()]),
+ ' ' .join(self.cmd))
if self.stdo:
res += '--- stdout ---\n'
res += self.stdo
@@ -84,7 +88,8 @@ def write_json_log(jsonlogfile, test_name, result):
'result' : result.res,
'duration' : result.duration,
'returncode' : result.returncode,
- 'command' : result.cmd}
+ 'command' : result.cmd,
+ 'env' : result.env}
if result.stde:
jresult['stderr'] = result.stde
jsonlogfile.write(json.dumps(jresult) + '\n')
@@ -162,7 +167,7 @@ def run_single_test(wrap, test):
else:
res = 'FAIL'
returncode = p.returncode
- return TestRun(res, returncode, test.should_fail, duration, stdo, stde, cmd)
+ return TestRun(res, returncode, test.should_fail, duration, stdo, stde, cmd, test.env)
def print_stats(numlen, tests, name, result, i, logfile, jsonlogfile):
global collected_logs, error_count, options
@@ -202,10 +207,8 @@ def run_tests(datafilename):
wrap = [options.wrapper]
logfilename = logfile_base + '-' + options.wrapper.replace(' ', '_') + '.txt'
jsonlogfilename = logfile_base + '-' + options.wrapper.replace(' ', '_') + '.json'
- logfile = open(logfilename, 'w')
- jsonlogfile = open(jsonlogfilename, 'w')
- logfile.write('Log of Meson test suite run on %s.\n\n' % datetime.datetime.now().isoformat())
- tests = pickle.load(open(datafilename, 'rb'))
+ with open(datafilename, 'rb') as f:
+ tests = pickle.load(f)
if len(tests) == 0:
print('No tests defined.')
return
@@ -222,24 +225,31 @@ def run_tests(datafilename):
executor = conc.ThreadPoolExecutor(max_workers=num_workers)
futures = []
filtered_tests = filter_tests(options.suite, tests)
- for i, test in enumerate(filtered_tests):
- if test.suite[0] == '':
- visible_name = test.name
- else:
- if options.suite is not None:
- visible_name = options.suite + ' / ' + test.name
+
+ with open(jsonlogfilename, 'w') as jsonlogfile, \
+ open(logfilename, 'w') as logfile:
+ logfile.write('Log of Meson test suite run on %s.\n\n' %
+ datetime.datetime.now().isoformat())
+ for i, test in enumerate(filtered_tests):
+ if test.suite[0] == '':
+ visible_name = test.name
else:
- visible_name = test.suite[0] + ' / ' + test.name
+ if options.suite is not None:
+ visible_name = options.suite + ' / ' + test.name
+ else:
+ visible_name = test.suite[0] + ' / ' + test.name
- if not test.is_parallel:
- drain_futures(futures)
- futures = []
- res = run_single_test(wrap, test)
- print_stats(numlen, filtered_tests, visible_name, res, i, logfile, jsonlogfile)
- else:
- f = executor.submit(run_single_test, wrap, test)
- futures.append((f, numlen, filtered_tests, visible_name, i, logfile, jsonlogfile))
- drain_futures(futures)
+ if not test.is_parallel:
+ drain_futures(futures)
+ futures = []
+ res = run_single_test(wrap, test)
+ print_stats(numlen, filtered_tests, visible_name, res, i,
+ logfile, jsonlogfile)
+ else:
+ f = executor.submit(run_single_test, wrap, test)
+ futures.append((f, numlen, filtered_tests, visible_name, i,
+ logfile, jsonlogfile))
+ drain_futures(futures)
return logfilename
def run(args):
diff --git a/mesonbuild/scripts/regen_checker.py b/mesonbuild/scripts/regen_checker.py
index f65f3bd..ddf4943 100644
--- a/mesonbuild/scripts/regen_checker.py
+++ b/mesonbuild/scripts/regen_checker.py
@@ -48,8 +48,10 @@ def run(args):
private_dir = args[0]
dumpfile = os.path.join(private_dir, 'regeninfo.dump')
coredata = os.path.join(private_dir, 'coredata.dat')
- regeninfo = pickle.load(open(dumpfile, 'rb'))
- coredata = pickle.load(open(coredata, 'rb'))
+ with open(dumpfile, 'rb') as f:
+ regeninfo = pickle.load(f)
+ with open(coredata, 'rb') as f:
+ coredata = pickle.load(f)
mesonscript = coredata.meson_script_file
backend = coredata.get_builtin_option('backend')
regen_timestamp = os.stat(dumpfile).st_mtime
diff --git a/mesonbuild/scripts/symbolextractor.py b/mesonbuild/scripts/symbolextractor.py
index 79c1264..c117301 100644
--- a/mesonbuild/scripts/symbolextractor.py
+++ b/mesonbuild/scripts/symbolextractor.py
@@ -34,16 +34,19 @@ parser.add_argument('args', nargs='+')
def dummy_syms(outfilename):
"""Just touch it so relinking happens always."""
- open(outfilename, 'w').close()
+ with open(outfilename, 'w'):
+ pass
def write_if_changed(text, outfilename):
try:
- oldtext = open(outfilename, 'r').read()
+ with open(outfilename, 'r') as f:
+ oldtext = f.read()
if text == oldtext:
return
except FileNotFoundError:
pass
- open(outfilename, 'w').write(text)
+ with open(outfilename, 'w') as f:
+ f.write(text)
def linux_syms(libfilename, outfilename):
pe = subprocess.Popen(['readelf', '-d', libfilename], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
diff --git a/mesonbuild/scripts/vcstagger.py b/mesonbuild/scripts/vcstagger.py
index 390e37a..3f36e0a 100644
--- a/mesonbuild/scripts/vcstagger.py
+++ b/mesonbuild/scripts/vcstagger.py
@@ -23,9 +23,16 @@ def config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_
except Exception:
new_string = fallback
- new_data = open(infile).read().replace(replace_string, new_string)
- if (not os.path.exists(outfile)) or (open(outfile).read() != new_data):
- open(outfile, 'w').write(new_data)
+ with open(infile) as f:
+ new_data = f.read().replace(replace_string, new_string)
+ if os.path.exists(outfile):
+ with open(outfile) as f:
+ needs_update = (f.read() != new_data)
+ else:
+ needs_update = True
+ if needs_update:
+ with open(outfile, 'w') as f:
+ f.write(new_data)
def run(args):
infile, outfile, fallback, source_dir, replace_string, regex_selector = args[0:6]
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index 6e3383c..f03af67 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -13,6 +13,7 @@
# limitations under the License.
from .. import mlog
+import contextlib
import urllib.request, os, hashlib, shutil
import subprocess
import sys
@@ -58,23 +59,23 @@ def open_wrapdburl(urlstring):
class PackageDefinition:
def __init__(self, fname):
self.values = {}
- ifile = open(fname)
- first = ifile.readline().strip()
+ with open(fname) as ifile:
+ first = ifile.readline().strip()
- if first == '[wrap-file]':
- self.type = 'file'
- elif first == '[wrap-git]':
- self.type = 'git'
- else:
- raise RuntimeError('Invalid format of package file')
- for line in ifile:
- line = line.strip()
- if line == '':
- continue
- (k, v) = line.split('=', 1)
- k = k.strip()
- v = v.strip()
- self.values[k] = v
+ if first == '[wrap-file]':
+ self.type = 'file'
+ elif first == '[wrap-git]':
+ self.type = 'git'
+ else:
+ raise RuntimeError('Invalid format of package file')
+ for line in ifile:
+ line = line.strip()
+ if line == '':
+ continue
+ (k, v) = line.split('=', 1)
+ k = k.strip()
+ v = v.strip()
+ self.values[k] = v
def get(self, key):
return self.values[key]
@@ -114,7 +115,10 @@ class Resolver:
is_there = os.path.isdir(checkoutdir)
if is_there:
if revno.lower() == 'head':
- subprocess.check_call(['git', 'pull'], cwd=checkoutdir)
+ # Failure to do pull is not a fatal error,
+ # because otherwise you can't develop without
+ # a working net connection.
+ subprocess.call(['git', 'pull'], cwd=checkoutdir)
else:
if subprocess.call(['git', 'checkout', revno], cwd=checkoutdir) != 0:
subprocess.check_call(['git', 'fetch'], cwd=checkoutdir)
@@ -134,26 +138,26 @@ class Resolver:
resp = open_wrapdburl(url)
else:
resp = urllib.request.urlopen(url)
- dlsize = int(resp.info()['Content-Length'])
- print('Download size:', dlsize)
- print('Downloading: ', end='')
- sys.stdout.flush()
- printed_dots = 0
- blocks = []
- downloaded = 0
- while True:
- block = resp.read(blocksize)
- if block == b'':
- break
- downloaded += len(block)
- blocks.append(block)
- ratio = int(downloaded/dlsize * 10)
- while printed_dots < ratio:
- print('.', end='')
- sys.stdout.flush()
- printed_dots += 1
- print('')
- resp.close()
+ with contextlib.closing(resp) as resp:
+ dlsize = int(resp.info()['Content-Length'])
+ print('Download size:', dlsize)
+ print('Downloading: ', end='')
+ sys.stdout.flush()
+ printed_dots = 0
+ blocks = []
+ downloaded = 0
+ while True:
+ block = resp.read(blocksize)
+ if block == b'':
+ break
+ downloaded += len(block)
+ blocks.append(block)
+ ratio = int(downloaded/dlsize * 10)
+ while printed_dots < ratio:
+ print('.', end='')
+ sys.stdout.flush()
+ printed_dots += 1
+ print('')
return b''.join(blocks)
def get_hash(self, data):
@@ -174,7 +178,8 @@ class Resolver:
expected = p.get('source_hash')
if dhash != expected:
raise RuntimeError('Incorrect hash for source %s:\n %s expected\n %s actual.' % (packagename, expected, dhash))
- open(ofname, 'wb').write(srcdata)
+ with open(ofname, 'wb') as f:
+ f.write(srcdata)
if p.has_patch():
purl = p.get('patch_url')
mlog.log('Downloading patch from', mlog.bold(purl))
@@ -183,7 +188,9 @@ class Resolver:
expected = p.get('patch_hash')
if phash != expected:
raise RuntimeError('Incorrect hash for patch %s:\n %s expected\n %s actual' % (packagename, expected, phash))
- open(os.path.join(self.cachedir, p.get('patch_filename')), 'wb').write(pdata)
+ filename = os.path.join(self.cachedir, p.get('patch_filename'))
+ with open(filename, 'wb') as f:
+ f.write(pdata)
else:
mlog.log('Package does not require patch.')
diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py
index c5f8eef..e94a2c5 100755
--- a/mesonbuild/wrap/wraptool.py
+++ b/mesonbuild/wrap/wraptool.py
@@ -92,7 +92,8 @@ def install(name):
(branch, revision) = get_latest_version(name)
u = open_wrapdburl(API_ROOT + 'projects/%s/%s/%s/get_wrap' % (name, branch, revision))
data = u.read()
- open(wrapfile, 'wb').write(data)
+ with open(wrapfile, 'wb') as f:
+ f.write(data)
print('Installed', name, 'branch', branch, 'revision', revision)
def get_current_version(wrapfile):
@@ -129,7 +130,8 @@ def update(name):
os.unlink(os.path.join('subprojects/packagecache', patch_file))
except FileNotFoundError:
pass
- open(wrapfile, 'wb').write(data)
+ with open(wrapfile, 'wb') as f:
+ f.write(data)
print('Updated', name, 'to branch', new_branch, 'revision', new_revision)
def info(name):
diff --git a/run_tests.py b/run_tests.py
index b71ab6d..b57dd39 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -156,8 +156,9 @@ def validate_install(srcdir, installdir):
if os.path.exists(os.path.join(installdir, noinst_file)):
expected[noinst_file] = False
elif os.path.exists(info_file):
- for line in open(info_file):
- expected[platform_fix_exe_name(line.strip())] = False
+ with open(info_file) as f:
+ for line in f:
+ expected[platform_fix_exe_name(line.strip())] = False
# Check if expected files were found
for fname in expected:
if os.path.exists(os.path.join(installdir, fname)):
@@ -249,7 +250,8 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, flags, compile_c
(returncode, stdo, stde) = run_configure_inprocess(gen_command)
try:
logfile = os.path.join(test_build_dir, 'meson-logs/meson-log.txt')
- mesonlog = open(logfile, errors='ignore').read()
+ with open(logfile, errors='ignore') as f:
+ mesonlog = f.read()
except Exception:
mesonlog = 'No meson-log.txt found.'
gen_time = time.time() - gen_start
@@ -304,6 +306,17 @@ def gather_tests(testdir):
tests = [os.path.join(testdir, t[1]) for t in testlist]
return tests
+def have_d_compiler():
+ if shutil.which("ldc2"):
+ return True
+ elif shutil.which("ldc"):
+ return True
+ elif shutil.which("gdc"):
+ return True
+ elif shutil.which("dmd"):
+ return True
+ return False
+
def detect_tests_to_run():
all_tests = []
all_tests.append(('common', gather_tests('test cases/common'), False))
@@ -318,6 +331,7 @@ def detect_tests_to_run():
all_tests.append(('C#', gather_tests('test cases/csharp'), False if shutil.which('mcs') else True))
all_tests.append(('vala', gather_tests('test cases/vala'), False if shutil.which('valac') else True))
all_tests.append(('rust', gather_tests('test cases/rust'), False if shutil.which('rustc') else True))
+ all_tests.append(('d', gather_tests('test cases/d'), False if have_d_compiler() else True))
all_tests.append(('objective c', gather_tests('test cases/objc'), False if not mesonlib.is_windows() else True))
all_tests.append(('fortran', gather_tests('test cases/fortran'), False if shutil.which('gfortran') else True))
all_tests.append(('swift', gather_tests('test cases/swift'), False if shutil.which('swiftc') else True))
@@ -389,7 +403,9 @@ def run_tests(extra_args):
def check_file(fname):
linenum = 1
- for line in open(fname, 'rb').readlines():
+ with open(fname, 'rb') as f:
+ lines = f.readlines()
+ for line in lines:
if b'\t' in line:
print("File %s contains a literal tab on line %d. Only spaces are permitted." % (fname, linenum))
sys.exit(1)
diff --git a/test cases/common/103 manygen/subdir/manygen.py b/test cases/common/103 manygen/subdir/manygen.py
index 4411183..4fd2f25 100755
--- a/test cases/common/103 manygen/subdir/manygen.py
+++ b/test cases/common/103 manygen/subdir/manygen.py
@@ -6,7 +6,8 @@
import sys, os
import shutil, subprocess
-funcname = open(sys.argv[1]).readline().strip()
+with open(sys.argv[1]) as f:
+ funcname = f.readline().strip()
outdir = sys.argv[2]
if not os.path.isdir(outdir):
@@ -21,7 +22,8 @@ if not compiler:
shutil.which('clang') or \
shutil.which('cc')
-if 'cl' in os.path.basename(compiler):
+compbase = os.path.basename(compiler)
+if 'cl' in compbase and 'clang' not in compbase:
libsuffix = '.lib'
is_vs = True
compiler = 'cl'
@@ -44,19 +46,22 @@ outc = os.path.join(outdir, funcname + '.c')
tmpc = 'diibadaaba.c'
tmpo = 'diibadaaba' + objsuffix
-open(outc, 'w').write('''#include"%s.h"
+with open(outc, 'w') as f:
+ f.write('''#include"%s.h"
int %s_in_src() {
return 0;
}
''' % (funcname, funcname))
-open(outh, 'w').write('''#pragma once
+with open(outh, 'w') as f:
+ f.write('''#pragma once
int %s_in_lib();
int %s_in_obj();
int %s_in_src();
''' % (funcname, funcname, funcname))
-open(tmpc, 'w').write('''int %s_in_obj() {
+with open(tmpc, 'w') as f:
+ f.write('''int %s_in_obj() {
return 0;
}
''' % funcname)
@@ -66,7 +71,8 @@ if is_vs:
else:
subprocess.check_call([compiler, '-c', '-o', outo, tmpc])
-open(tmpc, 'w').write('''int %s_in_lib() {
+with open(tmpc, 'w') as f:
+ f.write('''int %s_in_lib() {
return 0;
}
''' % funcname)
diff --git a/test cases/common/107 postconf/postconf.py b/test cases/common/107 postconf/postconf.py
index 209b7af..50c91ca 100644
--- a/test cases/common/107 postconf/postconf.py
+++ b/test cases/common/107 postconf/postconf.py
@@ -7,5 +7,10 @@ template = '''#pragma once
#define THE_NUMBER {}
'''
-data = open(os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat')).readline().strip()
-open(os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h'), 'w').write(template.format(data))
+input_file = os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat')
+output_file = os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h')
+
+with open(input_file) as f:
+ data = f.readline().strip()
+with open(output_file, 'w') as f:
+ f.write(template.format(data))
diff --git a/test cases/common/108 postconf with args/postconf.py b/test cases/common/108 postconf with args/postconf.py
index 4cfbb7c..cef7f79 100644
--- a/test cases/common/108 postconf with args/postconf.py
+++ b/test cases/common/108 postconf with args/postconf.py
@@ -9,5 +9,10 @@ template = '''#pragma once
#define THE_ARG2 {}
'''
-data = open(os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat')).readline().strip()
-open(os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h'), 'w').write(template.format(data, sys.argv[1], sys.argv[2]))
+input_file = os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat')
+output_file = os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h')
+
+with open(input_file) as f:
+ data = f.readline().strip()
+with open(output_file, 'w') as f:
+ f.write(template.format(data, sys.argv[1], sys.argv[2]))
diff --git a/test cases/common/113 generatorcustom/catter.py b/test cases/common/113 generatorcustom/catter.py
index 354d6e0..7a6c085 100755
--- a/test cases/common/113 generatorcustom/catter.py
+++ b/test cases/common/113 generatorcustom/catter.py
@@ -8,6 +8,7 @@ inputs = sys.argv[1:-1]
with open(output, 'w') as ofile:
ofile.write('#pragma once\n')
for i in inputs:
- content = open(i, 'r').read()
+ with open(i, 'r') as ifile:
+ content = ifile.read()
ofile.write(content)
ofile.write('\n')
diff --git a/test cases/common/113 generatorcustom/gen.py b/test cases/common/113 generatorcustom/gen.py
index ba02e3f..c843497 100755
--- a/test cases/common/113 generatorcustom/gen.py
+++ b/test cases/common/113 generatorcustom/gen.py
@@ -5,7 +5,9 @@ import sys, os
ifile = sys.argv[1]
ofile = sys.argv[2]
-resname = open(ifile, 'r').readline().strip()
+with open(ifile, 'r') as f:
+ resname = f.readline().strip()
templ = 'const char %s[] = "%s";\n'
-open(ofile, 'w').write(templ % (resname, resname))
+with open(ofile, 'w') as f:
+ f.write(templ % (resname, resname))
diff --git a/test cases/common/117 custom target capture/data_source.txt b/test cases/common/117 custom target capture/data_source.txt
new file mode 100644
index 0000000..0c23cc0
--- /dev/null
+++ b/test cases/common/117 custom target capture/data_source.txt
@@ -0,0 +1 @@
+This is a text only input file.
diff --git a/test cases/common/117 custom target capture/installed_files.txt b/test cases/common/117 custom target capture/installed_files.txt
new file mode 100644
index 0000000..d90a6b0
--- /dev/null
+++ b/test cases/common/117 custom target capture/installed_files.txt
@@ -0,0 +1 @@
+usr/subdir/data.dat
diff --git a/test cases/common/117 custom target capture/meson.build b/test cases/common/117 custom target capture/meson.build
new file mode 100644
index 0000000..6c19752
--- /dev/null
+++ b/test cases/common/117 custom target capture/meson.build
@@ -0,0 +1,16 @@
+project('custom target', 'c')
+
+python = find_program('python3')
+
+# Note that this will not add a dependency to the compiler executable.
+# Code will not be rebuilt if it changes.
+comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py')
+
+mytarget = custom_target('bindat',
+output : 'data.dat',
+input : 'data_source.txt',
+capture : true,
+command : [python, comp, '@INPUT@'],
+install : true,
+install_dir : 'subdir'
+)
diff --git a/test cases/common/117 custom target capture/my_compiler.py b/test cases/common/117 custom target capture/my_compiler.py
new file mode 100755
index 0000000..b60722a
--- /dev/null
+++ b/test cases/common/117 custom target capture/my_compiler.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python3
+
+import sys
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2:
+ print(sys.argv[0], 'input_file')
+ sys.exit(1)
+ with open(sys.argv[1]) as f:
+ ifile = f.read()
+ if ifile != 'This is a text only input file.\n':
+ print('Malformed input')
+ sys.exit(1)
+ print('This is a binary output file.')
diff --git a/test cases/common/16 configure file/generator.py b/test cases/common/16 configure file/generator.py
index de9a423..31a6944 100755
--- a/test cases/common/16 configure file/generator.py
+++ b/test cases/common/16 configure file/generator.py
@@ -1,13 +1,11 @@
#!/usr/bin/env python3
-import sys
+import sys, os
if len(sys.argv) != 3:
print("Wrong amount of parameters.")
-# Just test that it exists.
-ifile = open(sys.argv[1], 'r')
+assert(os.path.exists(sys.argv[1]))
-ofile = open(sys.argv[2], 'w')
-ofile.write("#define ZERO_RESULT 0\n")
-ofile.close()
+with open(sys.argv[2], 'w') as ofile:
+ ofile.write("#define ZERO_RESULT 0\n")
diff --git a/test cases/common/29 pipeline/meson.build b/test cases/common/29 pipeline/meson.build
index 8418381..200a6d8 100644
--- a/test cases/common/29 pipeline/meson.build
+++ b/test cases/common/29 pipeline/meson.build
@@ -6,8 +6,9 @@ e1 = executable('srcgen', 'srcgen.c', native : true)
# Generate a source file that needs to be included in the build.
gen = generator(e1, \
- output : '@BASENAME@.c', # Line continuation inside arguments should work without needing a "\".
- arguments : ['@INPUT@', '@OUTPUT@'])
+ depfile : '@BASENAME@.d',
+ output : '@BASENAME@.c', # Line continuation inside arguments should work without needing a "\".
+ arguments : ['@INPUT@', '@OUTPUT@', '@DEPFILE@'])
generated = gen.process(['input_src.dat'])
diff --git a/test cases/common/29 pipeline/srcgen.c b/test cases/common/29 pipeline/srcgen.c
index 8095724..ceb9ecc 100644
--- a/test cases/common/29 pipeline/srcgen.c
+++ b/test cases/common/29 pipeline/srcgen.c
@@ -1,5 +1,6 @@
#include<stdio.h>
#include<assert.h>
+#include<string.h>
#define ARRSIZE 80
@@ -7,17 +8,20 @@ int main(int argc, char **argv) {
char arr[ARRSIZE];
char *ofilename;
char *ifilename;
+ char *dfilename;
FILE *ifile;
FILE *ofile;
+ FILE *depfile;
size_t bytes;
+ int i;
- if(argc != 3) {
- fprintf(stderr, "%s <input file> <output file>\n", argv[0]);
+ if(argc != 4) {
+ fprintf(stderr, "%s <input file> <output file> <dependency file>\n", argv[0]);
return 1;
}
ifilename = argv[1];
ofilename = argv[2];
- printf("%s\n", ifilename);
+ dfilename = argv[3];
ifile = fopen(argv[1], "r");
if(!ifile) {
fprintf(stderr, "Could not open source file %s.\n", argv[1]);
@@ -34,7 +38,32 @@ int main(int argc, char **argv) {
assert(bytes > 0);
fwrite(arr, 1, bytes, ofile);
+ depfile = fopen(dfilename, "w");
+ if(!depfile) {
+ fprintf(stderr, "Could not open depfile %s\n", ofilename);
+ fclose(ifile);
+ fclose(ofile);
+ return 1;
+ }
+ for(i=0; i<strlen(ofilename); i++) {
+ if(ofilename[i] == ' ') {
+ fwrite("\\ ", 1, 2, depfile);
+ } else {
+ fwrite(&ofilename[i], 1, 1, depfile);
+ }
+ }
+ fwrite(": ", 1, 2, depfile);
+ for(i=0; i<strlen(ifilename); i++) {
+ if(ifilename[i] == ' ') {
+ fwrite("\\ ", 1, 2, depfile);
+ } else {
+ fwrite(&ifilename[i], 1, 1, depfile);
+ }
+ }
+ fwrite("\n", 1, 1, depfile);
+
fclose(ifile);
fclose(ofile);
+ fclose(depfile);
return 0;
}
diff --git a/test cases/common/38 run program/meson.build b/test cases/common/38 run program/meson.build
index 20a8107..1563dec 100644
--- a/test cases/common/38 run program/meson.build
+++ b/test cases/common/38 run program/meson.build
@@ -41,3 +41,17 @@ endif
if cs.stderr() != ''
error('Extra text in stderr (script).')
endif
+
+# We should be able to have files() in argument
+f = files('meson.build')
+
+if build_machine.system() == 'windows'
+ c = run_command('cmd', '/c', 'echo', f)
+else
+ c = run_command('echo', f)
+endif
+
+if c.returncode() != 0
+ error('Using files() in argument failed.')
+endif
+
diff --git a/test cases/common/44 has member/meson.build b/test cases/common/44 has member/meson.build
index fa01877..e60aeb3 100644
--- a/test cases/common/44 has member/meson.build
+++ b/test cases/common/44 has member/meson.build
@@ -3,9 +3,17 @@ project('has member', 'c')
cc = meson.get_compiler('c')
if not cc.has_member('struct tm', 'tm_sec', prefix : '#include<time.h>')
- error('Did not detect member that exists.')
+ error('Did not detect member of "struct tm" that exists: "tm_sec"')
endif
if cc.has_member('struct tm', 'tm_nonexistent', prefix : '#include<time.h>')
- error('Not existing member found.')
+ error('Not existing member "tm_nonexistent" found.')
+endif
+
+if not cc.has_members('struct tm', 'tm_sec', 'tm_min', prefix : '#include<time.h>')
+ error('Did not detect members of "struct tm" that exist: "tm_sec" "tm_min"')
+endif
+
+if cc.has_members('struct tm', 'tm_sec', 'tm_nonexistent2', prefix : '#include<time.h>')
+ error('Not existing member "tm_nonexistent2" found.')
endif
diff --git a/test cases/common/48 test args/tester.py b/test cases/common/48 test args/tester.py
index 36e510d..0b4010a 100755
--- a/test cases/common/48 test args/tester.py
+++ b/test cases/common/48 test args/tester.py
@@ -2,5 +2,6 @@
import sys
-if open(sys.argv[1]).read() != 'contents\n':
- sys.exit(1)
+with open(sys.argv[1]) as f:
+ if f.read() != 'contents\n':
+ sys.exit(1)
diff --git a/test cases/common/52 custom install dirs/installed_files.txt b/test cases/common/52 custom install dirs/installed_files.txt
index 1b8b561..0cc533a 100644
--- a/test cases/common/52 custom install dirs/installed_files.txt
+++ b/test cases/common/52 custom install dirs/installed_files.txt
@@ -1,4 +1,10 @@
usr/dib/dab/dub/prog?exe
+usr/dib/dab/dub2/prog2?exe
usr/some/dir/sample.h
+usr/some/dir2/sample.h
usr/woman/prog.1.gz
+usr/woman2/prog.1.gz
usr/meow/datafile.cat
+usr/meow2/datafile.cat
+usr/woof/subdir/datafile.dog
+usr/woof2/subdir/datafile.dog
diff --git a/test cases/common/52 custom install dirs/meson.build b/test cases/common/52 custom install dirs/meson.build
index 622ecad..494ff0e 100644
--- a/test cases/common/52 custom install dirs/meson.build
+++ b/test cases/common/52 custom install dirs/meson.build
@@ -1,5 +1,11 @@
project('custom install dirs', 'c')
executable('prog', 'prog.c', install : true, install_dir : 'dib/dab/dub')
+executable('prog2', 'prog.c', install : true, install_dir : get_option('prefix') + '/dib/dab/dub2')
install_headers('sample.h', install_dir : 'some/dir')
+install_headers('sample.h', install_dir : get_option('prefix') + '/some/dir2')
install_man('prog.1', install_dir : 'woman')
+install_man('prog.1', install_dir : get_option('prefix') + '/woman2')
install_data('datafile.cat', install_dir : 'meow')
+install_data('datafile.cat', install_dir : get_option('prefix') + '/meow2')
+install_subdir('subdir', install_dir : 'woof')
+install_subdir('subdir', install_dir : get_option('prefix') + '/woof2')
diff --git a/test cases/common/52 custom install dirs/subdir/datafile.dog b/test cases/common/52 custom install dirs/subdir/datafile.dog
new file mode 100644
index 0000000..7a5bcb7
--- /dev/null
+++ b/test cases/common/52 custom install dirs/subdir/datafile.dog
@@ -0,0 +1 @@
+Installed dog is installed.
diff --git a/test cases/common/56 custom target/depfile/dep.py b/test cases/common/56 custom target/depfile/dep.py
new file mode 100755
index 0000000..585e192
--- /dev/null
+++ b/test cases/common/56 custom target/depfile/dep.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+
+import sys, os
+from glob import glob
+
+_, srcdir, depfile, output = sys.argv
+
+depfiles = glob(os.path.join(srcdir, '*'))
+
+quoted_depfiles = [x.replace(' ', '\ ') for x in depfiles]
+
+with open(output, 'w') as f:
+ f.write('I am the result of globbing.')
+with open(depfile, 'w') as f:
+ f.write('%s: %s\n' % (output, ' '.join(quoted_depfiles)))
diff --git a/test cases/common/56 custom target/depfile/meson.build b/test cases/common/56 custom target/depfile/meson.build
new file mode 100644
index 0000000..46bca74
--- /dev/null
+++ b/test cases/common/56 custom target/depfile/meson.build
@@ -0,0 +1,7 @@
+
+
+mytarget = custom_target('depfile',
+ output : 'dep.dat',
+ depfile : 'dep.dat.d',
+ command : [find_program('dep.py'), meson.current_source_dir(), '@DEPFILE@', '@OUTPUT@'],
+)
diff --git a/test cases/common/56 custom target/meson.build b/test cases/common/56 custom target/meson.build
index db81824..e216bae 100644
--- a/test cases/common/56 custom target/meson.build
+++ b/test cases/common/56 custom target/meson.build
@@ -13,3 +13,5 @@ command : [python, comp, '@INPUT@', '@OUTPUT@'],
install : true,
install_dir : 'subdir'
)
+
+subdir('depfile')
diff --git a/test cases/common/56 custom target/my_compiler.py b/test cases/common/56 custom target/my_compiler.py
index 43e7143..d99029b 100755
--- a/test cases/common/56 custom target/my_compiler.py
+++ b/test cases/common/56 custom target/my_compiler.py
@@ -6,9 +6,10 @@ if __name__ == '__main__':
if len(sys.argv) != 3:
print(sys.argv[0], 'input_file output_file')
sys.exit(1)
- ifile = open(sys.argv[1]).read()
+ with open(sys.argv[1]) as f:
+ ifile = f.read()
if ifile != 'This is a text only input file.\n':
print('Malformed input')
sys.exit(1)
- ofile = open(sys.argv[2], 'w')
- ofile.write('This is a binary output file.\n')
+ with open(sys.argv[2], 'w') as ofile:
+ ofile.write('This is a binary output file.\n')
diff --git a/test cases/common/57 custom target chain/installed_files.txt b/test cases/common/57 custom target chain/installed_files.txt
index 4e326a2..7feb072 100644
--- a/test cases/common/57 custom target chain/installed_files.txt
+++ b/test cases/common/57 custom target chain/installed_files.txt
@@ -1 +1,2 @@
usr/subdir/data2.dat
+usr/subdir/data3.dat
diff --git a/test cases/common/57 custom target chain/meson.build b/test cases/common/57 custom target chain/meson.build
index 286ff61..1af0425 100644
--- a/test cases/common/57 custom target chain/meson.build
+++ b/test cases/common/57 custom target chain/meson.build
@@ -4,7 +4,7 @@ python = find_program('python3')
comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py')
comp2 = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler2.py')
-infile = '@0@/@1@'.format(meson.current_source_dir(), 'data_source.txt')
+infile = files('data_source.txt')[0]
mytarget = custom_target('bindat',
output : 'data.dat',
@@ -18,4 +18,12 @@ mytarget2 = custom_target('bindat2',
install_dir : 'subdir'
)
+mytarget3 = custom_target('bindat3',
+ output : 'data3.dat',
+ input : [mytarget],
+ command : [python, comp2, '@INPUT@', '@OUTPUT@'],
+ install : true,
+ install_dir : 'subdir'
+)
+
subdir('usetarget')
diff --git a/test cases/common/57 custom target chain/my_compiler.py b/test cases/common/57 custom target chain/my_compiler.py
index 43e7143..d99029b 100755
--- a/test cases/common/57 custom target chain/my_compiler.py
+++ b/test cases/common/57 custom target chain/my_compiler.py
@@ -6,9 +6,10 @@ if __name__ == '__main__':
if len(sys.argv) != 3:
print(sys.argv[0], 'input_file output_file')
sys.exit(1)
- ifile = open(sys.argv[1]).read()
+ with open(sys.argv[1]) as f:
+ ifile = f.read()
if ifile != 'This is a text only input file.\n':
print('Malformed input')
sys.exit(1)
- ofile = open(sys.argv[2], 'w')
- ofile.write('This is a binary output file.\n')
+ with open(sys.argv[2], 'w') as ofile:
+ ofile.write('This is a binary output file.\n')
diff --git a/test cases/common/57 custom target chain/my_compiler2.py b/test cases/common/57 custom target chain/my_compiler2.py
index 22a4160..22ec789 100755
--- a/test cases/common/57 custom target chain/my_compiler2.py
+++ b/test cases/common/57 custom target chain/my_compiler2.py
@@ -6,9 +6,10 @@ if __name__ == '__main__':
if len(sys.argv) != 3:
print(sys.argv[0], 'input_file output_file')
sys.exit(1)
- ifile = open(sys.argv[1]).read()
+ with open(sys.argv[1]) as f:
+ ifile = f.read()
if ifile != 'This is a binary output file.\n':
print('Malformed input')
sys.exit(1)
- ofile = open(sys.argv[2], 'w')
- ofile.write('This is a different binary output file.\n')
+ with open(sys.argv[2], 'w') as ofile:
+ ofile.write('This is a different binary output file.\n')
diff --git a/test cases/common/57 custom target chain/usetarget/subcomp.py b/test cases/common/57 custom target chain/usetarget/subcomp.py
index 207a8ad..6f4b686 100755
--- a/test cases/common/57 custom target chain/usetarget/subcomp.py
+++ b/test cases/common/57 custom target chain/usetarget/subcomp.py
@@ -3,5 +3,5 @@
import sys, os
with open(sys.argv[1], 'rb') as ifile:
- open(sys.argv[2], 'w').write('Everything ok.\n')
-
+ with open(sys.argv[2], 'w') as ofile:
+ ofile.write('Everything ok.\n')
diff --git a/test cases/common/58 run target/converter.py b/test cases/common/58 run target/converter.py
index 6acbc84..8dd31fe 100644
--- a/test cases/common/58 run target/converter.py
+++ b/test cases/common/58 run target/converter.py
@@ -2,4 +2,5 @@
import sys
-open(sys.argv[2], 'wb').write(open(sys.argv[1], 'rb').read())
+with open(sys.argv[1], 'rb') as ifile, open(sys.argv[2], 'wb') as ofile:
+ ofile.write(ifile.read())
diff --git a/test cases/common/58 run target/fakeburner.py b/test cases/common/58 run target/fakeburner.py
index a100a6f..5728002 100755
--- a/test cases/common/58 run target/fakeburner.py
+++ b/test cases/common/58 run target/fakeburner.py
@@ -5,7 +5,8 @@ import sys
plain_arg = sys.argv[1]
_, filename, _ = plain_arg.split(':')
try:
- content = open(filename, 'rb').read()
+ with open(filename, 'rb') as f:
+ content = f.read()
except FileNotFoundError:
print('Could not open file. Missing dependency?')
sys.exit(1)
diff --git a/test cases/common/58 run target/meson.build b/test cases/common/58 run target/meson.build
index 0febe35..0ab41b3 100644
--- a/test cases/common/58 run target/meson.build
+++ b/test cases/common/58 run target/meson.build
@@ -34,3 +34,12 @@ run_target('upload2',
python3 = find_program('python3')
run_target('py3hi',
command : [python3, '-c', 'print("I am Python3.")'])
+
+run_target('ct_in_arg',
+ command : ['echo', hex, files('helloprinter.c')])
+
+# What if the output of a custom_target is the command to
+# execute. Obviously this will not work as hex is not an
+# executable but test that the output is generated correctly.
+run_target('donotrunme',
+ command : [hex])
diff --git a/test cases/common/61 custom target source output/generator.py b/test cases/common/61 custom target source output/generator.py
index 4bf5c84..3464b0a 100755
--- a/test cases/common/61 custom target source output/generator.py
+++ b/test cases/common/61 custom target source output/generator.py
@@ -7,8 +7,10 @@ if len(sys.argv) != 2:
odir = sys.argv[1]
-open(os.path.join(odir, 'mylib.h'), 'w').write('int func();\n')
-open(os.path.join(odir, 'mylib.c'), 'w').write('''int func() {
+with open(os.path.join(odir, 'mylib.h'), 'w') as f:
+ f.write('int func();\n')
+with open(os.path.join(odir, 'mylib.c'), 'w') as f:
+ f.write('''int func() {
return 0;
}
''')
diff --git a/test cases/common/64 custom header generator/makeheader.py b/test cases/common/64 custom header generator/makeheader.py
index 9ef2bd5..f156834 100644
--- a/test cases/common/64 custom header generator/makeheader.py
+++ b/test cases/common/64 custom header generator/makeheader.py
@@ -6,5 +6,7 @@
import sys
template = '#define RET_VAL %s\n'
-output = template % (open(sys.argv[1]).readline().strip())
-open(sys.argv[2], 'w').write(output)
+with open(sys.argv[1]) as f:
+ output = template % (f.readline().strip(), )
+with open(sys.argv[2], 'w') as f:
+ f.write(output)
diff --git a/test cases/common/65 multiple generators/mygen.py b/test cases/common/65 multiple generators/mygen.py
index cd786ea..99dc331 100755
--- a/test cases/common/65 multiple generators/mygen.py
+++ b/test cases/common/65 multiple generators/mygen.py
@@ -6,14 +6,17 @@ if len(sys.argv) != 3:
print("You is fail.")
sys.exit(1)
-val = open(sys.argv[1]).read().strip()
+with open(sys.argv[1]) as f:
+ val = f.read().strip()
outdir = sys.argv[2]
outhdr = os.path.join(outdir, 'source%s.h' % val)
outsrc = os.path.join(outdir, 'source%s.cpp' % val)
-open(outhdr, 'w').write('int func%s();\n' % val)
-open(outsrc, 'w').write('''int func%s() {
+with open(outhdr, 'w') as f:
+ f.write('int func%s();\n' % val)
+with open(outsrc, 'w') as f:
+ f.write('''int func%s() {
return 0;
}
''' % val)
diff --git a/test cases/common/68 number arithmetic/meson.build b/test cases/common/68 number arithmetic/meson.build
index 4b98d73..02c7878 100644
--- a/test cases/common/68 number arithmetic/meson.build
+++ b/test cases/common/68 number arithmetic/meson.build
@@ -21,6 +21,27 @@ if (5 / 3) * 3 != 3
error('Integer division is broken')
endif
+assert((5 % 2) == 1, 'Integer modulo (odd) is broken')
+assert((4 % 2) == 0, 'Integer modulo (even) is broken')
+
+if 2 * 1 % 2 != 0
+ error('Modulo precendence with multiplication is broken')
+endif
+if 2 + 1 % 2 != 3
+ error('Modulo precendence with addition is broken')
+endif
+if 9 / 9 % 2 != 1
+ error('Modulo precendence with division is broken')
+endif
+if 9 - 9 % 2 != 8
+ error('Modulo precendence with subtraction is broken')
+endif
+
+assert(2.is_even(), 'int is_even() broken for even value')
+assert(not(2.is_odd()), 'int is_odd() broken for even value')
+assert(not(3.is_even()), 'int is_even() broken for odd value')
+assert(3.is_odd(), 'int is_odd() broken for odd value')
+
assert(3 < 4, 'Lt broken')
assert(not(4 < 3), 'Lt broken')
assert(3 <= 4, 'Lte broken')
diff --git a/test cases/common/72 build always/version_gen.py b/test cases/common/72 build always/version_gen.py
index c82678d..d7b01ca 100755
--- a/test cases/common/72 build always/version_gen.py
+++ b/test cases/common/72 build always/version_gen.py
@@ -14,14 +14,17 @@ def generate(infile, outfile, fallback):
version = stdo.decode().strip()
except:
pass
- newdata = open(infile).read().replace('@VERSION@', version)
+ with open(infile) as f:
+ newdata = f.read().replace('@VERSION@', version)
try:
- olddata = open(outfile).read()
+ with open(outfile) as f:
+ olddata = f.read()
if olddata == newdata:
return
except:
pass
- open(outfile, 'w').write(newdata)
+ with open(outfile, 'w') as f:
+ f.write(newdata)
if __name__ == '__main__':
infile = sys.argv[1]
diff --git a/test cases/common/76 configure file in custom target/src/mycompiler.py b/test cases/common/76 configure file in custom target/src/mycompiler.py
index d5dcab5..b00c862 100644
--- a/test cases/common/76 configure file in custom target/src/mycompiler.py
+++ b/test cases/common/76 configure file in custom target/src/mycompiler.py
@@ -2,7 +2,8 @@
import sys
-ifile = open(sys.argv[1])
-if ifile.readline().strip() != '42':
- print('Incorrect input')
-open(sys.argv[2], 'w').write('Success\n')
+with open(sys.argv[1]) as ifile:
+ if ifile.readline().strip() != '42':
+ print('Incorrect input')
+with open(sys.argv[2], 'w') as ofile:
+ ofile.write('Success\n')
diff --git a/test cases/common/78 ctarget dependency/gen1.py b/test cases/common/78 ctarget dependency/gen1.py
index 64b8e6d..0fa6ea1 100755
--- a/test cases/common/78 ctarget dependency/gen1.py
+++ b/test cases/common/78 ctarget dependency/gen1.py
@@ -6,5 +6,7 @@ import time, sys
# is missing.
time.sleep(0.5)
-contents = open(sys.argv[1], 'r').read()
-open(sys.argv[2], 'w').write(contents)
+with open(sys.argv[1], 'r') as f:
+ contents = f.read()
+with open(sys.argv[2], 'w') as f:
+ f.write(contents)
diff --git a/test cases/common/78 ctarget dependency/gen2.py b/test cases/common/78 ctarget dependency/gen2.py
index 3a8be7d..b087b02 100755
--- a/test cases/common/78 ctarget dependency/gen2.py
+++ b/test cases/common/78 ctarget dependency/gen2.py
@@ -6,4 +6,5 @@ from glob import glob
files = glob(os.path.join(sys.argv[1], '*.tmp'))
assert(len(files) == 1)
-open(sys.argv[2], 'w').write(open(files[0], 'r').read())
+with open(files[0], 'r') as ifile, open(sys.argv[2], 'w') as ofile:
+ ofile.write(ifile.read())
diff --git a/test cases/common/93 private include/stlib/compiler.py b/test cases/common/93 private include/stlib/compiler.py
index 3e74c88..98dbe46 100755
--- a/test cases/common/93 private include/stlib/compiler.py
+++ b/test cases/common/93 private include/stlib/compiler.py
@@ -26,5 +26,7 @@ hfile = os.path.join(outdir, base + '.h')
c_code = c_templ % (base, base)
h_code = h_templ % base
-open(cfile, 'w').write(c_code)
-open(hfile, 'w').write(h_code)
+with open(cfile, 'w') as f:
+ f.write(c_code)
+with open(hfile, 'w') as f:
+ f.write(h_code)
diff --git a/test cases/common/95 dep fallback/meson.build b/test cases/common/95 dep fallback/meson.build
index 86fb6b2..4cf0577 100644
--- a/test cases/common/95 dep fallback/meson.build
+++ b/test cases/common/95 dep fallback/meson.build
@@ -1,6 +1,10 @@
project('dep fallback', 'c')
-bob = dependency('boblib', fallback : ['boblib', 'bob_dep'])
+bob = dependency('boblib', fallback : ['boblib', 'bob_dep'], required: false)
+if not bob.found()
+ error('Bob is actually needed')
+endif
+jimmy = dependency('jimmylib', fallback : ['jimmylib', 'jimmy_dep'], required: false)
exe = executable('bobtester', 'tester.c', dependencies : bob)
test('bobtester', exe)
diff --git a/test cases/common/98 gen extra/srcgen.py b/test cases/common/98 gen extra/srcgen.py
index 55e777e..73bc337 100755
--- a/test cases/common/98 gen extra/srcgen.py
+++ b/test cases/common/98 gen extra/srcgen.py
@@ -19,8 +19,10 @@ c_templ = '''int %s() {
options = parser.parse_args(sys.argv[1:])
-funcname = open(options.input).readline().strip()
+with open(options.input) as f:
+ funcname = f.readline().strip()
if options.upper:
funcname = funcname.upper()
-open(options.output, 'w').write(c_templ % funcname)
+with open(options.output, 'w') as f:
+ f.write(c_templ % funcname)
diff --git a/test cases/d/1 simple/app.d b/test cases/d/1 simple/app.d
new file mode 100644
index 0000000..0be1d2c
--- /dev/null
+++ b/test cases/d/1 simple/app.d
@@ -0,0 +1,8 @@
+
+import std.stdio;
+import utils;
+
+void main ()
+{
+ printGreeting ("a Meson D test");
+}
diff --git a/test cases/d/1 simple/installed_files.txt b/test cases/d/1 simple/installed_files.txt
new file mode 100644
index 0000000..9374c54
--- /dev/null
+++ b/test cases/d/1 simple/installed_files.txt
@@ -0,0 +1 @@
+usr/bin/dsimpleapp?exe
diff --git a/test cases/d/1 simple/meson.build b/test cases/d/1 simple/meson.build
new file mode 100644
index 0000000..a10b67b
--- /dev/null
+++ b/test cases/d/1 simple/meson.build
@@ -0,0 +1,4 @@
+project('D Simple Test', 'd')
+
+e = executable('dsimpleapp', ['app.d', 'utils.d'], install : true)
+test('apptest', e)
diff --git a/test cases/d/1 simple/utils.d b/test cases/d/1 simple/utils.d
new file mode 100644
index 0000000..8645548
--- /dev/null
+++ b/test cases/d/1 simple/utils.d
@@ -0,0 +1,8 @@
+
+import std.stdio;
+import std.string : format;
+
+void printGreeting (string name)
+{
+ writeln ("Hello, I am %s.".format (name));
+}
diff --git a/test cases/d/2 static library/app.d b/test cases/d/2 static library/app.d
new file mode 100644
index 0000000..5d84a69
--- /dev/null
+++ b/test cases/d/2 static library/app.d
@@ -0,0 +1,8 @@
+
+import libstuff;
+
+void main ()
+{
+ immutable ret = printLibraryString ("foo");
+ assert (ret == 4);
+}
diff --git a/test cases/d/2 static library/installed_files.txt b/test cases/d/2 static library/installed_files.txt
new file mode 100644
index 0000000..0f2bab4
--- /dev/null
+++ b/test cases/d/2 static library/installed_files.txt
@@ -0,0 +1,2 @@
+usr/bin/app_s?exe
+usr/lib/libstuff.a
diff --git a/test cases/d/2 static library/libstuff.d b/test cases/d/2 static library/libstuff.d
new file mode 100644
index 0000000..fd3b4d0
--- /dev/null
+++ b/test cases/d/2 static library/libstuff.d
@@ -0,0 +1,9 @@
+
+import std.stdio;
+import std.string : format;
+
+int printLibraryString (string str)
+{
+ writeln ("Static Library says: %s".format (str));
+ return 4;
+}
diff --git a/test cases/d/2 static library/meson.build b/test cases/d/2 static library/meson.build
new file mode 100644
index 0000000..88ed2cb
--- /dev/null
+++ b/test cases/d/2 static library/meson.build
@@ -0,0 +1,5 @@
+project('D Static Library', 'd')
+
+lstatic = static_library('stuff', 'libstuff.d', install : true)
+es = executable('app_s', 'app.d', link_with : lstatic, install : true)
+test('linktest_static', es)
diff --git a/test cases/d/3 shared library/app.d b/test cases/d/3 shared library/app.d
new file mode 100644
index 0000000..5d84a69
--- /dev/null
+++ b/test cases/d/3 shared library/app.d
@@ -0,0 +1,8 @@
+
+import libstuff;
+
+void main ()
+{
+ immutable ret = printLibraryString ("foo");
+ assert (ret == 4);
+}
diff --git a/test cases/d/3 shared library/installed_files.txt b/test cases/d/3 shared library/installed_files.txt
new file mode 100644
index 0000000..d6a4dad
--- /dev/null
+++ b/test cases/d/3 shared library/installed_files.txt
@@ -0,0 +1,2 @@
+usr/bin/app_d?exe
+usr/lib/libstuff.so
diff --git a/test cases/d/3 shared library/libstuff.d b/test cases/d/3 shared library/libstuff.d
new file mode 100644
index 0000000..676a643
--- /dev/null
+++ b/test cases/d/3 shared library/libstuff.d
@@ -0,0 +1,9 @@
+
+import std.stdio;
+import std.string : format;
+
+int printLibraryString (string str)
+{
+ writeln ("Library says: %s".format (str));
+ return 4;
+}
diff --git a/test cases/d/3 shared library/meson.build b/test cases/d/3 shared library/meson.build
new file mode 100644
index 0000000..5dae66b
--- /dev/null
+++ b/test cases/d/3 shared library/meson.build
@@ -0,0 +1,12 @@
+project('D Shared Library', 'd')
+
+if meson.get_compiler('d').get_id() != 'gcc'
+
+ ldyn = shared_library('stuff', 'libstuff.d', install : true)
+ ed = executable('app_d', 'app.d', link_with : ldyn, install : true)
+ test('linktest_dyn', ed)
+
+else
+ message('GDC can not build shared libraries. Test skipped.')
+ install_data('no-installed-files', install_dir : '')
+endif
diff --git a/test cases/d/3 shared library/no-installed-files b/test cases/d/3 shared library/no-installed-files
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/d/3 shared library/no-installed-files
diff --git a/test cases/d/4 library versions/installed_files.txt b/test cases/d/4 library versions/installed_files.txt
new file mode 100644
index 0000000..b997e53
--- /dev/null
+++ b/test cases/d/4 library versions/installed_files.txt
@@ -0,0 +1,9 @@
+usr/lib/libsome.so
+usr/lib/libsome.so.0
+usr/lib/libsome.so.1.2.3
+usr/lib/libnoversion.so
+usr/lib/libonlyversion.so
+usr/lib/libonlyversion.so.1
+usr/lib/libonlyversion.so.1.4.5
+usr/lib/libonlysoversion.so
+usr/lib/libonlysoversion.so.5
diff --git a/test cases/d/4 library versions/lib.d b/test cases/d/4 library versions/lib.d
new file mode 100644
index 0000000..94df91e
--- /dev/null
+++ b/test cases/d/4 library versions/lib.d
@@ -0,0 +1,10 @@
+
+import std.stdio;
+import std.string : format;
+
+@safe
+int printLibraryString (string str)
+{
+ writeln ("Library says: %s".format (str));
+ return 4;
+}
diff --git a/test cases/d/4 library versions/meson.build b/test cases/d/4 library versions/meson.build
new file mode 100644
index 0000000..26cc38a
--- /dev/null
+++ b/test cases/d/4 library versions/meson.build
@@ -0,0 +1,25 @@
+project('D library versions', 'd')
+
+if meson.get_compiler('d').get_id() == 'gcc'
+ message('GDC can not build shared libraries. Test skipped.')
+ install_data('no-installed-files', install_dir : '')
+else
+
+ shared_library('some', 'lib.d',
+ version : '1.2.3',
+ soversion : '0',
+ install : true)
+
+ shared_library('noversion', 'lib.d',
+ install : true)
+
+ shared_library('onlyversion', 'lib.d',
+ version : '1.4.5',
+ install : true)
+
+ shared_library('onlysoversion', 'lib.d',
+ # Also test that int soversion is acceptable
+ soversion : 5,
+ install : true)
+
+endif
diff --git a/test cases/d/4 library versions/no-installed-files b/test cases/d/4 library versions/no-installed-files
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/d/4 library versions/no-installed-files
diff --git a/test cases/d/5 mixed/app.d b/test cases/d/5 mixed/app.d
new file mode 100644
index 0000000..6ab5d97
--- /dev/null
+++ b/test cases/d/5 mixed/app.d
@@ -0,0 +1,8 @@
+
+extern(C) int printLibraryString(const char *str);
+
+void main ()
+{
+ immutable ret = printLibraryString ("C foo");
+ assert (ret == 3);
+}
diff --git a/test cases/d/5 mixed/installed_files.txt b/test cases/d/5 mixed/installed_files.txt
new file mode 100644
index 0000000..9e7fccc
--- /dev/null
+++ b/test cases/d/5 mixed/installed_files.txt
@@ -0,0 +1,4 @@
+usr/bin/appdc_d?exe
+usr/lib/libstuff.so
+usr/bin/appdc_s?exe
+usr/lib/libstuff.a
diff --git a/test cases/d/5 mixed/libstuff.c b/test cases/d/5 mixed/libstuff.c
new file mode 100644
index 0000000..92d6600
--- /dev/null
+++ b/test cases/d/5 mixed/libstuff.c
@@ -0,0 +1,18 @@
+#if defined _WIN32 || defined __CYGWIN__
+ #define DLL_PUBLIC __declspec(dllexport)
+#else
+ #if defined __GNUC__
+ #define DLL_PUBLIC __attribute__ ((visibility("default")))
+ #else
+ #pragma message ("Compiler does not support symbol visibility.")
+ #define DLL_PUBLIC
+ #endif
+#endif
+
+#include <stdio.h>
+
+int DLL_PUBLIC printLibraryString(const char *str)
+{
+ printf("C library says: %s", str);
+ return 3;
+}
diff --git a/test cases/d/5 mixed/meson.build b/test cases/d/5 mixed/meson.build
new file mode 100644
index 0000000..3dad66d
--- /dev/null
+++ b/test cases/d/5 mixed/meson.build
@@ -0,0 +1,9 @@
+project('Mixing C and D', 'd', 'c')
+
+ldyn = shared_library('stuff', 'libstuff.c', install : true)
+ed = executable('appdc_d', 'app.d', link_with : ldyn, install : true)
+test('linktest_cdyn', ed)
+
+lstatic = static_library('stuff', 'libstuff.c', install : true)
+es = executable('appdc_s', 'app.d', link_with : lstatic, install : true)
+test('linktest_cstatic', es)
diff --git a/test cases/d/6 unittest/app.d b/test cases/d/6 unittest/app.d
new file mode 100644
index 0000000..751e754
--- /dev/null
+++ b/test cases/d/6 unittest/app.d
@@ -0,0 +1,34 @@
+
+import std.stdio;
+
+uint getFour ()
+{
+ auto getTwo ()
+ {
+ return 1 + 1;
+ }
+
+ return getTwo () + getTwo ();
+}
+
+void main ()
+{
+ import core.stdc.stdlib : exit;
+
+ writeln ("Four: ", getFour ());
+ exit (4);
+}
+
+unittest
+{
+ writeln ("TEST");
+ import core.stdc.stdlib : exit;
+
+ assert (getFour () > 2);
+ assert (getFour () == 4);
+
+ // we explicitly terminate here to give the unittest program a different exit
+ // code than the main application has.
+ // (this prevents the regular main() from being executed)
+ exit (0);
+}
diff --git a/test cases/d/6 unittest/installed_files.txt b/test cases/d/6 unittest/installed_files.txt
new file mode 100644
index 0000000..e718389
--- /dev/null
+++ b/test cases/d/6 unittest/installed_files.txt
@@ -0,0 +1 @@
+usr/bin/dapp?exe
diff --git a/test cases/d/6 unittest/meson.build b/test cases/d/6 unittest/meson.build
new file mode 100644
index 0000000..1551e94
--- /dev/null
+++ b/test cases/d/6 unittest/meson.build
@@ -0,0 +1,8 @@
+project('D Unittests', 'd')
+
+e = executable('dapp', 'app.d', install : true)
+test('dapp_run', e, should_fail: true)
+
+e_test = executable('dapp_test', 'app.d',
+ d_args: meson.get_compiler('d').unittest_args())
+test('dapp_test', e_test)
diff --git a/test cases/failing/31 invalid man extension/meson.build b/test cases/failing/31 invalid man extension/meson.build
new file mode 100644
index 0000000..45eddca
--- /dev/null
+++ b/test cases/failing/31 invalid man extension/meson.build
@@ -0,0 +1,2 @@
+project('man install', 'c')
+m1 = install_man('foo.a1')
diff --git a/test cases/failing/32 no man extension/meson.build b/test cases/failing/32 no man extension/meson.build
new file mode 100644
index 0000000..bf83571
--- /dev/null
+++ b/test cases/failing/32 no man extension/meson.build
@@ -0,0 +1,2 @@
+project('man install', 'c')
+m1 = install_man('foo')
diff --git a/test cases/frameworks/11 gir subproject/gir/meson-subsample.c b/test cases/frameworks/11 gir subproject/gir/meson-subsample.c
new file mode 100644
index 0000000..2d58a10
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/gir/meson-subsample.c
@@ -0,0 +1,124 @@
+#include "meson-subsample.h"
+
+struct _MesonSubSample
+{
+ MesonSample parent_instance;
+
+ gchar *msg;
+};
+
+G_DEFINE_TYPE (MesonSubSample, meson_sub_sample, MESON_TYPE_SAMPLE)
+
+enum {
+ PROP_0,
+ PROP_MSG,
+ LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+/**
+ * meson_sub_sample_new:
+ * @msg: The message to set.
+ *
+ * Allocates a new #MesonSubSample.
+ *
+ * Returns: (transfer full): a #MesonSubSample.
+ */
+MesonSubSample *
+meson_sub_sample_new (const gchar *msg)
+{
+ g_return_val_if_fail (msg != NULL, NULL);
+
+ return g_object_new (MESON_TYPE_SUB_SAMPLE,
+ "message", msg,
+ NULL);
+}
+
+static void
+meson_sub_sample_finalize (GObject *object)
+{
+ MesonSubSample *self = (MesonSubSample *)object;
+
+ g_clear_pointer (&self->msg, g_free);
+
+ G_OBJECT_CLASS (meson_sub_sample_parent_class)->finalize (object);
+}
+
+static void
+meson_sub_sample_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSubSample *self = MESON_SUB_SAMPLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ g_value_set_string (value, self->msg);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sub_sample_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSubSample *self = MESON_SUB_SAMPLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ self->msg = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sub_sample_class_init (MesonSubSampleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meson_sub_sample_finalize;
+ object_class->get_property = meson_sub_sample_get_property;
+ object_class->set_property = meson_sub_sample_set_property;
+
+ gParamSpecs [PROP_MSG] =
+ g_param_spec_string ("message",
+ "Message",
+ "The message to print.",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+}
+
+static void
+meson_sub_sample_init (MesonSubSample *self)
+{
+}
+
+/**
+ * meson_sub_sample_print_message:
+ * @self: a #MesonSubSample.
+ *
+ * Prints the message.
+ *
+ * Returns: Nothing.
+ */
+void
+meson_sub_sample_print_message (MesonSubSample *self)
+{
+ g_return_if_fail (MESON_IS_SUB_SAMPLE (self));
+
+ g_print ("Message: %s\n", self->msg);
+}
diff --git a/test cases/frameworks/11 gir subproject/gir/meson-subsample.h b/test cases/frameworks/11 gir subproject/gir/meson-subsample.h
new file mode 100644
index 0000000..666d59f
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/gir/meson-subsample.h
@@ -0,0 +1,21 @@
+#ifndef MESON_SUB_SAMPLE_H
+#define MESON_SUB_SAMPLE_H
+
+#if !defined (MESON_TEST)
+#error "MESON_TEST not defined."
+#endif
+
+#include <glib-object.h>
+#include <meson-sample.h>
+
+G_BEGIN_DECLS
+
+#define MESON_TYPE_SUB_SAMPLE (meson_sub_sample_get_type())
+
+G_DECLARE_FINAL_TYPE (MesonSubSample, meson_sub_sample, MESON, SUB_SAMPLE, MesonSample)
+
+MesonSubSample *meson_sub_sample_new (const gchar *msg);
+
+G_END_DECLS
+
+#endif /* MESON_SUB_SAMPLE_H */
diff --git a/test cases/frameworks/11 gir subproject/gir/meson.build b/test cases/frameworks/11 gir subproject/gir/meson.build
new file mode 100644
index 0000000..e92c641
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/gir/meson.build
@@ -0,0 +1,35 @@
+libsources = ['meson-subsample.c', 'meson-subsample.h']
+
+girsubproject = shared_library(
+ 'girsubproject',
+ sources : libsources,
+ dependencies : [gobj, meson_gir],
+ install : true
+)
+
+girexe = executable(
+ 'girprog',
+ sources : 'prog.c',
+ dependencies : [gobj, meson_gir],
+ link_with : girsubproject
+)
+
+gnome.generate_gir(
+ girsubproject,
+ sources : libsources,
+ dependencies : [gobj, meson_gir],
+ nsversion : '1.0',
+ namespace : 'MesonSub',
+ symbol_prefix : 'meson_sub_',
+ identifier_prefix : 'MesonSub',
+ includes : ['GObject-2.0', 'Meson-1.0'],
+ install : true
+)
+
+message('TEST: ' + girsubproject.outdir())
+
+test('gobject introspection/subproject/c', girexe)
+test('gobject introspection/subproject/py', find_program('prog.py'),
+ env : ['GI_TYPELIB_PATH=' + girsubproject.outdir() + ':subprojects/mesongir',
+ 'LD_LIBRARY_PATH=' + girsubproject.outdir() + ':subprojects/mesongir',
+ ])
diff --git a/test cases/frameworks/11 gir subproject/gir/prog.c b/test cases/frameworks/11 gir subproject/gir/prog.c
new file mode 100644
index 0000000..f25c9d8
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/gir/prog.c
@@ -0,0 +1,12 @@
+#include "meson-subsample.h"
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ MesonSample * i = (MesonSample*) meson_sub_sample_new ("Hello, sub/meson/c!");
+ meson_sample_print_message (i);
+ g_object_unref (i);
+
+ return 0;
+}
diff --git a/test cases/frameworks/11 gir subproject/gir/prog.py b/test cases/frameworks/11 gir subproject/gir/prog.py
new file mode 100755
index 0000000..ea4da5b
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/gir/prog.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+from gi.repository import MesonSub
+
+if __name__ == "__main__":
+ s = MesonSub.Sample.new("Hello, sub/meson/py!")
+ s.print_message()
diff --git a/test cases/frameworks/11 gir subproject/installed_files.txt b/test cases/frameworks/11 gir subproject/installed_files.txt
new file mode 100644
index 0000000..434481e
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/installed_files.txt
@@ -0,0 +1,6 @@
+usr/lib/girepository-1.0/Meson-1.0.typelib
+usr/lib/girepository-1.0/MesonSub-1.0.typelib
+usr/share/gir-1.0/Meson-1.0.gir
+usr/share/gir-1.0/MesonSub-1.0.gir
+usr/lib/libgirsubproject.so
+usr/lib/libgirlib.so
diff --git a/test cases/frameworks/11 gir subproject/meson.build b/test cases/frameworks/11 gir subproject/meson.build
new file mode 100644
index 0000000..f3bde40
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/meson.build
@@ -0,0 +1,10 @@
+project('gobject-introspection-with-subproject', 'c')
+
+gnome = import('gnome')
+gobj = dependency('gobject-2.0')
+
+add_global_arguments('-DMESON_TEST', language : 'c')
+meson_gir = dependency('meson-gir', fallback : ['mesongir', 'meson_gir'])
+
+subdir('gir')
+
diff --git a/test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.c b/test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.c
new file mode 100644
index 0000000..2e78b07
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.c
@@ -0,0 +1,127 @@
+#include "meson-sample.h"
+
+typedef struct _MesonSamplePrivate
+{
+ gchar *msg;
+} MesonSamplePrivate;
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (MesonSample, meson_sample, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_MSG,
+ LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+/**
+ * meson_sample_new:
+ * @msg: The message to set.
+ *
+ * Allocates a new #MesonSample.
+ *
+ * Returns: (transfer full): a #MesonSample.
+ */
+MesonSample *
+meson_sample_new (const gchar *msg)
+{
+ g_return_val_if_fail (msg != NULL, NULL);
+
+ return g_object_new (MESON_TYPE_SAMPLE,
+ "message", msg,
+ NULL);
+}
+
+static void
+meson_sample_finalize (GObject *object)
+{
+ MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object);
+
+ g_clear_pointer (&priv->msg, g_free);
+
+ G_OBJECT_CLASS (meson_sample_parent_class)->finalize (object);
+}
+
+static void
+meson_sample_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ g_value_set_string (value, priv->msg);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sample_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ priv->msg = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sample_class_init (MesonSampleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meson_sample_finalize;
+ object_class->get_property = meson_sample_get_property;
+ object_class->set_property = meson_sample_set_property;
+
+ gParamSpecs [PROP_MSG] =
+ g_param_spec_string ("message",
+ "Message",
+ "The message to print.",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+}
+
+static void
+meson_sample_init (MesonSample *self)
+{
+}
+
+/**
+ * meson_sample_print_message:
+ * @self: a #MesonSample.
+ *
+ * Prints the message.
+ *
+ * Returns: Nothing.
+ */
+void
+meson_sample_print_message (MesonSample *self)
+{
+ MesonSamplePrivate *priv;
+
+ g_return_if_fail (MESON_IS_SAMPLE (self));
+
+ priv = meson_sample_get_instance_private (self);
+
+ g_print ("Message: %s\n", priv->msg);
+}
diff --git a/test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.h b/test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.h
new file mode 100644
index 0000000..e4c07a8
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.h
@@ -0,0 +1,26 @@
+#ifndef MESON_SAMPLE_H
+#define MESON_SAMPLE_H
+
+#if !defined (MESON_TEST)
+#error "MESON_TEST not defined."
+#endif
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MESON_TYPE_SAMPLE (meson_sample_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (MesonSample, meson_sample, MESON, SAMPLE, GObject)
+
+struct _MesonSampleClass {
+ GObjectClass parent_class;
+};
+
+
+MesonSample *meson_sample_new (const gchar *msg);
+void meson_sample_print_message (MesonSample *self);
+
+G_END_DECLS
+
+#endif /* MESON_SAMPLE_H */
diff --git a/test cases/frameworks/11 gir subproject/subprojects/mesongir/meson.build b/test cases/frameworks/11 gir subproject/subprojects/mesongir/meson.build
new file mode 100644
index 0000000..027b4ee
--- /dev/null
+++ b/test cases/frameworks/11 gir subproject/subprojects/mesongir/meson.build
@@ -0,0 +1,31 @@
+project('gobject-introspection-subproject', 'c')
+
+gnome = import('gnome')
+gobj = dependency('gobject-2.0')
+
+libsources = ['meson-sample.c', 'meson-sample.h']
+
+girlib = shared_library(
+ 'girlib',
+ sources : libsources,
+ dependencies : gobj,
+ install : true
+)
+
+girtarget = gnome.generate_gir(
+ girlib,
+ sources : libsources,
+ nsversion : '1.0',
+ namespace : 'Meson',
+ symbol_prefix : 'meson_',
+ identifier_prefix : 'Meson',
+ includes : ['GObject-2.0'],
+ install : true
+)
+
+meson_gir = declare_dependency(link_with : girlib,
+ include_directories : [include_directories('.')],
+ dependencies : [gobj],
+ # Everything that uses libgst needs this built to compile
+ sources : girtarget,
+)
diff --git a/test cases/frameworks/6 gettext/src/meson.build b/test cases/frameworks/6 gettext/src/meson.build
index db2490f..2c10027 100644
--- a/test cases/frameworks/6 gettext/src/meson.build
+++ b/test cases/frameworks/6 gettext/src/meson.build
@@ -1 +1,2 @@
-executable('intlprog', 'intlmain.c', install : true)
+executable('intlprog', 'intlmain.c', install : true,
+ dependencies : meson.get_compiler('c').find_library('intl', required : false))
diff --git a/test cases/frameworks/7 gnome/gir/prog.c b/test cases/frameworks/7 gnome/gir/prog.c
index 1116285..c855a6b 100644
--- a/test cases/frameworks/7 gnome/gir/prog.c
+++ b/test cases/frameworks/7 gnome/gir/prog.c
@@ -6,18 +6,26 @@ gint
main (gint argc,
gchar *argv[])
{
- g_autoptr(GError) error = NULL;
+ GError * error = NULL;
- g_autoptr(GOptionContext) ctx = g_option_context_new (NULL);
+ GOptionContext * ctx = g_option_context_new (NULL);
g_option_context_add_group (ctx, g_irepository_get_option_group ());
if (!g_option_context_parse (ctx, &argc, &argv, &error)) {
g_print ("sample: %s\n", error->message);
+ g_option_context_free (ctx);
+ if (error) {
+ g_error_free (error);
+ }
+
return 1;
}
- g_autoptr(MesonSample) i = meson_sample_new ("Hello, meson/c!");
+ MesonSample * i = meson_sample_new ("Hello, meson/c!");
meson_sample_print_message (i);
+ g_object_unref (i);
+ g_option_context_free (ctx);
+
return 0;
}
diff --git a/test cases/frameworks/9 wxwidgets/meson.build b/test cases/frameworks/9 wxwidgets/meson.build
index 4f4d251..c1fa367 100644
--- a/test cases/frameworks/9 wxwidgets/meson.build
+++ b/test cases/frameworks/9 wxwidgets/meson.build
@@ -1,8 +1,9 @@
project('wxwidgets test', 'cpp')
-wxd = dependency('wxwidgets', version : '>=3.0.0')
+wxd = dependency('wxwidgets', version : '>=3.0.0', required : false)
-wp = executable('wxprog', 'wxprog.cpp',
-dependencies : wxd)
+if wxd.found()
+ wp = executable('wxprog', 'wxprog.cpp', dependencies : wxd)
-test('wxtest', wp)
+ test('wxtest', wp)
+endif
diff --git a/test cases/osx/2 library versions/exe.orig.c b/test cases/osx/2 library versions/exe.orig.c
new file mode 100644
index 0000000..1a8cc62
--- /dev/null
+++ b/test cases/osx/2 library versions/exe.orig.c
@@ -0,0 +1,4 @@
+int
+main (int argc, char *argv[])
+{
+}
diff --git a/test cases/osx/2 library versions/installed_files.txt b/test cases/osx/2 library versions/installed_files.txt
index 66470ab..4d58502 100644
--- a/test cases/osx/2 library versions/installed_files.txt
+++ b/test cases/osx/2 library versions/installed_files.txt
@@ -1,4 +1,4 @@
-usr/lib/libsome.0.dylib
+usr/lib/libsome.dylib
usr/lib/libnoversion.dylib
-usr/lib/libonlyversion.1.dylib
-usr/lib/libonlysoversion.5.dylib
+usr/lib/libonlyversion.dylib
+usr/lib/libonlysoversion.dylib
diff --git a/test cases/osx/2 library versions/meson.build b/test cases/osx/2 library versions/meson.build
index 504aa4e..107b467 100644
--- a/test cases/osx/2 library versions/meson.build
+++ b/test cases/osx/2 library versions/meson.build
@@ -1,18 +1,41 @@
project('library versions', 'c')
-shared_library('some', 'lib.c',
+some = shared_library('some', 'lib.c',
version : '1.2.3',
soversion : '0',
install : true)
-shared_library('noversion', 'lib.c',
+noversion = shared_library('noversion', 'lib.c',
install : true)
-shared_library('onlyversion', 'lib.c',
+onlyversion = shared_library('onlyversion', 'lib.c',
version : '1.4.5',
install : true)
-shared_library('onlysoversion', 'lib.c',
+onlysoversion = shared_library('onlysoversion', 'lib.c',
# Also test that int soversion is acceptable
soversion : 5,
install : true)
+
+# Hack to make the executables below depend on the shared libraries above
+# without actually adding them as `link_with` dependencies since we want to try
+# linking to them with -lfoo linker arguments.
+out = custom_target('library-dependency-hack',
+ input : 'exe.orig.c',
+ output : 'exe.c',
+ depends : [some, noversion, onlyversion, onlysoversion],
+ command : ['cp', '@INPUT@', '@OUTPUT@'])
+
+# Manually test if the linker can find the above libraries
+# i.e., whether they were generated with the right naming scheme
+executable('manuallink1', out,
+ link_args : ['-L.', '-lsome'])
+
+executable('manuallink2', out,
+ link_args : ['-L.', '-lnoversion'])
+
+executable('manuallink3', out,
+ link_args : ['-L.', '-lonlyversion'])
+
+executable('manuallink4', out,
+ link_args : ['-L.', '-lonlysoversion'])
diff --git a/tools/ac_converter.py b/tools/ac_converter.py
index 571481e..c7c9f44 100755
--- a/tools/ac_converter.py
+++ b/tools/ac_converter.py
@@ -25,28 +25,6 @@ that are unrelated to configure checks.
import sys
-print('''cc = meson.get_compiler('c')
-cdata = configuration_data()''')
-
-print('check_headers = [')
-
-for line in open(sys.argv[1]):
- line = line.strip()
- if line.startswith('#mesondefine') and \
- line.endswith('_H'):
- token = line.split()[1]
- tarr = token.split('_')[1:-1]
- tarr = [x.lower() for x in tarr]
- hname = '/'.join(tarr) + '.h'
- print(" ['%s', '%s']," % (token, hname))
-print(']\n')
-
-print('''foreach h : check_headers
- if cc.has_header(h.get(1))
- cdata.set(h.get(0), 1)
- endif
-endforeach
-''')
# Add stuff here as it is encountered.
function_data = \
@@ -242,18 +220,71 @@ function_data = \
'HAVE_PTHREAD_SET_NAME_NP': ('pthread_set_name_np', 'pthread.h'),
}
-print('check_functions = [')
+headers = []
+functions = []
+sizes = []
+with open(sys.argv[1]) as f:
+ for line in f:
+ line = line.strip()
+ arr = line.split()
+
+ # Check for headers.
+ if line.startswith('#mesondefine') and line.endswith('_H'):
+ token = line.split()[1]
+ tarr = token.split('_')[1:-1]
+ tarr = [x.lower() for x in tarr]
+ hname = '/'.join(tarr) + '.h'
+ headers.append((token, hname))
+
+ # Check for functions.
+ try:
+ token = arr[1]
+ if token in function_data:
+ fdata = function_data[token]
+ functions.append((token, fdata[0], fdata[1]))
+ elif token.startswith('HAVE_') and not token.endswith('_H'):
+ functions.append((token, ))
+ except Exception:
+ pass
+
+ # Check for sizeof tests.
+ if len(arr) != 2:
+ continue
+ elem = arr[1]
+ if elem.startswith('SIZEOF_'):
+ typename = elem.split('_', 1)[1] \
+ .replace('_P', '*') \
+ .replace('_', ' ') \
+ .lower() \
+ .replace('size t', 'size_t')
+ sizes.append((elem, typename))
-for line in open(sys.argv[1]):
- try:
- token = line.split()[1]
- if token in function_data:
- fdata = function_data[token]
- print(" ['%s', '%s', '#include<%s>']," % (token, fdata[0], fdata[1]))
- elif token.startswith('HAVE_') and not token.endswith('_H'):
- print('# check token', token)
- except Exception:
- pass
+print('''cc = meson.get_compiler('c')
+cdata = configuration_data()''')
+
+# Convert header checks.
+
+print('check_headers = [')
+for token, hname in headers:
+ print(" ['%s', '%s']," % (token, hname))
+print(']\n')
+
+print('''foreach h : check_headers
+ if cc.has_header(h.get(1))
+ cdata.set(h.get(0), 1)
+ endif
+endforeach
+''')
+
+# Convert function checks.
+
+print('check_functions = [')
+for token in functions:
+ if len(func) == 3:
+ token, fdata0, fdata1 = token
+ print(" ['%s', '%s', '#include<%s>']," % (token, fdata0, fdata1))
+ else:
+ print('# check token', token)
print(']\n')
print('''foreach f : check_functions
@@ -265,14 +296,8 @@ endforeach
# Convert sizeof checks.
-for line in open(sys.argv[1]):
- arr = line.strip().split()
- if len(arr) != 2:
- continue
- elem = arr[1]
- if elem.startswith('SIZEOF_'):
- typename = elem.split('_', 1)[1].replace('_P', '*').replace('_', ' ').lower().replace('size t', 'size_t')
- print("cdata.set('%s', cc.sizeof('%s'))" % (elem, typename))
+for elem, typename in sizes:
+ print("cdata.set('%s', cc.sizeof('%s'))" % (elem, typename))
print('''
configure_file(input : 'config.h.meson',
diff --git a/tools/cmake2meson.py b/tools/cmake2meson.py
index 098a6e0..7465d45 100755
--- a/tools/cmake2meson.py
+++ b/tools/cmake2meson.py
@@ -252,39 +252,46 @@ class Converter:
subdir = self.cmake_root
cfile = os.path.join(subdir, 'CMakeLists.txt')
try:
- cmakecode = open(cfile).read()
+ with open(cfile) as f:
+ cmakecode = f.read()
except FileNotFoundError:
print('\nWarning: No CMakeLists.txt in', subdir, '\n')
return
p = Parser(cmakecode)
- outfile = open(os.path.join(subdir, 'meson.build'), 'w')
- for t in p.parse():
- if t.name == 'add_subdirectory':
- #print('\nRecursing to subdir', os.path.join(self.cmake_root, t.args[0].value), '\n')
- self.convert(os.path.join(subdir, t.args[0].value))
- #print('\nReturning to', self.cmake_root, '\n')
- self.write_entry(outfile, t)
+ with open(os.path.join(subdir, 'meson.build'), 'w') as outfile:
+ for t in p.parse():
+ if t.name == 'add_subdirectory':
+ # print('\nRecursing to subdir',
+ # os.path.join(self.cmake_root, t.args[0].value),
+ # '\n')
+ self.convert(os.path.join(subdir, t.args[0].value))
+ # print('\nReturning to', self.cmake_root, '\n')
+ self.write_entry(outfile, t)
if subdir == self.cmake_root and len(self.options) > 0:
self.write_options()
def write_options(self):
- optfile = open(os.path.join(self.cmake_root, 'meson_options.txt'), 'w')
- for o in self.options:
- (optname, description, default) = o
- if default is None:
- defaultstr = ''
- else:
- if default == 'OFF':
- typestr = ' type : boolean,'
- default = 'false'
- elif default == 'ON':
- default = 'true'
- typestr = ' type : boolean,'
+ filename = os.path.join(self.cmake_root, 'meson_options.txt')
+ with open(filename, 'w') as optfile:
+ for o in self.options:
+ (optname, description, default) = o
+ if default is None:
+ defaultstr = ''
else:
- typestr = ' type : string,'
- defaultstr = ' value : %s,' % default
- line = "option(%s,%s%s description : '%s')\n" % (optname, typestr, defaultstr, description)
- optfile.write(line)
+ if default == 'OFF':
+ typestr = ' type : boolean,'
+ default = 'false'
+ elif default == 'ON':
+ default = 'true'
+ typestr = ' type : boolean,'
+ else:
+ typestr = ' type : string,'
+ defaultstr = ' value : %s,' % default
+ line = "option(%s,%s%s description : '%s')\n" % (optname,
+ typestr,
+ defaultstr,
+ description)
+ optfile.write(line)
if __name__ == '__main__':
if len(sys.argv) != 2: