aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml43
-rw-r--r--.travis.yml20
-rw-r--r--authors.txt1
-rw-r--r--contributing.txt2
-rw-r--r--mesonbuild/backend/backends.py84
-rw-r--r--mesonbuild/backend/ninjabackend.py30
-rw-r--r--mesonbuild/backend/vs2010backend.py160
-rw-r--r--mesonbuild/build.py10
-rw-r--r--mesonbuild/compilers.py93
-rw-r--r--mesonbuild/coredata.py1
-rw-r--r--mesonbuild/environment.py11
-rw-r--r--mesonbuild/interpreter.py31
-rw-r--r--mesonbuild/mesonmain.py8
-rw-r--r--mesonbuild/mlog.py6
-rw-r--r--mesonbuild/modules/gnome.py157
-rw-r--r--mesonbuild/modules/pkgconfig.py4
-rw-r--r--mesonbuild/modules/qt4.py6
-rw-r--r--mesonbuild/modules/qt5.py6
-rw-r--r--mesonbuild/modules/rpm.py15
-rwxr-xr-xmesonbuild/scripts/regen_checker.py2
-rw-r--r--mesonbuild/scripts/scanbuild.py13
-rw-r--r--mesonbuild/scripts/yelphelper.py2
-rwxr-xr-xrun_project_tests.py57
-rwxr-xr-xrun_unittests.py8
-rwxr-xr-xtest cases/common/103 manygen/subdir/manygen.py3
-rw-r--r--test cases/common/103 manygen/subdir/meson.build13
-rw-r--r--test cases/common/111 has header symbol/meson.build32
-rw-r--r--test cases/common/113 generatorcustom/meson.build26
-rw-r--r--test cases/common/121 skip/meson.build4
-rw-r--r--test cases/common/16 configure file/config.h1
-rw-r--r--test cases/common/16 configure file/prog.c5
-rw-r--r--test cases/common/16 configure file/prog2.c2
-rw-r--r--test cases/common/33 try compile/meson.build29
-rw-r--r--test cases/common/35 sizeof/meson.build24
-rw-r--r--test cases/common/35 sizeof/prog.c.in (renamed from test cases/common/35 sizeof/prog.c)6
-rw-r--r--test cases/common/37 has header/meson.build18
-rw-r--r--test cases/common/39 tryrun/meson.build80
-rw-r--r--test cases/common/43 has function/meson.build72
-rw-r--r--test cases/common/44 has member/meson.build30
-rw-r--r--test cases/common/45 alignment/meson.build48
-rw-r--r--test cases/common/51 pkgconfig-gen/meson.build2
-rw-r--r--test cases/common/56 custom target/meson.build2
-rwxr-xr-xtest cases/common/56 custom target/my_compiler.py9
-rwxr-xr-xtest cases/common/58 run target/check_exists.py7
-rw-r--r--test cases/common/58 run target/meson.build4
-rw-r--r--test cases/common/62 exe static shared/stat.c4
-rw-r--r--test cases/common/83 has type/meson.build18
-rw-r--r--test cases/failing/34 dependency not-required then required/meson.build2
-rw-r--r--test cases/failing/34 non-root subproject/meson.build3
-rw-r--r--test cases/failing/34 non-root subproject/some/meson.build1
-rw-r--r--test cases/frameworks/10 gtk-doc/meson.build4
-rw-r--r--test cases/python3/3 cython/meson.build2
-rw-r--r--test cases/vala/11 mixed sources/meson.build3
53 files changed, 780 insertions, 444 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 38ebe56..adc13b8 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -2,23 +2,56 @@ version: 1.0.{build}
os: Visual Studio 2015
+environment:
+ matrix:
+ - arch: x86
+ compiler: msvc2010
+ backend: ninja
+
+ - arch: x86
+ compiler: msvc2010
+ backend: vs2010
+
+ - arch: x86
+ compiler: msvc2015
+ backend: ninja
+
+ - arch: x86
+ compiler: msvc2015
+ backend: vs2015
+
+ - arch: x64
+ compiler: msvc2015
+ backend: ninja
+
+ - arch: x64
+ compiler: msvc2015
+ backend: vs2015
+
platform:
- - x86
+ - x64
branches:
only:
- master
install:
- - ps: (new-object net.webclient).DownloadFile('https://dl.dropboxusercontent.com/u/37517477/ninja.exe', 'c:\python34\ninja.exe')
- - cmd: copy c:\python34\python.exe c:\python34\python3.exe
- - '"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x86'
+ # Use the x86 python only when building for x86 for the cpython tests.
+ # For all other archs (including, say, arm), use the x64 python.
+ - ps: (new-object net.webclient).DownloadFile('https://dl.dropboxusercontent.com/u/37517477/ninja.exe', 'C:\projects\meson\ninja.exe')
+ - cmd: if %arch%==x86 (set MESON_PYTHON_PATH=C:\python34) else (set MESON_PYTHON_PATH=C:\python34-x64)
+ - cmd: echo Using Python at %MESON_PYTHON_PATH%
+ - cmd: copy %MESON_PYTHON_PATH%\python.exe %MESON_PYTHON_PATH%\python3.exe
+ - cmd: if %compiler%==msvc2010 ( call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" %arch% )
+ - cmd: if %compiler%==msvc2015 ( call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %arch% )
build_script:
- cmd: echo No build step.
+ - cmd: if %backend%==ninja ( ninja.exe --version ) else ( MSBuild /version & echo. )
test_script:
- - cmd: PATH c:\python34;%PATH%; && python3 run_tests.py --backend=ninja
+ - cmd: echo Running tests for %arch% and %compiler% with the %backend% backend
+ - cmd: PATH=%cd%;%MESON_PYTHON_PATH%;%PATH%; && python3 run_tests.py --backend=%backend%
on_finish:
- appveyor PushArtifact meson-test-run.txt -DeploymentName "Text test logs"
diff --git a/.travis.yml b/.travis.yml
index cf3a5a6..8648572 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,15 +1,29 @@
-sudo: required
+sudo: false
os:
- linux
- osx
+compiler:
+ - gcc
+ - clang
+
+env:
+ - MESON_ARGS=""
+ - MESON_ARGS="--unity"
+
language:
- cpp
services:
- docker
+matrix:
+ exclude:
+ # On OS X gcc is just a wrapper around clang, so don't waste time testing that
+ - os: osx
+ compiler: gcc
+
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ninja python3; fi
@@ -22,5 +36,5 @@ script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo FROM jpakkane/mesonci:yakkety > Dockerfile; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo ADD . /root >> Dockerfile; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker build -t withgit .; fi
- - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true ./run_tests.py"; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) ./run_tests.py --backend=ninja ; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true CC=$CC CXX=$CXX ./run_tests.py -- $MESON_ARGS"; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) ./run_tests.py --backend=ninja -- $MESON_ARGS ; fi
diff --git a/authors.txt b/authors.txt
index f591d13..c2e8388 100644
--- a/authors.txt
+++ b/authors.txt
@@ -54,3 +54,4 @@ Alexandre Foley
Jouni Kosonen
Aurelien Jarno
Mark Schulte
+Paulo Antonio Alvarez
diff --git a/contributing.txt b/contributing.txt
index 7553ab0..cb71ca0 100644
--- a/contributing.txt
+++ b/contributing.txt
@@ -32,7 +32,7 @@ those are simple.
External dependencies
The goal of Meson is to be as easily usable as possible. The user
-experience thould be "get Python3 and Ninja, run", even on
+experience should be "get Python3 and Ninja, run", even on
Windows. Unfortunately this means that we can't have dependencies on
projects outside of Python's standard library. This applies only to
core functionality, though. For additional helper programs etc the use
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index e91b44b..2861bb6 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -81,8 +81,8 @@ class Backend():
def get_target_filename(self, t):
if isinstance(t, build.CustomTarget):
if len(t.get_outputs()) != 1:
- mlog.log(mlog.red('WARNING'), 'custom_target {!r} has more ' \
- 'than one output! Using the first one.'.format(t.name))
+ mlog.warning('custom_target {!r} has more than one output! ' \
+ 'Using the first one.'.format(t.name))
filename = t.get_outputs()[0]
else:
assert(isinstance(t, build.BuildTarget))
@@ -236,19 +236,23 @@ class Backend():
def determine_linker(self, target, src):
if isinstance(target, build.StaticLibrary):
- if self.build.static_cross_linker is not None:
+ if target.is_cross:
return self.build.static_cross_linker
else:
return self.build.static_linker
- if len(self.build.compilers) == 1:
- return self.build.compilers[0]
+ if target.is_cross:
+ compilers = self.build.cross_compilers
+ else:
+ compilers = self.build.compilers
+ if len(compilers) == 1:
+ return compilers[0]
# Currently a bit naive. C++ must
# be linked with a C++ compiler, but
# otherwise we don't care. This will
# become trickier if and when Fortran
# and the like become supported.
cpp = None
- for c in self.build.compilers:
+ for c in compilers:
if c.get_language() == 'cpp':
cpp = c
break
@@ -256,7 +260,7 @@ class Backend():
for s in src:
if c.can_compile(s):
return cpp
- for c in self.build.compilers:
+ for c in compilers:
if c.get_language() == 'vala':
continue
for s in src:
@@ -568,32 +572,46 @@ class Backend():
i = i.replace('@INPUT%d@' % j, src)
for (j, res) in enumerate(ofilenames):
i = i.replace('@OUTPUT%d@' % j, res)
- if i == '@INPUT@':
- cmd += srcs
- elif i == '@OUTPUT@':
- cmd += ofilenames
- 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)
- if match.group(1) is None and not absolute_paths:
- lead_dir = ''
- else:
- lead_dir = self.environment.get_build_dir()
- i = i.replace(source,
- os.path.join(lead_dir,
- outdir))
- cmd.append(i)
+ if '@INPUT@' in i:
+ msg = 'Custom target {} has @INPUT@ in the command, but'.format(target.name)
+ if len(srcs) == 0:
+ raise MesonException(msg + ' no input files')
+ if i == '@INPUT@':
+ cmd += srcs
+ continue
+ else:
+ if len(srcs) > 1:
+ raise MesonException(msg + ' more than one input file')
+ i = i.replace('@INPUT@', srcs[0])
+ elif '@OUTPUT@' in i:
+ msg = 'Custom target {} has @OUTPUT@ in the command, but'.format(target.name)
+ if len(ofilenames) == 0:
+ raise MesonException(msg + ' no output files')
+ if i == '@OUTPUT@':
+ cmd += ofilenames
+ continue
+ else:
+ if len(ofilenames) > 1:
+ raise MesonException(msg + ' more than one output file')
+ i = i.replace('@OUTPUT@', ofilenames[0])
+ elif '@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)
+ dfilename = os.path.join(outdir, 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)
+ if match.group(1) is None and not absolute_paths:
+ lead_dir = ''
+ else:
+ lead_dir = self.environment.get_build_dir()
+ i = i.replace(source,
+ os.path.join(lead_dir,
+ outdir))
+ cmd.append(i)
# This should not be necessary but removing it breaks
# building GStreamer on Windows. The underlying issue
# is problems with quoting backslashes on Windows
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index add7dcc..c854f1b 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -215,7 +215,7 @@ int dummy;
with open(os.path.join(builddir, 'compile_commands.json'), 'wb') as f:
f.write(jsondb)
except Exception:
- mlog.log(mlog.red('Warning:', 'Could not create compilation database.'))
+ mlog.warning('Could not create compilation database.')
# Get all generated headers. Any source file might need them so
# we need to add an order dependency to them.
@@ -494,8 +494,8 @@ int dummy;
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))
+ rel_dfile = os.path.join(self.get_target_dir(target), target.depfile)
+ abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
os.makedirs(abs_pdir, exist_ok=True)
elem.add_item('DEPFILE', rel_dfile)
elem.add_item('COMMAND', cmd)
@@ -515,10 +515,10 @@ int dummy;
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))
+ relfname = i.rel_to_builddir(self.build_to_src)
+ arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname))
else:
- mlog.debug(str(i))
- raise MesonException('Unreachable code in generate_run_target.')
+ raise AssertionError('Unreachable code in generate_run_target: ' + str(i))
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
@@ -581,7 +581,7 @@ int dummy;
elem.add_item('DESC', 'Generating HTML coverage report.')
elem.write(outfile)
if not added_rule:
- mlog.log(mlog.red('Warning:'), 'coverage requested but neither gcovr nor lcov/genhtml found.')
+ mlog.warning('coverage requested but neither gcovr nor lcov/genhtml found.')
def generate_install(self, outfile):
install_data_file = os.path.join(self.environment.get_scratch_dir(), 'install.dat')
@@ -1024,6 +1024,7 @@ int dummy;
# found inside the build tree (generated sources).
args += ['-d', c_out_dir]
args += ['-C']
+ args += ['--nostdpkg']
if not isinstance(target, build.Executable):
# Library name
args += ['--library=' + target.name]
@@ -1694,9 +1695,9 @@ rule FORTRAN_DEP_HACK
if target.has_pch():
tfilename = self.get_target_filename_abs(target)
- return compiler.get_compile_debugfile_args(tfilename)
+ return compiler.get_compile_debugfile_args(tfilename, pch=True)
else:
- return compiler.get_compile_debugfile_args(objfile)
+ return compiler.get_compile_debugfile_args(objfile, pch=False)
def get_link_debugfile_args(self, linker, target, outname):
return linker.get_link_debugfile_args(outname)
@@ -1720,10 +1721,11 @@ rule FORTRAN_DEP_HACK
# Add the root source and build directories as include dirs
curdir = target.get_subdir()
tmppath = os.path.normpath(os.path.join(self.build_to_src, curdir))
- commands += compiler.get_include_args(tmppath, False)
+ src_inc = compiler.get_include_args(tmppath, False)
if curdir == '':
curdir = '.'
- commands += compiler.get_include_args(curdir, False)
+ build_inc = compiler.get_include_args(curdir, False)
+ commands += build_inc + src_inc
# -I args work differently than other ones. In them the first found
# directory is used whereas for other flags (such as -ffoo -fno-foo) the
# latest one is used. Therefore put the internal include directories
@@ -2084,7 +2086,7 @@ rule FORTRAN_DEP_HACK
ninja_command = environment.detect_ninja()
if ninja_command is None:
- raise MesonException('Could not detect Ninja v1.6 or newer)')
+ raise MesonException('Could not detect Ninja v1.6 or newer')
elem = NinjaBuildElement(self.all_outputs, 'clean', 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('COMMAND', [ninja_command, '-t', 'clean'])
elem.add_item('description', 'Cleaning')
@@ -2100,5 +2102,9 @@ rule FORTRAN_DEP_HACK
elem.add_item('pool', 'console')
elem.write(outfile)
+ elem = NinjaBuildElement(self.all_outputs, 'reconfigure', 'REGENERATE_BUILD', 'PHONY')
+ elem.add_item('pool', 'console')
+ elem.write(outfile)
+
elem = NinjaBuildElement(self.all_outputs, deps, 'phony', '')
elem.write(outfile)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index f1d949a..c66233e 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -284,20 +284,13 @@ class Vs2010Backend(backends.Backend):
def generate_projects(self):
projlist = []
- comp = None
- for l, c in self.environment.coredata.compilers.items():
- if l == 'c' or l == 'cpp':
- comp = c
- break
- if comp is None:
- raise RuntimeError('C and C++ compilers missing.')
for name, target in self.build.targets.items():
outdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
fname = name + '.vcxproj'
relname = os.path.join(target.subdir, fname)
projfile = os.path.join(outdir, fname)
uuid = self.environment.coredata.target_guids[name]
- self.gen_vcxproj(target, projfile, uuid, comp)
+ self.gen_vcxproj(target, projfile, uuid)
projlist.append((name, relname, uuid))
return projlist
@@ -430,12 +423,26 @@ class Vs2010Backend(backends.Backend):
pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile')
pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % lang
- def add_additional_options(self, source_file, parent_node, extra_args, has_additional_options_set):
- if has_additional_options_set:
+ def add_additional_options(self, lang, parent_node, file_args):
+ if len(file_args[lang]) == 0:
# We only need per file options if they were not set per project.
return
- lang = Vs2010Backend.lang_from_source_file(source_file)
- ET.SubElement(parent_node, "AdditionalOptions").text = ' '.join(extra_args[lang]) + ' %(AdditionalOptions)'
+ args = file_args[lang] + ['%(AdditionalOptions)']
+ ET.SubElement(parent_node, "AdditionalOptions").text = ' '.join(args)
+
+ def add_preprocessor_defines(self, lang, parent_node, file_defines):
+ if len(file_defines[lang]) == 0:
+ # We only need per file options if they were not set per project.
+ return
+ defines = file_defines[lang] + ['%(PreprocessorDefinitions)']
+ ET.SubElement(parent_node, "PreprocessorDefinitions").text = ';'.join(defines)
+
+ def add_include_dirs(self, lang, parent_node, file_inc_dirs):
+ if len(file_inc_dirs[lang]) == 0:
+ # We only need per file options if they were not set per project.
+ return
+ dirs = file_inc_dirs[lang] + ['%(AdditionalIncludeDirectories)']
+ ET.SubElement(parent_node, "AdditionalIncludeDirectories").text = ';'.join(dirs)
@staticmethod
def has_objects(objects, additional_objects, generated_objects):
@@ -505,7 +512,19 @@ class Vs2010Backend(backends.Backend):
other.append(arg)
return (lpaths, libs, other)
- def gen_vcxproj(self, target, ofname, guid, compiler):
+ def _get_cl_compiler(self, target):
+ for lang, c in target.compilers.items():
+ if lang in ('c', 'cpp'):
+ return c
+ # No source files, only objects, but we still need a compiler, so
+ # return a found compiler
+ if len(target.objects) > 0:
+ for lang, c in self.environment.coredata.compilers.items():
+ if lang in ('c', 'cpp'):
+ return c
+ raise MesonException('Could not find a C or C++ compiler. MSVC can only build C/C++ projects.')
+
+ def gen_vcxproj(self, target, ofname, guid):
mlog.debug('Generating vcxproj %s.' % target.name)
entrypoint = 'WinMainCRTStartup'
subsystem = 'Windows'
@@ -532,6 +551,7 @@ class Vs2010Backend(backends.Backend):
# Prefix to use to access the source tree's subdir from the vcxproj dir
proj_to_src_dir = os.path.join(proj_to_src_root, target.subdir)
(sources, headers, objects, languages) = self.split_sources(target.sources)
+ compiler = self._get_cl_compiler(target)
buildtype_args = compiler.get_buildtype_args(self.buildtype)
buildtype_link_args = compiler.get_buildtype_linker_args(self.buildtype)
project_name = target.name
@@ -643,83 +663,86 @@ class Vs2010Backend(backends.Backend):
# Build information
compiles = ET.SubElement(root, 'ItemDefinitionGroup')
clconf = ET.SubElement(compiles, 'ClCompile')
- inc_dirs = ['.', self.relpath(self.get_target_private_dir(target), self.get_target_dir(target)),
- proj_to_src_dir] + generated_files_include_dirs
-
- extra_args = {'c': [], 'cpp': []}
+ # Arguments, include dirs, defines for all files in the current target
+ target_args = []
+ target_defines = []
+ target_inc_dirs = ['.', self.relpath(self.get_target_private_dir(target),
+ self.get_target_dir(target)),
+ proj_to_src_dir] + generated_files_include_dirs
+ # Arguments, include dirs, defines passed to individual files in
+ # a target; perhaps because the args are language-specific
+ file_args = dict((lang, []) for lang in target.compilers)
+ file_defines = dict((lang, []) for lang in target.compilers)
+ file_inc_dirs = dict((lang, []) for lang in target.compilers)
for l, args in self.environment.coredata.external_args.items():
- if l in extra_args:
- extra_args[l] += args
+ if l in file_args:
+ file_args[l] += args
for l, args in self.build.global_args.items():
- if l in extra_args:
- extra_args[l] += args
+ if l in file_args:
+ file_args[l] += args
for l, args in target.extra_args.items():
- if l in extra_args:
- extra_args[l] += compiler.unix_compile_flags_to_native(args)
- # FIXME all the internal flags of VS (optimization etc) are represented
- # by their own XML elements. In theory we should split all flags to those
- # that have an XML element and those that don't and serialise them
- # properly. This is a crapton of work for no real gain, so just dump them
- # here.
- general_args = compiler.get_option_compile_args(self.environment.coredata.compiler_options)
+ if l in file_args:
+ file_args[l] += compiler.unix_compile_flags_to_native(args)
+ for l, comp in target.compilers.items():
+ if l in file_args:
+ file_args[l] += comp.get_option_compile_args(self.environment.coredata.compiler_options)
for d in target.get_external_deps():
# Cflags required by external deps might have UNIX-specific flags,
# so filter them out if needed
d_compile_args = compiler.unix_compile_flags_to_native(d.get_compile_args())
for arg in d_compile_args:
- if arg.startswith('-I') or arg.startswith('/I'):
+ if arg.startswith(('-D', '/D')):
+ define = arg[2:]
+ # De-dup
+ if define not in target_defines:
+ target_defines.append(define)
+ elif arg.startswith(('-I', '/I')):
inc_dir = arg[2:]
# De-dup
- if inc_dir not in inc_dirs:
- inc_dirs.append(inc_dir)
+ if inc_dir not in target_inc_dirs:
+ target_inc_dirs.append(inc_dir)
else:
- general_args.append(arg)
+ # De-dup
+ if arg not in target_args:
+ target_args.append(arg)
- defines = []
# Split preprocessor defines and include directories out of the list of
# all extra arguments. The rest go into %(AdditionalOptions).
- for l, args in extra_args.items():
- extra_args[l] = []
+ for l, args in file_args.items():
+ file_args[l] = []
for arg in args:
- if arg.startswith('-D') or arg.startswith('/D'):
+ if arg.startswith(('-D', '/D')):
define = self.escape_preprocessor_define(arg[2:])
# De-dup
- if define not in defines:
- defines.append(define)
- elif arg.startswith('-I') or arg.startswith('/I'):
+ if define not in file_defines[l]:
+ file_defines[l].append(define)
+ elif arg.startswith(('-I', '/I')):
inc_dir = arg[2:]
# De-dup
- if inc_dir not in inc_dirs:
- inc_dirs.append(inc_dir)
+ if inc_dir not in file_inc_dirs[l]:
+ file_inc_dirs[l].append(inc_dir)
else:
- extra_args[l].append(self.escape_additional_option(arg))
+ file_args[l].append(self.escape_additional_option(arg))
languages += gen_langs
- has_language_specific_args = any(l != extra_args['c'] for l in extra_args.values())
- additional_options_set = False
- if not has_language_specific_args or len(languages) == 1:
- if len(languages) == 0:
- extra_args = []
- else:
- extra_args = extra_args[languages[0]]
- extra_args = general_args + extra_args
- if len(extra_args) > 0:
- extra_args.append('%(AdditionalOptions)')
- ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(extra_args)
- additional_options_set = True
+ if len(target_args) > 0:
+ target_args.append('%(AdditionalOptions)')
+ ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(target_args)
+ additional_options_set = True
for d in target.include_dirs:
for i in d.incdirs:
curdir = os.path.join(d.curdir, i)
- inc_dirs.append(self.relpath(curdir, target.subdir)) # build dir
- inc_dirs.append(os.path.join(proj_to_src_root, curdir)) # src dir
+ target_inc_dirs.append(self.relpath(curdir, target.subdir)) # build dir
+ target_inc_dirs.append(os.path.join(proj_to_src_root, curdir)) # src dir
for i in d.get_extra_build_dirs():
curdir = os.path.join(d.curdir, i)
- inc_dirs.append(self.relpath(curdir, target.subdir)) # build dir
+ target_inc_dirs.append(self.relpath(curdir, target.subdir)) # build dir
- inc_dirs.append('%(AdditionalIncludeDirectories)')
- ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(inc_dirs)
- ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(defines)
+ target_inc_dirs.append('%(AdditionalIncludeDirectories)')
+ ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(target_inc_dirs)
+ target_defines.append('%(PreprocessorDefinitions)')
+ ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(target_defines)
rebuild = ET.SubElement(clconf, 'MinimalRebuild')
rebuild.text = 'true'
funclink = ET.SubElement(clconf, 'FunctionLevelLinking')
@@ -834,19 +857,26 @@ class Vs2010Backend(backends.Backend):
for s in sources:
relpath = os.path.join(down, s.rel_to_builddir(self.build_to_src))
inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath)
+ lang = Vs2010Backend.lang_from_source_file(s)
self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s)
- self.add_additional_options(s, inc_cl, extra_args, additional_options_set)
+ self.add_additional_options(lang, inc_cl, file_args)
+ self.add_preprocessor_defines(lang, inc_cl, file_defines)
+ self.add_include_dirs(lang, inc_cl, file_inc_dirs)
basename = os.path.basename(s.fname)
if basename in self.sources_conflicts[target.get_id()]:
ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + self.object_filename_from_source(target, s)
for s in gen_src:
inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s)
+ lang = Vs2010Backend.lang_from_source_file(s)
self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s)
- self.add_additional_options(s, inc_cl, extra_args, additional_options_set)
+ self.add_additional_options(lang, inc_cl, file_args)
+ self.add_preprocessor_defines(lang, inc_cl, file_defines)
+ self.add_include_dirs(lang, inc_cl, file_inc_dirs)
for lang in pch_sources:
header, impl, suffix = pch_sources[lang]
relpath = os.path.join(proj_to_src_dir, impl)
inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath)
+ lang = Vs2010Backend.lang_from_source_file(s)
pch = ET.SubElement(inc_cl, 'PrecompiledHeader')
pch.text = 'Create'
pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile')
@@ -855,7 +885,9 @@ class Vs2010Backend(backends.Backend):
# MSBuild searches for the header relative from the implementation, so we have to use
# just the file name instead of the relative path to the file.
pch_file.text = os.path.split(header)[1]
- self.add_additional_options(impl, inc_cl, extra_args, additional_options_set)
+ self.add_additional_options(lang, inc_cl, file_args)
+ self.add_preprocessor_defines(lang, inc_cl, file_defines)
+ self.add_include_dirs(lang, inc_cl, file_inc_dirs)
if self.has_objects(objects, additional_objects, gen_objs):
inc_objs = ET.SubElement(root, 'ItemGroup')
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index c3867e0..d87d9a0 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -309,8 +309,8 @@ class BuildTarget():
if not k in known_kwargs:
unknowns.append(k)
if len(unknowns) > 0:
- mlog.log(mlog.bold('Warning:'), 'Unknown keyword argument(s) in target %s: %s.' %
- (self.name, ', '.join(unknowns)))
+ mlog.warning('Unknown keyword argument(s) in target %s: %s.' %
+ (self.name, ', '.join(unknowns)))
def process_objectlist(self, objects):
assert(isinstance(objects, list))
@@ -583,7 +583,7 @@ class BuildTarget():
if for_darwin(self.is_cross, self.environment) or for_windows(self.is_cross, self.environment):
self.pic = True
elif '-fPIC' in clist + cpplist:
- mlog.log(mlog.red('WARNING:'), "Use the 'pic' kwarg instead of passing -fPIC manually to static library {!r}".format(self.name))
+ mlog.warning("Use the 'pic' kwarg instead of passing -fPIC manually to static library {!r}".format(self.name))
self.pic = True
else:
self.pic = kwargs.get('pic', False)
@@ -1139,8 +1139,8 @@ class CustomTarget:
if k not in CustomTarget.known_kwargs:
unknowns.append(k)
if len(unknowns) > 0:
- mlog.log(mlog.bold('Warning:'), 'Unknown keyword arguments in target %s: %s' %
- (self.name, ', '.join(unknowns)))
+ mlog.warning('Unknown keyword arguments in target %s: %s' %
+ (self.name, ', '.join(unknowns)))
def __repr__(self):
repr_str = "<{0} {1}: {2}>"
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index 94e8a54..bbe6a72 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import shutil
import contextlib
import subprocess, os.path
import tempfile
@@ -434,7 +435,7 @@ class Compiler():
# Some compilers (msvc) write debug info to a separate file.
# These args specify where it should be written.
- def get_compile_debugfile_args(self, rel_obj):
+ def get_compile_debugfile_args(self, rel_obj, **kwargs):
return []
def get_link_debugfile_args(self, rel_obj):
@@ -512,6 +513,13 @@ class CCompiler(Compiler):
def get_no_optimization_args(self):
return ['-O0']
+ def get_compiler_check_args(self):
+ '''
+ Get arguments useful for compiler checks such as being permissive in
+ the code quality and not doing any optimization.
+ '''
+ return self.get_no_optimization_args()
+
def get_output_args(self, target):
return ['-o', target]
@@ -643,9 +651,14 @@ int someSymbolHereJustForFun;
extra_args = []
templ = '''{2}
#include <{0}>
-int main () {{ {1}; }}'''
- # Pass -O0 to ensure that the symbol isn't optimized away
- args = extra_args + self.get_no_optimization_args()
+int main () {{
+ /* If it's not defined as a macro, try to use as a symbol */
+ #ifndef {1}
+ {1};
+ #endif
+ return 0;
+}}'''
+ args = extra_args + self.get_compiler_check_args()
return self.compiles(templ.format(hname, symbol, prefix), env, args, dependencies)
@contextlib.contextmanager
@@ -784,7 +797,7 @@ int main(int argc, char **argv) {{
%s
int temparray[%d-sizeof(%s)];
'''
- args = extra_args + self.get_no_optimization_args()
+ args = extra_args + self.get_compiler_check_args()
if not self.compiles(element_exists_templ.format(prefix, element), env, args, dependencies):
return -1
for i in range(1, 1024):
@@ -833,7 +846,7 @@ struct tmp {
int testarray[%d-offsetof(struct tmp, target)];
'''
- args = extra_args + self.get_no_optimization_args()
+ args = extra_args + self.get_compiler_check_args()
if not self.compiles(type_exists_templ.format(typename), env, args, dependencies):
return -1
for i in range(1, 1024):
@@ -918,7 +931,7 @@ int main(int argc, char **argv) {
head = '#include <limits.h>\n{0}\n'
# We don't know what the function takes or returns, so try to use it as
# a function pointer
- main = '\nint main() {{ int a = (int) &{1}; }}'
+ main = '\nint main() {{ void *a = (void*) &{1}; }}'
return head, main
def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None):
@@ -967,9 +980,8 @@ int main(int argc, char **argv) {
head, main = self._no_prototype_templ()
templ = head + stubs_fail + main
- # Add -O0 to ensure that the symbol isn't optimized away by the compiler
- args = extra_args + self.get_no_optimization_args()
- if self.links(templ.format(prefix, funcname), env, extra_args, dependencies):
+ args = extra_args + self.get_compiler_check_args()
+ if self.links(templ.format(prefix, funcname), env, args, dependencies):
return True
# Some functions like alloca() are defined as compiler built-ins which
# are inlined by the compiler, so test for that instead. Built-ins are
@@ -1048,6 +1060,20 @@ class CPPCompiler(CCompiler):
code = 'class breakCCompiler;int main(int argc, char **argv) { return 0; }\n'
return self.sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code)
+ def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None):
+ # Check if it's a C-like symbol
+ if super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies):
+ return True
+ # Check if it's a class or a template
+ if extra_args is None:
+ extra_args = []
+ templ = '''{2}
+#include <{0}>
+using {1};
+int main () {{ return 0; }}'''
+ args = extra_args + self.get_compiler_check_args()
+ return self.compiles(templ.format(hname, symbol, prefix), env, args, dependencies)
+
class ObjCCompiler(CCompiler):
def __init__(self, exelist, version, is_cross, exe_wrap):
self.language = 'objc'
@@ -1274,11 +1300,20 @@ class JavaCompiler(Compiler):
pc.wait()
if pc.returncode != 0:
raise EnvironmentException('Java compiler %s can not compile programs.' % self.name_string())
- cmdlist = [self.javarunner, obj]
- pe = subprocess.Popen(cmdlist, cwd=work_dir)
- pe.wait()
- if pe.returncode != 0:
- raise EnvironmentException('Executables created by Java compiler %s are not runnable.' % self.name_string())
+ runner = shutil.which(self.javarunner)
+ if runner:
+ cmdlist = [runner, obj]
+ pe = subprocess.Popen(cmdlist, cwd=work_dir)
+ pe.wait()
+ if pe.returncode != 0:
+ raise EnvironmentException('Executables created by Java compiler %s are not runnable.' % self.name_string())
+ else:
+ m = "Java Virtual Machine wasn't found, but it's needed by Meson. " \
+ "Please install a JRE.\nIf you have specific needs where this " \
+ "requirement doesn't make sense, please open a bug at " \
+ "https://github.com/mesonbuild/meson/issues/new and tell us " \
+ "all about it."
+ raise EnvironmentException(m)
def needs_static_linker(self):
return False
@@ -1848,19 +1883,29 @@ class VisualStudioCCompiler(CCompiler):
raise MesonException('Compiling test app failed.')
return not(warning_text in stde or warning_text in stdo)
- def get_compile_debugfile_args(self, rel_obj):
+ def get_compile_debugfile_args(self, rel_obj, pch=False):
pdbarr = rel_obj.split('.')[:-1]
pdbarr += ['pdb']
- return ['/Fd' + '.'.join(pdbarr)]
+ args = ['/Fd' + '.'.join(pdbarr)]
+ # When generating a PDB file with PCH, all compile commands write
+ # to the same PDB file. Hence, we need to serialize the PDB
+ # writes using /FS since we do parallel builds. This slows down the
+ # build obviously, which is why we only do this when PCH is on.
+ # This was added in Visual Studio 2013 (MSVC 18.0). Before that it was
+ # always on: https://msdn.microsoft.com/en-us/library/dn502518.aspx
+ if pch and mesonlib.version_compare(self.version, '>=18.0'):
+ args = ['/FS'] + args
+ return args
def get_link_debugfile_args(self, targetfile):
pdbarr = targetfile.split('.')[:-1]
pdbarr += ['pdb']
return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)]
-class VisualStudioCPPCompiler(VisualStudioCCompiler):
+class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler):
def __init__(self, exelist, version, is_cross, exe_wrap):
self.language = 'cpp'
+ CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
self.base_options = ['b_pch'] # FIXME add lto, pgo and the like
@@ -2035,6 +2080,12 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
return options['cpp_winlibs'].value
return []
+ def get_compiler_check_args(self):
+ # -fpermissive allows non-conforming code to compile which is necessary
+ # for many C++ checks. Particularly, the has_header_symbol check is
+ # too strict without this and always fails.
+ return self.get_no_optimization_args() + ['-fpermissive']
+
class GnuObjCCompiler(GnuCompiler,ObjCCompiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None, defines=None):
@@ -2057,6 +2108,12 @@ class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
'2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'],
'3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']}
+ def get_compiler_check_args(self):
+ # -fpermissive allows non-conforming code to compile which is necessary
+ # for many ObjC++ checks. Particularly, the has_header_symbol check is
+ # too strict without this and always fails.
+ return self.get_no_optimization_args() + ['-fpermissive']
+
class ClangCompiler():
def __init__(self, clang_type):
self.id = 'clang'
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index c8ee13f..fad39e6 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -247,4 +247,5 @@ forbidden_target_names = {'clean': None,
'install': None,
'build.ninja': None,
'scan-build': None,
+ 'reconfigure': None,
}
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index f7045f4..405685c 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -331,6 +331,13 @@ class Environment():
if len(rest) == 2:
defines[rest[0]] = rest[1]
return defines
+ @staticmethod
+ def get_gnu_version_from_defines(defines):
+ dot = '.'
+ major = defines.get('__GNUC__', '0')
+ minor = defines.get('__GNUC_MINOR__', '0')
+ patch = defines.get('__GNUC_PATCHLEVEL__', '0')
+ return dot.join((major, minor, patch))
@staticmethod
def get_gnu_compiler_type(defines):
@@ -385,6 +392,7 @@ class Environment():
popen_exceptions[compiler] = 'no pre-processor defines'
continue
gtype = self.get_gnu_compiler_type(defines)
+ version = self.get_gnu_version_from_defines(defines)
return GnuCCompiler(ccache + [compiler], version, gtype, is_cross, exe_wrap, defines)
if 'clang' in out:
if 'Apple' in out:
@@ -443,6 +451,7 @@ class Environment():
popen_exceptions[compiler] = 'no pre-processor defines'
continue
gtype = self.get_gnu_compiler_type(defines)
+ version = self.get_gnu_version_from_defines(defines)
return GnuFortranCompiler([compiler], version, gtype, is_cross, exe_wrap, defines)
if 'G95' in out:
@@ -524,6 +533,7 @@ class Environment():
popen_exceptions[compiler] = 'no pre-processor defines'
continue
gtype = self.get_gnu_compiler_type(defines)
+ version = self.get_gnu_version_from_defines(defines)
return GnuCPPCompiler(ccache + [compiler], version, gtype, is_cross, exe_wrap, defines)
if 'clang' in out:
if 'Apple' in out:
@@ -563,6 +573,7 @@ class Environment():
version = search_version(out)
if 'Free Software Foundation' in out:
defines = self.get_gnu_compiler_defines(exelist)
+ version = self.get_gnu_version_from_defines(defines)
return GnuObjCCompiler(exelist, version, is_cross, exe_wrap, defines)
if out.startswith('Apple LLVM'):
return ClangObjCCompiler(exelist, version, CLANG_OSX, is_cross, exe_wrap)
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 3dc0c99..7b1cb52 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -981,6 +981,8 @@ class ModuleHolder(InterpreterObject):
fn = getattr(self.held_object, method_name)
except AttributeError:
raise InvalidArguments('Module %s does not have method %s.' % (self.modname, method_name))
+ if method_name.startswith('_'):
+ raise InvalidArguments('Function {!r} in module {!r} is private.'.format(method_name, self.modname))
state = ModuleState()
state.build_to_src = os.path.relpath(self.interpreter.environment.get_source_dir(),
self.interpreter.environment.get_build_dir())
@@ -1555,7 +1557,7 @@ class Interpreter():
if dirname in self.subproject_stack:
fullstack = self.subproject_stack + [dirname]
incpath = ' => '.join(fullstack)
- raise InterpreterException('Recursive include of subprojects: %s.' % incpath)
+ raise InvalidCode('Recursive include of subprojects: %s.' % incpath)
if dirname in self.subprojects:
return self.subprojects[dirname]
r = wrap.Resolver(os.path.join(self.build.environment.get_source_dir(), self.subproject_dir))
@@ -1856,12 +1858,10 @@ requirements use the version keyword argument instead.''')
# Cached dep has the wrong version. Check if an external
# dependency or a fallback dependency provides it.
cached_dep = None
-
# Don't re-use cached dep if it wasn't required but this one is,
# so we properly go into fallback/error code paths
- if 'required' in kwargs and cached_dep is not None:
- if not cached_dep.required and kwargs.get('required', True):
- cached_dep = None
+ if kwargs.get('required', True) and not getattr(cached_dep, 'required', False):
+ cached_dep = None
if cached_dep:
dep = cached_dep
@@ -1908,8 +1908,14 @@ requirements use the version keyword argument instead.''')
def dependency_fallback(self, name, kwargs):
dirname, varname = self.get_subproject_infos(kwargs)
+ # Try to execute the subproject
try:
self.do_subproject(dirname, {})
+ # Invalid code is always an error
+ except InvalidCode:
+ raise
+ # If the subproject execution failed in a non-fatal way, don't raise an
+ # exception; let the caller handle things.
except:
mlog.log('Also couldn\'t find a fallback subproject in',
mlog.bold(os.path.join(self.subproject_dir, dirname)),
@@ -1918,13 +1924,11 @@ requirements use the version keyword argument instead.''')
try:
dep = self.subprojects[dirname].get_variable_method([varname], {})
except KeyError:
- mlog.log('Fallback variable', mlog.bold(varname),
- 'in the subproject', mlog.bold(dirname), 'does not exist')
- return None
+ raise InvalidCode('Fallback variable {!r} in the subproject '
+ '{!r} does not exist'.format(varname, dirname))
if not isinstance(dep, DependencyHolder):
- mlog.log('Fallback variable', mlog.bold(varname),
- 'in the subproject', mlog.bold(dirname),
- 'is not a dependency object.')
+ raise InvalidCode('Fallback variable {!r} in the subproject {!r} is '
+ 'not a dependency object.'.format(varname, dirname))
return None
# Check if the version of the declared dependency matches what we want
if 'version' in kwargs:
@@ -2173,10 +2177,7 @@ requirements use the version keyword argument instead.''')
% subdir)
self.visited_subdirs[subdir] = True
self.subdir = subdir
- try:
- os.makedirs(os.path.join(self.environment.build_dir, subdir))
- except FileExistsError:
- pass
+ os.makedirs(os.path.join(self.environment.build_dir, subdir), exist_ok=True)
buildfilename = os.path.join(self.subdir, environment.build_filename)
self.build_def_files.append(buildfilename)
absname = os.path.join(self.environment.get_source_dir(), buildfilename)
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 943c087..88826f8 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -89,6 +89,10 @@ class MesonApp():
def validate_core_dirs(self, dir1, dir2):
ndir1 = os.path.abspath(dir1)
ndir2 = os.path.abspath(dir2)
+ if not os.path.exists(ndir1):
+ os.makedirs(ndir1)
+ if not os.path.exists(ndir2):
+ os.makedirs(ndir2)
if not stat.S_ISDIR(os.stat(ndir1).st_mode):
raise RuntimeError('%s is not a directory' % dir1)
if not stat.S_ISDIR(os.stat(ndir2).st_mode):
@@ -121,8 +125,8 @@ itself as required.'''
def check_pkgconfig_envvar(self, env):
curvar = os.environ.get('PKG_CONFIG_PATH', '')
if curvar != env.coredata.pkgconf_envvar:
- mlog.log(mlog.red("WARNING:"), 'PKG_CONFIG_PATH has changed between invocations from "%s" to "%s".' %
- (env.coredata.pkgconf_envvar, curvar))
+ mlog.warning('PKG_CONFIG_PATH has changed between invocations from "%s" to "%s".' %
+ (env.coredata.pkgconf_envvar, curvar))
env.coredata.pkgconf_envvar = curvar
def generate(self):
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
index dab51bd..cded2b0 100644
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -53,6 +53,9 @@ def red(text):
def green(text):
return AnsiDecorator(text, "\033[1;32m")
+def yellow(text):
+ return AnsiDecorator(text, "\033[1;33m")
+
def cyan(text):
return AnsiDecorator(text, "\033[1;36m")
@@ -81,3 +84,6 @@ def log(*args, **kwargs):
if colorize_console:
arr = process_markup(args, True)
print(*arr, **kwargs)
+
+def warning(*args, **kwargs):
+ log(yellow('WARNING:'), *args, **kwargs)
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index b7d1438..f3f22bc 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -18,6 +18,7 @@ functionality such as gobject-introspection and gresources.'''
from .. import build
import os
import sys
+import copy
import subprocess
from ..mesonlib import MesonException
from .. import dependencies
@@ -31,7 +32,8 @@ gresource_warning_printed = False
class GnomeModule:
- def get_native_glib_version(self, state):
+ @staticmethod
+ def _get_native_glib_version(state):
global native_glib_version
if native_glib_version is None:
glib_dep = dependencies.PkgConfigDependency(
@@ -42,11 +44,11 @@ class GnomeModule:
def __print_gresources_warning(self, state):
global gresource_warning_printed
if not gresource_warning_printed:
- if mesonlib.version_compare(self.get_native_glib_version(state), '< 2.50.0'):
- mlog.log('Warning, GLib compiled dependencies do not work fully '
- 'with versions of GLib older than 2.50.0.\n'
- 'See the following upstream issue:',
- mlog.bold('https://bugzilla.gnome.org/show_bug.cgi?id=745754'))
+ if mesonlib.version_compare(self._get_native_glib_version(state), '< 2.50.2'):
+ mlog.warning('GLib compiled dependencies do not work fully '
+ 'with versions of GLib older than 2.50.2.\n'
+ 'See the following upstream issue:',
+ mlog.bold('https://bugzilla.gnome.org/show_bug.cgi?id=745754'))
gresource_warning_printed = True
return []
@@ -59,9 +61,6 @@ class GnomeModule:
if not isinstance(source_dirs, list):
source_dirs = [source_dirs]
- # Always include current directory, but after paths set by user
- source_dirs.append(os.path.join(state.environment.get_source_dir(), state.subdir))
-
if len(args) < 2:
raise MesonException('Not enough arguments; The name of the resource and the path to the XML file are required')
@@ -69,8 +68,8 @@ class GnomeModule:
if not isinstance(dependencies, list):
dependencies = [dependencies]
- if mesonlib.version_compare(self.get_native_glib_version(state),
- '< 2.48.2'):
+ glib_version = self._get_native_glib_version(state)
+ if mesonlib.version_compare(glib_version, '< 2.48.2'):
if len(dependencies) > 0:
raise MesonException(
'The "dependencies" argument of gnome.compile_resources() '
@@ -86,18 +85,18 @@ class GnomeModule:
else:
raise RuntimeError('Unreachable code.')
- kwargs['depend_files'] = self.get_gresource_dependencies(
+ depend_files, depends, subdirs = self._get_gresource_dependencies(
state, ifile, source_dirs, dependencies)
- for source_dir in source_dirs:
- sourcedir = os.path.join(state.build_to_src, state.subdir, source_dir)
- cmd += ['--sourcedir', sourcedir]
+ # Make source dirs relative to build dir now
+ source_dirs = [os.path.join(state.build_to_src, state.subdir, d) for d in source_dirs]
+ # Always include current directory, but after paths set by user
+ source_dirs.append(os.path.join(state.build_to_src, state.subdir))
+ # Ensure build directories of generated deps are included
+ source_dirs += subdirs
- if len(dependencies) > 0:
- # Add the build variant of each sourcedir if we have any
- # generated dependencies.
- sourcedir = os.path.join(state.subdir, source_dir)
- cmd += ['--sourcedir', sourcedir]
+ for source_dir in set(source_dirs):
+ cmd += ['--sourcedir', source_dir]
if 'c_name' in kwargs:
cmd += ['--c-name', kwargs.pop('c_name')]
@@ -105,17 +104,30 @@ class GnomeModule:
cmd += mesonlib.stringlistify(kwargs.pop('extra_args', []))
- kwargs['command'] = cmd
kwargs['input'] = args[1]
kwargs['output'] = args[0] + '.c'
+ kwargs['depends'] = depends
+ if mesonlib.version_compare(glib_version, '< 2.50.2'):
+ # This will eventually go out of sync if dependencies are added
+ kwargs['depend_files'] = depend_files
+ kwargs['command'] = cmd
+ else:
+ depfile = kwargs['output'] + '.d'
+ kwargs['depfile'] = depfile
+ kwargs['command'] = copy.copy(cmd) + ['--dependency-file', '@DEPFILE@']
target_c = build.CustomTarget(args[0] + '_c', state.subdir, kwargs)
- kwargs['output'] = args[0] + '.h'
- target_h = build.CustomTarget(args[0] + '_h', state.subdir, kwargs)
- return [target_c, target_h]
- def get_gresource_dependencies(self, state, input_file, source_dirs, dependencies):
- self.__print_gresources_warning(state)
+ h_kwargs = {
+ 'command': cmd,
+ 'input': args[1],
+ 'output': args[0] + '.h',
+ # The header doesn't actually care about the files yet it errors if missing
+ 'depends': depends
+ }
+ target_h = build.CustomTarget(args[0] + '_h', state.subdir, h_kwargs)
+ return [target_c, target_h]
+ def _get_gresource_dependencies(self, state, input_file, source_dirs, dependencies):
for dep in dependencies:
if not isinstance(dep, interpreter.CustomTargetHolder) and not \
isinstance(dep, mesonlib.File):
@@ -130,12 +142,13 @@ class GnomeModule:
for source_dir in source_dirs:
cmd += ['--sourcedir', os.path.join(state.subdir, source_dir)]
+ cmd += ['--sourcedir', state.subdir] # Current dir
pc = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True,
cwd=state.environment.get_source_dir())
(stdout, _) = pc.communicate()
if pc.returncode != 0:
- mlog.log(mlog.bold('Warning:'), 'glib-compile-resources has failed to get the dependencies for {}'.format(cmd[1]))
+ mlog.warning('glib-compile-resources has failed to get the dependencies for {}'.format(cmd[1]))
raise subprocess.CalledProcessError(pc.returncode, cmd)
dep_files = stdout.split('\n')[:-1]
@@ -153,6 +166,8 @@ class GnomeModule:
return os.path.exists(os.path.join(state.environment.get_source_dir(), f))
missing_dep_files = [f for f in dep_files if not exists_in_srcdir(f)]
+ depends = []
+ subdirs = []
for missing in missing_dep_files:
found = False
missing_basename = os.path.basename(missing)
@@ -163,6 +178,7 @@ class GnomeModule:
found = True
dep_files.remove(missing)
dep_files.append(dep)
+ subdirs.append(dep.subdir)
break
elif isinstance(dep, interpreter.CustomTargetHolder):
if dep.held_object.get_basename() == missing_basename:
@@ -173,6 +189,8 @@ class GnomeModule:
is_built=True,
subdir=dep.held_object.get_subdir(),
fname=dep.held_object.get_basename()))
+ depends.append(dep.held_object)
+ subdirs.append(dep.held_object.get_subdir())
break
if not found:
@@ -182,9 +200,10 @@ class GnomeModule:
'gnome.compile_resources() using the "dependencies" '
'keyword argument.' % (missing, input_file))
- return dep_files
+ return dep_files, depends, subdirs
- def get_link_args(self, state, lib, depends=None):
+ @staticmethod
+ def _get_link_args(state, lib, depends=None):
link_command = ['-l%s' % lib.name]
if isinstance(lib, build.SharedLibrary):
link_command += ['-L%s' %
@@ -194,7 +213,8 @@ class GnomeModule:
depends.append(lib)
return link_command
- def get_include_args(self, state, include_dirs, prefix='-I'):
+ @staticmethod
+ def _get_include_args(state, include_dirs, prefix='-I'):
if not include_dirs:
return []
@@ -222,7 +242,7 @@ class GnomeModule:
return dirs_str
- def get_dependencies_flags(self, deps, state, depends=None):
+ def _get_dependencies_flags(self, deps, state, depends=None):
cflags = set()
ldflags = set()
gi_includes = set()
@@ -233,14 +253,14 @@ class GnomeModule:
if hasattr(dep, 'held_object'):
dep = dep.held_object
if isinstance(dep, dependencies.InternalDependency):
- cflags.update(self.get_include_args( state, dep.include_directories))
+ cflags.update(self._get_include_args(state, dep.include_directories))
for lib in dep.libraries:
- ldflags.update(self.get_link_args(state, lib.held_object, depends))
- libdepflags = self.get_dependencies_flags(lib.held_object.get_external_deps(), state, depends)
+ ldflags.update(self._get_link_args(state, lib.held_object, depends))
+ libdepflags = self._get_dependencies_flags(lib.held_object.get_external_deps(), state, depends)
cflags.update(libdepflags[0])
ldflags.update(libdepflags[1])
gi_includes.update(libdepflags[2])
- extdepflags = self.get_dependencies_flags(dep.ext_deps, state, depends)
+ extdepflags = self._get_dependencies_flags(dep.ext_deps, state, depends)
cflags.update(extdepflags[0])
ldflags.update(extdepflags[1])
gi_includes.update(extdepflags[2])
@@ -294,7 +314,7 @@ class GnomeModule:
except Exception:
global girwarning_printed
if not girwarning_printed:
- mlog.log(mlog.bold('Warning:'), 'gobject-introspection dependency was not found, disabling gir generation.')
+ mlog.warning('gobject-introspection dependency was not found, disabling gir generation.')
girwarning_printed = True
return []
pkgargs = pkgstr.decode().strip().split()
@@ -314,14 +334,14 @@ class GnomeModule:
scan_command += extra_args
scan_command += ['-I' + os.path.join(state.environment.get_source_dir(), state.subdir),
'-I' + os.path.join(state.environment.get_build_dir(), state.subdir)]
- scan_command += self.get_include_args(state, girtarget.get_include_dirs())
+ scan_command += self._get_include_args(state, girtarget.get_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:
- scan_command += self.get_link_args(state, link.held_object, depends)
+ scan_command += self._get_link_args(state, link.held_object, depends)
if 'includes' in kwargs:
includes = kwargs.pop('includes')
@@ -384,7 +404,7 @@ class GnomeModule:
# ldflags will be misinterpreted by gir scanner (showing
# spurious dependencies) but building GStreamer fails if they
# are not used here.
- cflags, ldflags, gi_includes = self.get_dependencies_flags(deps, state, depends)
+ cflags, ldflags, gi_includes = self._get_dependencies_flags(deps, state, depends)
scan_command += list(cflags) + list(ldflags)
for i in gi_includes:
scan_command += ['--add-include-path=%s' % i]
@@ -396,9 +416,9 @@ class GnomeModule:
if not isinstance(incd.held_object, (str, build.IncludeDirs)):
raise MesonException(
'Gir include dirs should be include_directories().')
- scan_command += self.get_include_args(state, inc_dirs)
- scan_command += self.get_include_args(state, gir_inc_dirs + inc_dirs,
- prefix='--add-include-path=')
+ scan_command += self._get_include_args(state, inc_dirs)
+ scan_command += self._get_include_args(state, gir_inc_dirs + inc_dirs,
+ prefix='--add-include-path=')
if isinstance(girtarget, build.Executable):
scan_command += ['--program', girtarget]
@@ -419,8 +439,8 @@ class GnomeModule:
typelib_output = '%s-%s.typelib' % (ns, nsversion)
typelib_cmd = ['g-ir-compiler', scan_target, '--output', '@OUTPUT@']
- typelib_cmd += self.get_include_args(state, gir_inc_dirs,
- prefix='--includedir=')
+ typelib_cmd += self._get_include_args(state, gir_inc_dirs,
+ prefix='--includedir=')
for dep in deps:
if hasattr(dep, 'held_object'):
dep = dep.held_object
@@ -561,24 +581,24 @@ class GnomeModule:
'--headerdir=' + header_dir,
'--mainfile=' + main_file,
'--modulename=' + modulename]
- args += self.unpack_args('--htmlargs=', 'html_args', kwargs)
- args += self.unpack_args('--scanargs=', 'scan_args', kwargs)
- args += self.unpack_args('--scanobjsargs=', 'scanobjs_args', kwargs)
- args += self.unpack_args('--gobjects-types-file=', 'gobject_typesfile', kwargs, state)
- args += self.unpack_args('--fixxrefargs=', 'fixxref_args', kwargs)
- args += self.unpack_args('--html-assets=', 'html_assets', kwargs, state)
- args += self.unpack_args('--content-files=', 'content_files', kwargs, state)
- args += self.unpack_args('--ignore-headers=', 'ignore_headers', kwargs)
- args += self.unpack_args('--installdir=', 'install_dir', kwargs, state)
- args += self.get_build_args(kwargs, state)
+ args += self._unpack_args('--htmlargs=', 'html_args', kwargs)
+ args += self._unpack_args('--scanargs=', 'scan_args', kwargs)
+ args += self._unpack_args('--scanobjsargs=', 'scanobjs_args', kwargs)
+ args += self._unpack_args('--gobjects-types-file=', 'gobject_typesfile', kwargs, state)
+ args += self._unpack_args('--fixxrefargs=', 'fixxref_args', kwargs)
+ args += self._unpack_args('--html-assets=', 'html_assets', kwargs, state)
+ args += self._unpack_args('--content-files=', 'content_files', kwargs, state)
+ args += self._unpack_args('--ignore-headers=', 'ignore_headers', kwargs)
+ args += self._unpack_args('--installdir=', 'install_dir', kwargs, state)
+ args += self._get_build_args(kwargs, state)
res = [build.RunTarget(targetname, command[0], command[1:] + args, [], state.subdir)]
if kwargs.get('install', True):
res.append(build.InstallScript(command + args))
return res
- def get_build_args(self, kwargs, state):
+ def _get_build_args(self, kwargs, state):
args = []
- cflags, ldflags, gi_includes = self.get_dependencies_flags(kwargs.get('dependencies', []), state)
+ cflags, ldflags, gi_includes = self._get_dependencies_flags(kwargs.get('dependencies', []), state)
inc_dirs = kwargs.get('include_directories', [])
if not isinstance(inc_dirs, list):
inc_dirs = [inc_dirs]
@@ -586,7 +606,7 @@ class GnomeModule:
if not isinstance(incd.held_object, (str, build.IncludeDirs)):
raise MesonException(
'Gir include dirs should be include_directories().')
- cflags.update(self.get_include_args(state, inc_dirs))
+ cflags.update(self._get_include_args(state, inc_dirs))
if cflags:
args += ['--cflags=%s' % ' '.join(cflags)]
if ldflags:
@@ -606,8 +626,8 @@ class GnomeModule:
raise MesonException('Argument must be a string')
return os.path.join('share/gtkdoc/html', modulename)
-
- def unpack_args(self, arg, kwarg_name, kwargs, expend_file_state=None):
+ @staticmethod
+ def _unpack_args(arg, kwarg_name, kwargs, expend_file_state=None):
if kwarg_name not in kwargs:
return []
@@ -699,9 +719,9 @@ class GnomeModule:
if 'install_dir' not in custom_kwargs:
custom_kwargs['install_dir'] = \
state.environment.coredata.get_builtin_option('includedir')
- h_target = self.make_mkenum_custom_target(state, h_sources,
- h_output, h_cmd,
- custom_kwargs)
+ h_target = self._make_mkenum_custom_target(state, h_sources,
+ h_output, h_cmd,
+ custom_kwargs)
targets.append(h_target)
if c_template is not None:
@@ -717,9 +737,9 @@ class GnomeModule:
custom_kwargs['depends'] += [h_target]
else:
custom_kwargs['depends'] = h_target
- c_target = self.make_mkenum_custom_target(state, c_sources,
- c_output, c_cmd,
- custom_kwargs)
+ c_target = self._make_mkenum_custom_target(state, c_sources,
+ c_output, c_cmd,
+ custom_kwargs)
targets.insert(0, c_target)
if c_template is None and h_template is None:
@@ -728,15 +748,16 @@ class GnomeModule:
if 'install_dir' not in custom_kwargs:
custom_kwargs['install_dir'] = \
state.environment.coredata.get_builtin_option('includedir')
- target = self.make_mkenum_custom_target(state, sources, basename,
- generic_cmd, custom_kwargs)
+ target = self._make_mkenum_custom_target(state, sources, basename,
+ generic_cmd, custom_kwargs)
return target
elif len(targets) == 1:
return targets[0]
else:
return targets
- def make_mkenum_custom_target(self, state, sources, output, cmd, kwargs):
+ @staticmethod
+ def _make_mkenum_custom_target(state, sources, output, cmd, kwargs):
custom_kwargs = {
'input': sources,
'output': output,
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 7556375..3ecb40d 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -34,7 +34,7 @@ class PkgConfigModule:
return l.name
# In other cases, we can't guarantee that the compiler will be able to
# find the library via '-lfoo', so tell the user that.
- mlog.log(mlog.red('WARNING:'), msg.format(l.name, 'name_prefix', l.name, pcfile))
+ mlog.warning(msg.format(l.name, 'name_prefix', l.name, pcfile))
return l.name
def generate_pkgconfig_file(self, state, libraries, subdirs, name, description,
@@ -79,7 +79,7 @@ class PkgConfigModule:
# If using a custom suffix, the compiler may not be able to
# find the library
if l.name_suffix_set:
- mlog.log(mlog.red('WARNING:'), msg.format(l.name, 'name_suffix', lname, pcfile))
+ mlog.warning(msg.format(l.name, 'name_suffix', lname, pcfile))
yield '-l%s' % lname
if len(libraries) > 0:
ofile.write('Libs: {}\n'.format(' '.join(generate_libs_flags(libraries))))
diff --git a/mesonbuild/modules/qt4.py b/mesonbuild/modules/qt4.py
index 81a70fc..b1d951b 100644
--- a/mesonbuild/modules/qt4.py
+++ b/mesonbuild/modules/qt4.py
@@ -90,7 +90,7 @@ class Qt4Module():
result = []
for child in root[0]:
if child.tag != 'file':
- mlog.log("Warning, malformed rcc file: ", os.path.join(state.subdir, fname))
+ mlog.warning("malformed rcc file: ", os.path.join(state.subdir, fname))
break
else:
result.append(os.path.join(state.subdir, relative_part, child.text))
@@ -150,6 +150,6 @@ class Qt4Module():
return sources
def initialize():
- mlog.log('Warning, rcc dependencies will not work properly until this upstream issue is fixed:',
- mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'))
+ mlog.warning('rcc dependencies will not work properly until this upstream issue is fixed:',
+ mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'))
return Qt4Module()
diff --git a/mesonbuild/modules/qt5.py b/mesonbuild/modules/qt5.py
index 4f19b78..9fffcff 100644
--- a/mesonbuild/modules/qt5.py
+++ b/mesonbuild/modules/qt5.py
@@ -97,7 +97,7 @@ class Qt5Module():
result = []
for child in root[0]:
if child.tag != 'file':
- mlog.log("Warning, malformed rcc file: ", os.path.join(state.subdir, fname))
+ mlog.warning("malformed rcc file: ", os.path.join(state.subdir, fname))
break
else:
result.append(os.path.join(state.subdir, relative_part, child.text))
@@ -160,6 +160,6 @@ class Qt5Module():
return sources
def initialize():
- mlog.log('Warning, rcc dependencies will not work reliably until this upstream issue is fixed:',
- mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'))
+ mlog.warning('rcc dependencies will not work reliably until this upstream issue is fixed:',
+ mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'))
return Qt5Module()
diff --git a/mesonbuild/modules/rpm.py b/mesonbuild/modules/rpm.py
index 13aa20b..2c9ed57 100644
--- a/mesonbuild/modules/rpm.py
+++ b/mesonbuild/modules/rpm.py
@@ -63,8 +63,8 @@ class RPMModule:
so_installed = True
elif isinstance(target, build.StaticLibrary) and target.need_install:
to_delete.add('%%{buildroot}%%{_libdir}/%s' % target.get_filename())
- mlog.log('Warning, removing', mlog.bold(target.get_filename()),
- 'from package because packaging static libs not recommended')
+ mlog.warning('removing', mlog.bold(target.get_filename()),
+ 'from package because packaging static libs not recommended')
elif isinstance(target, gnome.GirTarget) and target.should_install():
files_devel.add('%%{_datadir}/gir-1.0/%s' % target.get_filename()[0])
elif isinstance(target, gnome.TypelibTarget) and target.should_install():
@@ -94,14 +94,13 @@ class RPMModule:
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)
+ fn.write('BuildRequires: pkgconfig(%s)\n' % dep[0])
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))
+ mlog.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: %{_bindir}/%s # FIXME\n' %
diff --git a/mesonbuild/scripts/regen_checker.py b/mesonbuild/scripts/regen_checker.py
index ddf4943..e8e1077 100755
--- a/mesonbuild/scripts/regen_checker.py
+++ b/mesonbuild/scripts/regen_checker.py
@@ -52,7 +52,7 @@ def run(args):
regeninfo = pickle.load(f)
with open(coredata, 'rb') as f:
coredata = pickle.load(f)
- mesonscript = coredata.meson_script_file
+ mesonscript = coredata.meson_script_launcher
backend = coredata.get_builtin_option('backend')
regen_timestamp = os.stat(dumpfile).st_mtime
if need_regen(regeninfo, regen_timestamp):
diff --git a/mesonbuild/scripts/scanbuild.py b/mesonbuild/scripts/scanbuild.py
index f13a1a4..dd74ce8 100644
--- a/mesonbuild/scripts/scanbuild.py
+++ b/mesonbuild/scripts/scanbuild.py
@@ -16,10 +16,10 @@ import subprocess
import shutil
import tempfile
-def scanbuild(srcdir, blddir, privdir, logdir, args):
+def scanbuild(exename, srcdir, blddir, privdir, logdir, args):
with tempfile.TemporaryDirectory(dir=privdir) as scandir:
- meson_cmd = ['scan-build'] + args
- build_cmd = ['scan-build', '-o', logdir, 'ninja']
+ meson_cmd = [exename] + args
+ build_cmd = [exename, '-o', logdir, 'ninja']
rc = subprocess.call(meson_cmd + [srcdir, scandir])
if rc != 0:
return rc
@@ -32,7 +32,8 @@ def run(args):
privdir = os.path.join(blddir, 'meson-private')
logdir = os.path.join(blddir, 'meson-logs/scanbuild')
shutil.rmtree(logdir, ignore_errors=True)
- if not shutil.which('scan-build'):
- print('Scan-build not installed')
+ exename = os.environ.get('SCANBUILD', 'scan-build')
+ if not shutil.which(exename):
+ print('Scan-build not installed.')
return 1
- return scanbuild(srcdir, blddir, privdir, logdir, meson_cmd)
+ return scanbuild(exename, srcdir, blddir, privdir, logdir, meson_cmd)
diff --git a/mesonbuild/scripts/yelphelper.py b/mesonbuild/scripts/yelphelper.py
index 00d713a..f33454d 100644
--- a/mesonbuild/scripts/yelphelper.py
+++ b/mesonbuild/scripts/yelphelper.py
@@ -75,7 +75,7 @@ def install_help(srcdir, blddir, sources, media, langs, install_dir, destdir, pr
outfile = os.path.join(indir, m)
if not os.path.exists(infile):
if lang == 'C':
- mlog.log(mlog.bold('Warning:'), 'Media file "%s" did not exist in C directory' %m)
+ mlog.warning('Media file "%s" did not exist in C directory' %m)
elif symlinks:
srcfile = os.path.join(c_install_dir, m)
mlog.log('Symlinking %s to %s.' %(outfile, srcfile))
diff --git a/run_project_tests.py b/run_project_tests.py
index 22e92b8..15d656b 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -326,6 +326,28 @@ def have_d_compiler():
return True
return False
+def have_java():
+ if shutil.which('javac') and shutil.which('java'):
+ return True
+ return False
+
+def using_backend(backends):
+ if isinstance(backends, str):
+ backends = (backends,)
+ for backend in backends:
+ if backend == 'ninja':
+ if not backend_flags:
+ return True
+ elif backend == 'xcode':
+ if backend_flags == '--backend=xcode':
+ return True
+ elif backend == 'vs':
+ if backend_flags.startswith('--backend=vs'):
+ return True
+ else:
+ raise AssertionError('Unknown backend type: ' + backend)
+ return False
+
def detect_tests_to_run():
all_tests = []
all_tests.append(('common', gather_tests('test cases/common'), False))
@@ -338,15 +360,15 @@ def detect_tests_to_run():
all_tests.append(('platform-windows', gather_tests('test cases/windows'), False if mesonlib.is_windows() else True))
all_tests.append(('platform-linux', gather_tests('test cases/linuxlike'), False if not (mesonlib.is_osx() or mesonlib.is_windows()) else True))
all_tests.append(('framework', gather_tests('test cases/frameworks'), False if not mesonlib.is_osx() and not mesonlib.is_windows() else True))
- all_tests.append(('java', gather_tests('test cases/java'), False if not mesonlib.is_osx() and shutil.which('javac') else True))
- 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))
- all_tests.append(('python3', gather_tests('test cases/python3'), False if shutil.which('python3') else True))
+ all_tests.append(('java', gather_tests('test cases/java'), False if using_backend('ninja') and not mesonlib.is_osx() and have_java() else True))
+ all_tests.append(('C#', gather_tests('test cases/csharp'), False if using_backend('ninja') and shutil.which('mcs') else True))
+ all_tests.append(('vala', gather_tests('test cases/vala'), False if using_backend('ninja') and shutil.which('valac') else True))
+ all_tests.append(('rust', gather_tests('test cases/rust'), False if using_backend('ninja') and shutil.which('rustc') else True))
+ all_tests.append(('d', gather_tests('test cases/d'), False if using_backend('ninja') and have_d_compiler() else True))
+ all_tests.append(('objective c', gather_tests('test cases/objc'), False if using_backend(('ninja', 'xcode')) and not mesonlib.is_windows() else True))
+ all_tests.append(('fortran', gather_tests('test cases/fortran'), False if using_backend('ninja') and shutil.which('gfortran') else True))
+ all_tests.append(('swift', gather_tests('test cases/swift'), False if using_backend(('ninja', 'xcode')) and shutil.which('swiftc') else True))
+ all_tests.append(('python3', gather_tests('test cases/python3'), False if using_backend('ninja') and shutil.which('python3') else True))
return all_tests
def run_tests(extra_args):
@@ -379,7 +401,7 @@ def run_tests(extra_args):
futures.append((testname, t, result))
for (testname, t, result) in futures:
result = result.result()
- if result is None:
+ if result is None or 'MESON_SKIP_TEST' in result.stdo:
print('Skipping:', t)
current_test = ET.SubElement(current_suite, 'testcase', {'name' : testname,
'classname' : name})
@@ -490,6 +512,21 @@ if __name__ == '__main__':
options = parser.parse_args()
setup_commands(options.backend)
+ # Appveyor sets the `platform` environment variable which completely messes
+ # up building with the vs2010 and vs2015 backends.
+ #
+ # Specifically, MSBuild reads the `platform` environment variable to set
+ # the configured value for the platform (Win32/x64/arm), which breaks x86
+ # builds.
+ #
+ # Appveyor setting this also breaks our 'native build arch' detection for
+ # Windows in environment.py:detect_windows_arch() by overwriting the value
+ # of `platform` set by vcvarsall.bat.
+ #
+ # While building for x86, `platform` should be unset.
+ if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86':
+ os.environ.pop('platform')
+
script_dir = os.path.split(__file__)[0]
if script_dir != '':
os.chdir(script_dir)
diff --git a/run_unittests.py b/run_unittests.py
index cf30276..8df0001 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -73,6 +73,9 @@ class LinuxlikeTests(unittest.TestCase):
def build(self):
self.output += subprocess.check_output(self.ninja_command)
+ def run_target(self, target):
+ self.output += subprocess.check_output(self.ninja_command + [target])
+
def setconf(self, arg):
self.output += subprocess.check_output(self.mconf_command + [arg, self.builddir])
@@ -173,5 +176,10 @@ class LinuxlikeTests(unittest.TestCase):
self.assertEqual(intro[0]['install_filename'], '/usr/local/libtest/libstat.a')
self.assertEqual(intro[1]['install_filename'], '/usr/local/bin/prog')
+ def test_run_target_files_path(self):
+ testdir = os.path.join(self.common_test_dir, '58 run target')
+ self.init(testdir)
+ self.run_target('check_exists')
+
if __name__ == '__main__':
unittest.main()
diff --git a/test cases/common/103 manygen/subdir/manygen.py b/test cases/common/103 manygen/subdir/manygen.py
index 4fd2f25..8449dc3 100755
--- a/test cases/common/103 manygen/subdir/manygen.py
+++ b/test cases/common/103 manygen/subdir/manygen.py
@@ -9,6 +9,7 @@ import shutil, subprocess
with open(sys.argv[1]) as f:
funcname = f.readline().strip()
outdir = sys.argv[2]
+buildtype_args = sys.argv[3]
if not os.path.isdir(outdir):
print('Outdir does not exist.')
@@ -67,7 +68,7 @@ with open(tmpc, 'w') as f:
''' % funcname)
if is_vs:
- subprocess.check_call([compiler, '/nologo', '/c', '/Fo' + outo, tmpc])
+ subprocess.check_call([compiler, '/nologo', '/c', buildtype_args, '/Fo' + outo, tmpc])
else:
subprocess.check_call([compiler, '-c', '-o', outo, tmpc])
diff --git a/test cases/common/103 manygen/subdir/meson.build b/test cases/common/103 manygen/subdir/meson.build
index 5c5d763..3036899 100644
--- a/test cases/common/103 manygen/subdir/meson.build
+++ b/test cases/common/103 manygen/subdir/meson.build
@@ -1,6 +1,17 @@
gen = find_program('manygen.py')
+buildtype = get_option('buildtype')
+buildtype_args = '-Dfooxxx' # a useless compiler argument
if meson.get_compiler('c').get_id() == 'msvc'
+ # We need our manually generated code to use the same CRT as the executable.
+ # Taken from compilers.py since build files do not have access to this.
+ if buildtype == 'debug'
+ buildtype_args = '/MDd'
+ elif buildtype == 'debugoptimized'
+ buildtype_args = '/MDd'
+ elif buildtype == 'release'
+ buildtype_args = '/MD'
+ endif
outfiles = ['gen_func.lib', 'gen_func.c', 'gen_func.h', 'gen_func.o']
else
outfiles = ['gen_func.a', 'gen_func.c', 'gen_func.h', 'gen_func.o']
@@ -9,5 +20,5 @@ endif
generated = custom_target('manygen',
output : outfiles,
input : ['funcinfo.def'],
- command : [gen, '@INPUT@', '@OUTDIR@'],
+ command : [gen, '@INPUT@', '@OUTDIR@', buildtype_args],
)
diff --git a/test cases/common/111 has header symbol/meson.build b/test cases/common/111 has header symbol/meson.build
index e0afb42..b5c865f 100644
--- a/test cases/common/111 has header symbol/meson.build
+++ b/test cases/common/111 has header symbol/meson.build
@@ -1,18 +1,32 @@
-project('has header symbol', 'c')
+project('has header symbol', 'c', 'cpp')
cc = meson.get_compiler('c')
+cpp = meson.get_compiler('cpp')
-assert (cc.has_header_symbol('stdio.h', 'int'), 'base types should always be available')
-assert (cc.has_header_symbol('stdio.h', 'printf'), 'printf function not found')
-assert (cc.has_header_symbol('stdio.h', 'FILE'), 'FILE structure not found')
-assert (cc.has_header_symbol('limits.h', 'INT_MAX'), 'INT_MAX define not found')
-assert (not cc.has_header_symbol('limits.h', 'guint64'), 'guint64 is not defined in limits.h')
-assert (not cc.has_header_symbol('stdlib.h', 'FILE'), 'FILE structure is defined in stdio.h, not stdlib.h')
-assert (not cc.has_header_symbol('stdlol.h', 'printf'), 'stdlol.h shouldn\'t exist')
-assert (not cc.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header')
+foreach comp : [cc, cpp]
+ assert (comp.has_header_symbol('stdio.h', 'int'), 'base types should always be available')
+ assert (comp.has_header_symbol('stdio.h', 'printf'), 'printf function not found')
+ assert (comp.has_header_symbol('stdio.h', 'FILE'), 'FILE structure not found')
+ assert (comp.has_header_symbol('limits.h', 'INT_MAX'), 'INT_MAX define not found')
+ assert (not comp.has_header_symbol('limits.h', 'guint64'), 'guint64 is not defined in limits.h')
+ assert (not comp.has_header_symbol('stdlib.h', 'FILE'), 'FILE structure is defined in stdio.h, not stdlib.h')
+ assert (not comp.has_header_symbol('stdlol.h', 'printf'), 'stdlol.h shouldn\'t exist')
+ assert (not comp.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header')
+endforeach
# This is likely only available on Glibc, so just test for it
if cc.has_function('ppoll')
assert (not cc.has_header_symbol('poll.h', 'ppoll'), 'ppoll should not be accessible without _GNU_SOURCE')
assert (cc.has_header_symbol('poll.h', 'ppoll', prefix : '#define _GNU_SOURCE'), 'ppoll should be accessible with _GNU_SOURCE')
endif
+
+assert (cpp.has_header_symbol('iostream', 'std::iostream'), 'iostream not found in iostream.h')
+assert (cpp.has_header_symbol('vector', 'std::vector'), 'vector not found in vector.h')
+assert (not cpp.has_header_symbol('limits.h', 'std::iostream'), 'iostream should not be defined in limits.h')
+
+boost = dependency('boost', required : false)
+if boost.found()
+ assert (cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion not found')
+else
+ assert (not cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion found?!')
+endif
diff --git a/test cases/common/113 generatorcustom/meson.build b/test cases/common/113 generatorcustom/meson.build
index 1f4cc88..472d565 100644
--- a/test cases/common/113 generatorcustom/meson.build
+++ b/test cases/common/113 generatorcustom/meson.build
@@ -1,17 +1,21 @@
project('generatorcustom', 'c')
-creator = find_program('gen.py')
-catter = find_program('catter.py')
+if meson.get_compiler('c').get_id() != 'msvc'
+ creator = find_program('gen.py')
+ catter = find_program('catter.py')
-gen = generator(creator,
- output: '@BASENAME@.h',
- arguments : ['@INPUT@', '@OUTPUT@'])
+ gen = generator(creator,
+ output: '@BASENAME@.h',
+ arguments : ['@INPUT@', '@OUTPUT@'])
-hs = gen.process('res1.txt', 'res2.txt')
+ hs = gen.process('res1.txt', 'res2.txt')
-allinone = custom_target('alltogether',
- input : hs,
- output : 'alltogether.h',
- command : [catter, '@INPUT@', '@OUTPUT@'])
+ allinone = custom_target('alltogether',
+ input : hs,
+ output : 'alltogether.h',
+ command : [catter, '@INPUT@', '@OUTPUT@'])
-executable('proggie', 'main.c', allinone)
+ executable('proggie', 'main.c', allinone)
+else
+ error('MESON_SKIP_TEST: Skipping test on VS backend; see: https://github.com/mesonbuild/meson/issues/1004')
+endif
diff --git a/test cases/common/121 skip/meson.build b/test cases/common/121 skip/meson.build
new file mode 100644
index 0000000..1adedb6
--- /dev/null
+++ b/test cases/common/121 skip/meson.build
@@ -0,0 +1,4 @@
+project('skip', 'c')
+
+error('MESON_SKIP_TEST this test is always skipped.')
+
diff --git a/test cases/common/16 configure file/config.h b/test cases/common/16 configure file/config.h
new file mode 100644
index 0000000..e85b634
--- /dev/null
+++ b/test cases/common/16 configure file/config.h
@@ -0,0 +1 @@
+#error "This file should not be included. Build dir must become before source dir in search order"
diff --git a/test cases/common/16 configure file/prog.c b/test cases/common/16 configure file/prog.c
index 718a402..89a718e 100644
--- a/test cases/common/16 configure file/prog.c
+++ b/test cases/common/16 configure file/prog.c
@@ -1,5 +1,8 @@
#include <string.h>
-#include "config.h"
+/* config.h must not be in quotes:
+ * https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html
+ */
+#include <config.h>
#ifdef SHOULD_BE_UNDEF
#error "FAIL!"
diff --git a/test cases/common/16 configure file/prog2.c b/test cases/common/16 configure file/prog2.c
index be85033..a88c70f 100644
--- a/test cases/common/16 configure file/prog2.c
+++ b/test cases/common/16 configure file/prog2.c
@@ -1,4 +1,4 @@
-#include"config2.h"
+#include<config2.h>
int main(int argc, char **argv) {
return ZERO_RESULT;
diff --git a/test cases/common/33 try compile/meson.build b/test cases/common/33 try compile/meson.build
index bca82ce..09ca395 100644
--- a/test cases/common/33 try compile/meson.build
+++ b/test cases/common/33 try compile/meson.build
@@ -1,4 +1,4 @@
-project('try compile', 'c')
+project('try compile', 'c', 'cpp')
code = '''#include<stdio.h>
void func() { printf("Something.\n"); }
@@ -8,19 +8,20 @@ breakcode = '''#include<nonexisting.h>
void func() { printf("This won't work.\n"); }
'''
-compiler = meson.get_compiler('c')
-if compiler.compiles(code, name : 'should succeed') == false
- error('Compiler is fail.')
-endif
+foreach compiler : [meson.get_compiler('c'), meson.get_compiler('cpp')]
+ if compiler.compiles(code, name : 'should succeed') == false
+ error('Compiler ' + compiler.get_id() + ' is fail.')
+ endif
-if compiler.compiles(files('valid.c'), name : 'should succeed') == false
- error('Compiler is fail.')
-endif
+ if compiler.compiles(files('valid.c'), name : 'should succeed') == false
+ error('Compiler ' + compiler.get_id() + ' is fail.')
+ endif
-if compiler.compiles(breakcode, name : 'should fail')
- error('Compiler returned true on broken code.')
-endif
+ if compiler.compiles(breakcode, name : 'should fail')
+ error('Compiler ' + compiler.get_id() + ' returned true on broken code.')
+ endif
-if compiler.compiles(files('invalid.c'), name : 'should fail')
- error('Compiler returned true on broken code.')
-endif
+ if compiler.compiles(files('invalid.c'), name : 'should fail')
+ error('Compiler ' + compiler.get_id() + ' returned true on broken code.')
+ endif
+endforeach
diff --git a/test cases/common/35 sizeof/meson.build b/test cases/common/35 sizeof/meson.build
index 4a0398b..9de5b78 100644
--- a/test cases/common/35 sizeof/meson.build
+++ b/test cases/common/35 sizeof/meson.build
@@ -1,13 +1,33 @@
-project('sizeof', 'c')
+project('sizeof', 'c', 'cpp')
+# Test with C
cc = meson.get_compiler('c')
+
intsize = cc.sizeof('int')
wcharsize = cc.sizeof('wchar_t', prefix : '#include<wchar.h>')
cd = configuration_data()
cd.set('INTSIZE', intsize)
cd.set('WCHARSIZE', wcharsize)
+cd.set('CONFIG', 'config.h')
configure_file(input : 'config.h.in', output : 'config.h', configuration : cd)
+s = configure_file(input : 'prog.c.in', output : 'prog.c', configuration : cd)
-e = executable('prog', 'prog.c')
+e = executable('prog', s)
test('sizeof test', e)
+
+# Test with C++
+cpp = meson.get_compiler('cpp')
+
+intsize = cpp.sizeof('int')
+wcharsize = cpp.sizeof('wchar_t', prefix : '#include<wchar.h>')
+
+cdpp = configuration_data()
+cdpp.set('INTSIZE', intsize)
+cdpp.set('WCHARSIZE', wcharsize)
+cdpp.set('CONFIG', 'config.hpp')
+configure_file(input : 'config.h.in', output : 'config.hpp', configuration : cdpp)
+spp = configure_file(input : 'prog.c.in', output : 'prog.cc', configuration : cdpp)
+
+epp = executable('progpp', spp)
+test('sizeof test c++', epp)
diff --git a/test cases/common/35 sizeof/prog.c b/test cases/common/35 sizeof/prog.c.in
index 9164c18..85b1229 100644
--- a/test cases/common/35 sizeof/prog.c
+++ b/test cases/common/35 sizeof/prog.c.in
@@ -1,6 +1,6 @@
-#include"config.h"
-#include<stdio.h>
-#include<wchar.h>
+#include "@CONFIG@"
+#include <stdio.h>
+#include <wchar.h>
int main(int argc, char **argv) {
if(INTSIZE != sizeof(int)) {
diff --git a/test cases/common/37 has header/meson.build b/test cases/common/37 has header/meson.build
index bbfce6d..ce6e71a 100644
--- a/test cases/common/37 has header/meson.build
+++ b/test cases/common/37 has header/meson.build
@@ -1,11 +1,11 @@
-project('has header', 'c')
+project('has header', 'c', 'cpp')
-cc = meson.get_compiler('c')
+foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')]
+ if comp.has_header('stdio.h') == false
+ error('Stdio missing.')
+ endif
-if cc.has_header('stdio.h') == false
- error('Stdio missing.')
-endif
-
-if cc.has_header('ouagadougou.h')
- error('Found non-existant header.')
-endif
+ if comp.has_header('ouagadougou.h')
+ error('Found non-existant header.')
+ endif
+endforeach
diff --git a/test cases/common/39 tryrun/meson.build b/test cases/common/39 tryrun/meson.build
index f5d07ab..c64446f 100644
--- a/test cases/common/39 tryrun/meson.build
+++ b/test cases/common/39 tryrun/meson.build
@@ -1,14 +1,14 @@
-project('tryrun', 'c')
+project('tryrun', 'c', 'cpp')
# Complex to exercise all code paths.
if meson.is_cross_build()
if meson.has_exe_wrapper()
- cc = meson.get_compiler('c', native : false)
+ compilers = [meson.get_compiler('c', native : false), meson.get_compiler('cpp', native : false)]
else
- cc = meson.get_compiler('c', native : true)
+ compilers = [meson.get_compiler('c', native : true), meson.get_compiler('cpp', native : true)]
endif
else
- cc = meson.get_compiler('c')
+ compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')]
endif
ok_code = '''#include<stdio.h>
@@ -32,45 +32,47 @@ INPUTS = [
['File', files('ok.c'), files('error.c'), files('no_compile.c')],
]
-foreach input : INPUTS
- type = input[0]
- ok = cc.run(input[1], name : type + ' should succeed')
- err = cc.run(input[2], name : type + ' should fail')
- noc = cc.run(input[3], name : type + ' does not compile')
+foreach cc : compilers
+ foreach input : INPUTS
+ type = input[0]
+ ok = cc.run(input[1], name : type + ' should succeed')
+ err = cc.run(input[2], name : type + ' should fail')
+ noc = cc.run(input[3], name : type + ' does not compile')
- if noc.compiled()
- error(type + ' compilation fail test failed.')
- else
- message(type + ' fail detected properly.')
- endif
+ if noc.compiled()
+ error(type + ' compilation fail test failed.')
+ else
+ message(type + ' fail detected properly.')
+ endif
- if ok.compiled()
- message(type + ' compilation worked.')
- else
- error(type + ' compilation did not work.')
- endif
+ if ok.compiled()
+ message(type + ' compilation worked.')
+ else
+ error(type + ' compilation did not work.')
+ endif
- if ok.returncode() == 0
- message(type + ' return code ok.')
- else
- error(type + ' return code fail')
- endif
+ if ok.returncode() == 0
+ message(type + ' return code ok.')
+ else
+ error(type + ' return code fail')
+ endif
- if err.returncode() == 1
- message(type + ' bad return code ok.')
- else
- error(type + ' bad return code fail.')
- endif
+ if err.returncode() == 1
+ message(type + ' bad return code ok.')
+ else
+ error(type + ' bad return code fail.')
+ endif
- if ok.stdout().strip() == 'stdout'
- message(type + ' stdout ok.')
- else
- message(type + ' bad stdout.')
- endif
+ if ok.stdout().strip() == 'stdout'
+ message(type + ' stdout ok.')
+ else
+ message(type + ' bad stdout.')
+ endif
- if ok.stderr().strip() == 'stderr'
- message(type + ' stderr ok.')
- else
- message(type + ' bad stderr.')
- endif
+ if ok.stderr().strip() == 'stderr'
+ message(type + ' stderr ok.')
+ else
+ message(type + ' bad stderr.')
+ endif
+ endforeach
endforeach
diff --git a/test cases/common/43 has function/meson.build b/test cases/common/43 has function/meson.build
index 00ca640..61f96e1 100644
--- a/test cases/common/43 has function/meson.build
+++ b/test cases/common/43 has function/meson.build
@@ -1,41 +1,43 @@
-project('has function', 'c')
+project('has function', 'c', 'cpp')
-cc = meson.get_compiler('c')
+compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')]
-if not cc.has_function('printf', prefix : '#include<stdio.h>')
- error('"printf" function not found (should always exist).')
-endif
+foreach cc : compilers
+ if not cc.has_function('printf', prefix : '#include<stdio.h>')
+ error('"printf" function not found (should always exist).')
+ endif
-# Should also be able to detect it without specifying the header
-# We check for a different function here to make sure the result is
-# not taken from a cache (ie. the check above)
-# On MSVC fprintf is defined as an inline function in the header, so it cannot
-# be found without the include.
-if cc.get_id() != 'msvc'
- assert(cc.has_function('fprintf'), '"fprintf" function not found without include (on !msvc).')
-else
- assert(cc.has_function('fprintf', prefix : '#include <stdio.h>'), '"fprintf" function not found with include (on msvc).')
-endif
+ # Should also be able to detect it without specifying the header
+ # We check for a different function here to make sure the result is
+ # not taken from a cache (ie. the check above)
+ # On MSVC fprintf is defined as an inline function in the header, so it cannot
+ # be found without the include.
+ if cc.get_id() != 'msvc'
+ assert(cc.has_function('fprintf'), '"fprintf" function not found without include (on !msvc).')
+ else
+ assert(cc.has_function('fprintf', prefix : '#include <stdio.h>'), '"fprintf" function not found with include (on msvc).')
+ endif
-if cc.has_function('hfkerhisadf', prefix : '#include<stdio.h>')
- error('Found non-existent function "hfkerhisadf".')
-endif
+ if cc.has_function('hfkerhisadf', prefix : '#include<stdio.h>')
+ error('Found non-existent function "hfkerhisadf".')
+ endif
-# With glibc on Linux lchmod is a stub that will always return an error,
-# we want to detect that and declare that the function is not available.
-# We can't check for the C library used here of course, but if it's not
-# implemented in glibc it's probably not implemented in any other 'slimmer'
-# C library variants either, so the check should be safe either way hopefully.
-if host_machine.system() == 'linux' and cc.get_id() == 'gcc'
- assert (cc.has_function('poll', prefix : '#include <poll.h>'), 'couldn\'t detect "poll" when defined by a header')
- assert (not cc.has_function('lchmod', prefix : '''#include <sys/stat.h>
- #include <unistd.h>'''), '"lchmod" check should have failed')
-endif
+ # With glibc on Linux lchmod is a stub that will always return an error,
+ # we want to detect that and declare that the function is not available.
+ # We can't check for the C library used here of course, but if it's not
+ # implemented in glibc it's probably not implemented in any other 'slimmer'
+ # C library variants either, so the check should be safe either way hopefully.
+ if host_machine.system() == 'linux' and cc.get_id() == 'gcc'
+ assert (cc.has_function('poll', prefix : '#include <poll.h>'), 'couldn\'t detect "poll" when defined by a header')
+ assert (not cc.has_function('lchmod', prefix : '''#include <sys/stat.h>
+ #include <unistd.h>'''), '"lchmod" check should have failed')
+ endif
-# For some functions one needs to define _GNU_SOURCE before including the
-# right headers to get them picked up. Make sure we can detect these functions
-# as well without any prefix
-if cc.has_header_symbol('sys/socket.h', 'recvmmsg', prefix : '#define _GNU_SOURCE')
- # We assume that if recvmmsg exists sendmmsg does too
- assert (cc.has_function('sendmmsg'), 'Failed to detect function "sendmmsg" (should always exist).')
-endif
+ # For some functions one needs to define _GNU_SOURCE before including the
+ # right headers to get them picked up. Make sure we can detect these functions
+ # as well without any prefix
+ if cc.has_header_symbol('sys/socket.h', 'recvmmsg', prefix : '#define _GNU_SOURCE')
+ # We assume that if recvmmsg exists sendmmsg does too
+ assert (cc.has_function('sendmmsg'), 'Failed to detect function "sendmmsg" (should always exist).')
+ endif
+endforeach
diff --git a/test cases/common/44 has member/meson.build b/test cases/common/44 has member/meson.build
index e60aeb3..4e61956 100644
--- a/test cases/common/44 has member/meson.build
+++ b/test cases/common/44 has member/meson.build
@@ -1,19 +1,21 @@
-project('has member', 'c')
+project('has member', 'c', 'cpp')
-cc = meson.get_compiler('c')
+compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')]
-if not cc.has_member('struct tm', 'tm_sec', prefix : '#include<time.h>')
- error('Did not detect member of "struct tm" that exists: "tm_sec"')
-endif
+foreach cc : compilers
+ if not cc.has_member('struct tm', 'tm_sec', prefix : '#include<time.h>')
+ 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 "tm_nonexistent" found.')
-endif
+ if cc.has_member('struct tm', 'tm_nonexistent', prefix : '#include<time.h>')
+ 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 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
+ if cc.has_members('struct tm', 'tm_sec', 'tm_nonexistent2', prefix : '#include<time.h>')
+ error('Not existing member "tm_nonexistent2" found.')
+ endif
+endforeach
diff --git a/test cases/common/45 alignment/meson.build b/test cases/common/45 alignment/meson.build
index 2ec3f89..a9bd65b 100644
--- a/test cases/common/45 alignment/meson.build
+++ b/test cases/common/45 alignment/meson.build
@@ -1,29 +1,31 @@
-project('alignment', 'c')
+project('alignment', 'c', 'cpp')
-cc = meson.get_compiler('c')
+compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')]
-# These tests should return the same value on all
-# platforms. If (and when) they don't, fix 'em up.
-if cc.alignment('char') != 1
- error('Alignment of char misdetected.')
-endif
+foreach cc : compilers
+ # These tests should return the same value on all
+ # platforms. If (and when) they don't, fix 'em up.
+ if cc.alignment('char') != 1
+ error('Alignment of char misdetected.')
+ endif
-ptr_size = cc.sizeof('void*')
-dbl_alignment = cc.alignment('double')
+ ptr_size = cc.sizeof('void*')
+ dbl_alignment = cc.alignment('double')
-# These tests are not thorough. Doing this properly
-# would take a lot of work because it is strongly
-# platform and compiler dependent. So just check
-# that they produce something fairly sane.
+ # These tests are not thorough. Doing this properly
+ # would take a lot of work because it is strongly
+ # platform and compiler dependent. So just check
+ # that they produce something fairly sane.
-if ptr_size == 8 or ptr_size == 4
- message('Size of ptr ok.')
-else
- error('Size of ptr misdetected.')
-endif
+ if ptr_size == 8 or ptr_size == 4
+ message('Size of ptr ok.')
+ else
+ error('Size of ptr misdetected.')
+ endif
-if dbl_alignment == 8 or dbl_alignment == 4
- message('Alignment of double ok.')
-else
- error('Alignment of double misdetected.')
-endif
+ if dbl_alignment == 8 or dbl_alignment == 4
+ message('Alignment of double ok.')
+ else
+ error('Alignment of double misdetected.')
+ endif
+endforeach
diff --git a/test cases/common/51 pkgconfig-gen/meson.build b/test cases/common/51 pkgconfig-gen/meson.build
index fa9439c..0933238 100644
--- a/test cases/common/51 pkgconfig-gen/meson.build
+++ b/test cases/common/51 pkgconfig-gen/meson.build
@@ -19,7 +19,7 @@ pkgg.generate(
)
pkgconfig = find_program('pkg-config', required: false)
-if pkgconfig.found()
+if pkgconfig.found() and build_machine.system() != 'windows'
test('pkgconfig-validation', pkgconfig,
args: ['--validate', 'simple'],
env: ['PKG_CONFIG_PATH=' + meson.current_build_dir() + '/meson-private' ],
diff --git a/test cases/common/56 custom target/meson.build b/test cases/common/56 custom target/meson.build
index e216bae..feaa762 100644
--- a/test cases/common/56 custom target/meson.build
+++ b/test cases/common/56 custom target/meson.build
@@ -9,7 +9,7 @@ comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py')
mytarget = custom_target('bindat',
output : 'data.dat',
input : 'data_source.txt',
-command : [python, comp, '@INPUT@', '@OUTPUT@'],
+command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@'],
install : true,
install_dir : 'subdir'
)
diff --git a/test cases/common/56 custom target/my_compiler.py b/test cases/common/56 custom target/my_compiler.py
index d99029b..4ba2da6 100755
--- a/test cases/common/56 custom target/my_compiler.py
+++ b/test cases/common/56 custom target/my_compiler.py
@@ -3,13 +3,14 @@
import sys
if __name__ == '__main__':
- if len(sys.argv) != 3:
- print(sys.argv[0], 'input_file output_file')
+ if len(sys.argv) != 3 or not sys.argv[1].startswith('--input') or \
+ not sys.argv[2].startswith('--output'):
+ print(sys.argv[0], '--input=input_file --output=output_file')
sys.exit(1)
- with open(sys.argv[1]) as f:
+ with open(sys.argv[1].split('=')[1]) as f:
ifile = f.read()
if ifile != 'This is a text only input file.\n':
print('Malformed input')
sys.exit(1)
- with open(sys.argv[2], 'w') as ofile:
+ with open(sys.argv[2].split('=')[1], 'w') as ofile:
ofile.write('This is a binary output file.\n')
diff --git a/test cases/common/58 run target/check_exists.py b/test cases/common/58 run target/check_exists.py
new file mode 100755
index 0000000..62cbe23
--- /dev/null
+++ b/test cases/common/58 run target/check_exists.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+import os
+import sys
+
+if not os.path.isfile(sys.argv[1]):
+ raise Exception("Couldn't find {!r}".format(sys.argv[1]))
diff --git a/test cases/common/58 run target/meson.build b/test cases/common/58 run target/meson.build
index 5824c74..0540b80 100644
--- a/test cases/common/58 run target/meson.build
+++ b/test cases/common/58 run target/meson.build
@@ -35,8 +35,8 @@ 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')])
+run_target('check_exists',
+ command : [find_program('check_exists.py'), 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
diff --git a/test cases/common/62 exe static shared/stat.c b/test cases/common/62 exe static shared/stat.c
index 4eceb30..680ed92 100644
--- a/test cases/common/62 exe static shared/stat.c
+++ b/test cases/common/62 exe static shared/stat.c
@@ -1,5 +1,7 @@
+#include "subdir/exports.h"
+
int shlibfunc();
-int statlibfunc() {
+int DLL_PUBLIC statlibfunc() {
return shlibfunc();
}
diff --git a/test cases/common/83 has type/meson.build b/test cases/common/83 has type/meson.build
index 002f150..de8dbc8 100644
--- a/test cases/common/83 has type/meson.build
+++ b/test cases/common/83 has type/meson.build
@@ -1,11 +1,13 @@
-project('has type', 'c')
+project('has type', 'c', 'cpp')
-cc = meson.get_compiler('c')
+compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')]
-if not cc.has_type('time_t', prefix : '#include<time.h>')
- error('Did not detect type that exists.')
-endif
+foreach cc : compilers
+ if not cc.has_type('time_t', prefix : '#include<time.h>')
+ error('Did not detect type that exists.')
+ endif
-if cc.has_type('no_time_t', prefix : '#include<time.h>')
- error('Not existing type found.')
-endif
+ if cc.has_type('no_time_t', prefix : '#include<time.h>')
+ error('Not existing type found.')
+ endif
+endforeach
diff --git a/test cases/failing/34 dependency not-required then required/meson.build b/test cases/failing/34 dependency not-required then required/meson.build
index f33c41c..1796699 100644
--- a/test cases/failing/34 dependency not-required then required/meson.build
+++ b/test cases/failing/34 dependency not-required then required/meson.build
@@ -1,4 +1,4 @@
project('dep-test', 'c', version : '1.0')
foo_dep = dependency('foo-bar-xyz-12.3', required : false)
-bar_dep = dependency('foo-bar-xyz-12.3', required : true)
+bar_dep = dependency('foo-bar-xyz-12.3')
diff --git a/test cases/failing/34 non-root subproject/meson.build b/test cases/failing/34 non-root subproject/meson.build
new file mode 100644
index 0000000..c84dce7
--- /dev/null
+++ b/test cases/failing/34 non-root subproject/meson.build
@@ -0,0 +1,3 @@
+project('non-root subproject', 'c')
+
+subdir('some')
diff --git a/test cases/failing/34 non-root subproject/some/meson.build b/test cases/failing/34 non-root subproject/some/meson.build
new file mode 100644
index 0000000..d82f451
--- /dev/null
+++ b/test cases/failing/34 non-root subproject/some/meson.build
@@ -0,0 +1 @@
+dependency('definitely-doesnt-exist', fallback : ['someproj', 'some_dep'])
diff --git a/test cases/frameworks/10 gtk-doc/meson.build b/test cases/frameworks/10 gtk-doc/meson.build
index c6881ab..95eeefa 100644
--- a/test cases/frameworks/10 gtk-doc/meson.build
+++ b/test cases/frameworks/10 gtk-doc/meson.build
@@ -8,4 +8,6 @@ inc = include_directories('include')
# We have to disable this test until this bug fix has landed to
# distros https://bugzilla.gnome.org/show_bug.cgi?id=753145
-# subdir('doc')
+error('MESON_SKIP_TEST can not enable gtk-doc test until upstream fixes have landed.')
+
+subdir('doc')
diff --git a/test cases/python3/3 cython/meson.build b/test cases/python3/3 cython/meson.build
index cd245c7..8729640 100644
--- a/test cases/python3/3 cython/meson.build
+++ b/test cases/python3/3 cython/meson.build
@@ -13,5 +13,5 @@ if cython.found()
env : ['PYTHONPATH=' + pydir]
)
else
- message('Cython not found, skipping test.')
+ error('MESON_SKIP_TEST: Cython not found, skipping test.')
endif
diff --git a/test cases/vala/11 mixed sources/meson.build b/test cases/vala/11 mixed sources/meson.build
index 75b8ecd..1aecd44 100644
--- a/test cases/vala/11 mixed sources/meson.build
+++ b/test cases/vala/11 mixed sources/meson.build
@@ -1,7 +1,8 @@
project('foo', 'c', 'vala')
glib = dependency('glib-2.0')
+gobject = dependency('gobject-2.0')
subdir('c')
-e = executable('foo', 'c/foo.c', retval, 'vala/bar.vala', dependencies: [glib])
+e = executable('foo', 'c/foo.c', retval, 'vala/bar.vala', dependencies: [glib, gobject])
test('test foo', e)