aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Compiler-properties.md2
-rw-r--r--docs/markdown/Contributing.md2
-rw-r--r--docs/markdown/Creating-Linux-binaries.md2
-rw-r--r--docs/markdown/Dependencies.md7
-rw-r--r--docs/markdown/Icestorm-module.md27
-rw-r--r--docs/markdown/Reference-manual.md5
-rw-r--r--docs/markdown/Reference-tables.md2
-rw-r--r--docs/markdown/Users.md7
-rw-r--r--docs/markdown/Videos.md44
-rw-r--r--docs/markdown/snippets/config-tool-cross.md13
-rw-r--r--docs/markdown/snippets/deprecations.md14
-rw-r--r--docs/markdown/snippets/fpga.md12
-rw-r--r--docs/markdown/snippets/project-license.md4
-rw-r--r--docs/sitemap.txt1
-rw-r--r--mesonbuild/backend/backends.py2
-rw-r--r--mesonbuild/backend/ninjabackend.py51
-rw-r--r--mesonbuild/backend/vs2010backend.py2
-rw-r--r--mesonbuild/backend/xcodebackend.py2
-rw-r--r--mesonbuild/build.py16
-rw-r--r--mesonbuild/compilers/c.py19
-rw-r--r--mesonbuild/compilers/compilers.py6
-rw-r--r--mesonbuild/compilers/cpp.py10
-rw-r--r--mesonbuild/compilers/fortran.py2
-rw-r--r--mesonbuild/dependencies/base.py41
-rw-r--r--mesonbuild/dependencies/dev.py10
-rw-r--r--mesonbuild/dependencies/misc.py97
-rw-r--r--mesonbuild/environment.py4
-rw-r--r--mesonbuild/interpreter.py37
-rw-r--r--mesonbuild/interpreterbase.py14
-rw-r--r--mesonbuild/mesonlib.py10
-rw-r--r--mesonbuild/mesonmain.py7
-rw-r--r--mesonbuild/mintro.py4
-rw-r--r--mesonbuild/mlog.py7
-rw-r--r--mesonbuild/modules/pkgconfig.py8
-rw-r--r--mesonbuild/modules/qt.py6
-rw-r--r--mesonbuild/modules/unstable_icestorm.py85
-rw-r--r--mesonbuild/mparser.py2
-rw-r--r--mesonbuild/mtest.py12
-rw-r--r--mesonbuild/scripts/coverage.py11
-rw-r--r--mesonbuild/scripts/gettext.py2
-rw-r--r--mesonbuild/scripts/meson_install.py70
-rw-r--r--mesonbuild/wrap/wraptool.py4
-rwxr-xr-xrun_project_tests.py52
-rwxr-xr-xrun_unittests.py62
-rw-r--r--test cases/common/140 get define/meson.build4
-rw-r--r--test cases/common/175 get project license/bar.c6
-rw-r--r--test cases/common/175 get project license/meson.build8
-rw-r--r--test cases/common/51 pkgconfig-gen/dependencies/exposed.c3
-rw-r--r--test cases/common/51 pkgconfig-gen/dependencies/internal.c3
-rw-r--r--test cases/common/51 pkgconfig-gen/dependencies/meson.build38
-rw-r--r--test cases/common/51 pkgconfig-gen/meson.build33
-rw-r--r--test cases/common/58 run target/meson.build3
-rw-r--r--test cases/common/90 identical target name in subproject/meson.build2
-rw-r--r--test cases/common/90 identical target name in subproject/subprojects/foo/meson.build2
-rw-r--r--test cases/failing/68 subproj different versions/meson.build2
-rw-r--r--test cases/fpga/1 simple/meson.build9
-rw-r--r--test cases/fpga/1 simple/spin.pcf6
-rw-r--r--test cases/fpga/1 simple/spin.v32
-rw-r--r--test cases/frameworks/4 qt/meson.build3
-rw-r--r--test cases/frameworks/4 qt/subfolder/main.cpp10
-rw-r--r--test cases/frameworks/4 qt/subfolder/meson.build4
-rw-r--r--test cases/frameworks/4 qt/subfolder/resources/stuff3.qrc6
-rw-r--r--test cases/frameworks/4 qt/subfolder/resources/thing.pngbin0 -> 40303 bytes
-rw-r--r--test cases/unit/21 warning location/a.c (renamed from test cases/unit/20 warning location/a.c)0
-rw-r--r--test cases/unit/21 warning location/b.c (renamed from test cases/unit/20 warning location/b.c)0
-rw-r--r--test cases/unit/21 warning location/conf.in (renamed from test cases/unit/20 warning location/conf.in)0
-rw-r--r--test cases/unit/21 warning location/main.c (renamed from test cases/unit/20 warning location/main.c)0
-rw-r--r--test cases/unit/21 warning location/meson.build (renamed from test cases/unit/20 warning location/meson.build)0
-rw-r--r--test cases/unit/21 warning location/sub/c.c (renamed from test cases/unit/20 warning location/sub/c.c)0
-rw-r--r--test cases/unit/21 warning location/sub/d.c (renamed from test cases/unit/20 warning location/sub/d.c)0
-rw-r--r--test cases/unit/21 warning location/sub/meson.build (renamed from test cases/unit/20 warning location/sub/meson.build)0
-rw-r--r--test cases/unit/21 warning location/sub/sub.c (renamed from test cases/unit/20 warning location/sub/sub.c)0
-rw-r--r--test cases/unit/22 unfound pkgconfig/meson.build15
-rw-r--r--test cases/unit/22 unfound pkgconfig/some.c3
74 files changed, 661 insertions, 328 deletions
diff --git a/docs/markdown/Compiler-properties.md b/docs/markdown/Compiler-properties.md
index 4def628..579417a 100644
--- a/docs/markdown/Compiler-properties.md
+++ b/docs/markdown/Compiler-properties.md
@@ -173,7 +173,7 @@ Does a structure contain a member?
==
Some platforms have different standard structures. Here's how one
-would check if a struct called `mystruct` from header `myheader.h</hh>
+would check if a struct called `mystruct` from header `myheader.h`
contains a member called `some_member`.
```meson
diff --git a/docs/markdown/Contributing.md b/docs/markdown/Contributing.md
index 169bf4c..293b629 100644
--- a/docs/markdown/Contributing.md
+++ b/docs/markdown/Contributing.md
@@ -20,7 +20,7 @@ test run before they are even considered for submission.
## Tests
-All new features must come with automatic tests that throughly prove
+All new features must come with automatic tests that thoroughly prove
that the feature is working as expected. Similarly bug fixes must come
with a unit test that demonstrates the bug, proves that it has been
fixed and prevents the feature from breaking in the future.
diff --git a/docs/markdown/Creating-Linux-binaries.md b/docs/markdown/Creating-Linux-binaries.md
index 8ca3ef0..084e157 100644
--- a/docs/markdown/Creating-Linux-binaries.md
+++ b/docs/markdown/Creating-Linux-binaries.md
@@ -61,7 +61,7 @@ Log out and back in and now your build environment is ready to use.
## Adding other tools
Old distros might have too old versions of some tools. For Meson this
-could nclude Python 3 and Ninja. If this is the case you need to
+could include Python 3 and Ninja. If this is the case you need to
download, build and install new versions into `~/devroot` in the usual
way.
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md
index b36d275..189db72 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -144,6 +144,13 @@ pass `gtest` or `gmock` to `dependency` and it will do everything for
you. If you want to use GMock, it is recommended to use GTest as well,
as getting it to work standalone is tricky.
+You can set the `main` keyword argument to `true` to use the `main()`
+function provided by GTest:
+```
+gtest_dep = dependency('gtest', main : true, required : false)
+e = executable('testprog', 'test.cc', dependencies : gtest_dep)
+test('gtest test', e)
+```
## MPI
MPI is supported for C, C++ and Fortran. Because dependencies are
diff --git a/docs/markdown/Icestorm-module.md b/docs/markdown/Icestorm-module.md
new file mode 100644
index 0000000..896311f
--- /dev/null
+++ b/docs/markdown/Icestorm-module.md
@@ -0,0 +1,27 @@
+# Unstable SIMD module
+
+This module provides is available since version 0.45.0.
+
+**Note**: this module is unstable. It is only provided as a technology
+preview. Its API may change in arbitrary ways between releases or it
+might be removed from Meson altogether.
+
+## Usage
+
+This module provides an experimental to create FPGA bitstreams using
+the [IceStorm](http://www.clifford.at/icestorm/) suite of tools.
+
+The module exposes only one method called `project` and it is used
+like this:
+
+ is.project('projname',
+ <verilog files>,
+ constraint_file : <pcf file>,
+ )
+
+The input to this function is the set of Verilog files and a
+constraint file. This produces output files called `projname.asc`,
+`projname.blif` and `projname.bin`. In addition it creates two run
+targets called `projname-time` for running timing analysis and
+`projname-upload` that uploads the generated bitstream to an FPGA
+devide using the `iceprog` programming executable.
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index a3e1ef0..31c4953 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -910,7 +910,8 @@ Project supports the following keyword arguments.
'GPL3']`. Note that the text is informal and is only written to
the dependency manifest. Meson does not do any license validation,
you are responsible for verifying that you abide by all licensing
- terms.
+ terms. You can access the value in your Meson build files with
+ `meson.project_license()`.
- `meson_version` takes a string describing which Meson version the
project requires. Usually something like `>0.28.0`.
@@ -1247,6 +1248,8 @@ the following methods.
- `project_version()` returns the version string specified in `project` function call.
+- `project_license()` returns the array of licenses specified in `project` function call.
+
- `project_name()` returns the project name specified in the `project` function call.
- `version()` return a string with the version of Meson.
diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md
index ee3b8c2..5ee0db1 100644
--- a/docs/markdown/Reference-tables.md
+++ b/docs/markdown/Reference-tables.md
@@ -57,7 +57,7 @@ These are provided by the `.system()` method call.
| windows | Any version of Windows |
| cygwin | The Cygwin environment for Windows |
| haiku | |
-| freebsd | FreeBSD and it's derivatives |
+| freebsd | FreeBSD and its derivatives |
| dragonfly | DragonFly BSD |
| netbsd | |
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index 616fdc5..0b7734d 100644
--- a/docs/markdown/Users.md
+++ b/docs/markdown/Users.md
@@ -10,6 +10,7 @@ If you have a project that uses Meson that you want to add to this list, let us
- [Arduino sample project](https://github.com/jpakkane/mesonarduino)
- [Budgie Desktop](https://github.com/budgie-desktop/budgie-desktop), a desktop environment built on GNOME technologies
- [casync](https://github.com/systemd/casync), Content-Addressable Data Synchronization Tool
+ - [Dpdk](http://dpdk.org/ml/archives/dev/2018-January/089724.html), Data plane development kit, a set of libraries and drivers for fast packet processing
- [Emeus](https://github.com/ebassi/emeus), Constraint based layout manager for GTK+
- [Frida](https://www.frida.re/), a dynamic binary instrumentation toolkit
- [Geary](https://wiki.gnome.org/Apps/Geary), an email application built around conversations, for the GNOME 3 desktop.
@@ -25,21 +26,27 @@ If you have a project that uses Meson that you want to add to this list, let us
- [GTK+](https://git.gnome.org/browse/gtk+/), the multi-platform toolkit used by GNOME
- [GtkDApp](https://gitlab.com/csoriano/GtkDApp), an application template for developing Flatpak apps with Gtk+ and D
- [HexChat](https://github.com/hexchat/hexchat), a cross-platform IRC client in C
+ - [IGT](https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/), Linux kernel graphics driver test suite.
- [Json-glib](https://git.gnome.org/browse/json-glib), GLib-based JSON manipulation library
- [Ksh](https://github.com/att/ast), a Korn Shell
+ - [Libdrm](https://cgit.freedesktop.org/drm/libdrm/), a library for abstracting DRM kernel interfaces
- [Libepoxy](https://github.com/anholt/libepoxy/), a library for handling OpenGL function pointer management
- [Libgit2-glib](https://git.gnome.org/browse/libgit2-glib/), a GLib wrapper for libgit2
- [Libhttpseverywhere](https://github.com/grindhold/libhttpseverywhere), a library to enable httpseverywhere on any desktop app
- [Lightdm-Webkit2-Greeter](https://github.com/Antergos/lightdm-webkit2-greeter)
- [Kiwix libraries](https://github.com/kiwix/kiwix-lib)
+ - [Mesa](https://www.mesa3d.org/), An open source graphics driver project
- [Nautilus](https://git.gnome.org/browse/nautilus/commit/?id=ed5652c89ac0654df2e82b54b00b27d51c825465) the Gnome file manager
- [Orc](http://cgit.freedesktop.org/gstreamer/orc/), the Optimized Inner Loop Runtime Compiler (not the default yet)
+ - [Outlier](https://github.com/kerolasa/outlier), a small Hello World style meson example project
- [Pango](https://git.gnome.org/browse/pango/), an Internationalized text layout and rendering library (not the default yet)
- [Parzip](https://github.com/jpakkane/parzip), a multithreaded reimplementation of Zip
+ - [PipeWire](https://pipewire.org/), a framework for video and audio for containerized applications
- [Pitivi](http://pitivi.org/), a nonlinear video editor
- [Polari](https://git.gnome.org/browse/polari), an IRC client
- [Sysprof](https://wiki.gnome.org/Apps/Sysprof), a profiling tool
- [systemd](https://github.com/systemd/systemd), the init system
+ - [Taisei Project](https://taisei-project.org/), an open-source Touhou Project clone and fangame
- [Xorg](https://cgit.freedesktop.org/xorg/xserver/) the X.org display server (not the default yet)
- [Valum](https://github.com/valum-framework/valum), a micro web framework written in Vala
- [Wayland and Weston](https://lists.freedesktop.org/archives/wayland-devel/2016-November/031984.html), a next generation display server (not merged yet)
diff --git a/docs/markdown/Videos.md b/docs/markdown/Videos.md
index 5abfbe4..d9ea34d 100644
--- a/docs/markdown/Videos.md
+++ b/docs/markdown/Videos.md
@@ -4,34 +4,28 @@ short-description: Videos about Meson
# Videos
-## An overview of meson
+ - [The Meson Build System, 4+ years of work to become an overnight
+ success](https://www.youtube.com/watch?v=gHdTzdXkhRY), Linux.conf.au 2018
-(from Linux.conf.au 2015 -- Auckland, New Zealand)
+ - [Meson and the changing Linux build
+ landscape](https://media.ccc.de/v/ASG2017-111-meson_and_the_changing_linux_build_landscape),
+ All Systems Go 2017
-<div class="video-container">
-<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/KPi0AuVpxLI" allowfullscreen></iframe>
-</div>
+ - [Meson, compiling the world with
+ Python](https://www.youtube.com/watch?v=sEO4DC8hm34), Europython
+ 2017
-## Talks about design, goals behind Meson's multiplatform dependency system was held
+ - [Builds, dependencies and deployment in a modern multiplatform
+ world](https://www.youtube.com/embed/CTJtKtQ8R5k), Linux.conf.au
+ 2016
-(From Linux.conf.au 2016 -- Geelong, Australia)
+ - [New world, new tools](https://www.youtube.com/embed/0-gx1qU2pPo),
+ Libre Application Summit 2016
-<div class="video-container">
-<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/CTJtKtQ8R5k" allowfullscreen></iframe>
-</div>
+ - [Making build systems not
+ suck](https://www.youtube.com/embed/KPi0AuVpxLI), Linux.conf.au
+ 2015, Auckland, New Zealand
-## Features and benefits of Meson's multiplatform support for building and dependencies]
-
-(Libre Application Summit 2016 talk _New world, new tools_ explored further)
-
-<div class="video-container">
-<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/0-gx1qU2pPo" allowfullscreen></iframe>
-</div>
-
-## The first ever public presentation on Meson
-
-(lightning talk at FOSDEM 2014)
-
-<video width="854" height="480" controls>
- <source src=http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2014/H2215_Ferrer/Sunday/Introducing_the_Meson_build_system.webm>
-</video>
+ - [Lightning talk at FOSDEM
+ 2014](http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2014/H2215_Ferrer/Sunday/Introducing_the_Meson_build_system.webm),
+ The first ever public presentation on Meson
diff --git a/docs/markdown/snippets/config-tool-cross.md b/docs/markdown/snippets/config-tool-cross.md
new file mode 100644
index 0000000..1102481
--- /dev/null
+++ b/docs/markdown/snippets/config-tool-cross.md
@@ -0,0 +1,13 @@
+# Config-Tool based dependencies can be specified in a cross file
+
+Tools like LLVM and pcap use a config tool for dependencies, this is a script
+or binary that is run to get configuration information (cflags, ldflags, etc)
+from.
+
+These binaries may now be specified in the `binaries` section of a cross file.
+
+```dosini
+[binaries]
+cc = ...
+llvm-config = '/usr/bin/llvm-config32'
+```
diff --git a/docs/markdown/snippets/deprecations.md b/docs/markdown/snippets/deprecations.md
new file mode 100644
index 0000000..adab2e6
--- /dev/null
+++ b/docs/markdown/snippets/deprecations.md
@@ -0,0 +1,14 @@
+## Removed two deprecated features
+
+The standalone `find_library` function has been a no-op for a long
+time. Starting with this version it becomes a hard error.
+
+There used to be a keywordless version of `run_target` which looked
+like this:
+
+ run_target('targetname', 'command', 'arg1', 'arg2')
+
+This is now an error. The correct format for this is now:
+
+ run_target('targetname',
+ command : ['command', 'arg1', 'arg2'])
diff --git a/docs/markdown/snippets/fpga.md b/docs/markdown/snippets/fpga.md
new file mode 100644
index 0000000..b5e4938
--- /dev/null
+++ b/docs/markdown/snippets/fpga.md
@@ -0,0 +1,12 @@
+## Experimental FPGA support
+
+This version adds support for generating, analysing and uploading FPGA
+programs using the [IceStorm
+toolchain](http://www.clifford.at/icestorm/). This support is
+experimental and is currently limited to the `iCE 40` series of FPGA
+chips.
+
+FPGA generation integrates with other parts of Meson seamlessly. As an
+example, [here](https://github.com/jpakkane/lm32) is an example
+project that compiles a simple firmware into Verilog and combines that
+with an lm32 softcore processor.
diff --git a/docs/markdown/snippets/project-license.md b/docs/markdown/snippets/project-license.md
new file mode 100644
index 0000000..5da2c6a
--- /dev/null
+++ b/docs/markdown/snippets/project-license.md
@@ -0,0 +1,4 @@
+## New method meson.project_license()
+
+The `meson` builtin object now has a `project_license()` method that returns a
+list of all licenses for the project.
diff --git a/docs/sitemap.txt b/docs/sitemap.txt
index 87a5eb5..d40c3a0 100644
--- a/docs/sitemap.txt
+++ b/docs/sitemap.txt
@@ -30,6 +30,7 @@ index.md
Modules.md
Gnome-module.md
i18n-module.md
+ Icestorm-module.md
Pkgconfig-module.md
Python-3-module.md
Qt4-module.md
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 5a5db22..292b027 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -322,7 +322,7 @@ class Backend:
continue
if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so']:
continue
- absdir = os.path.split(libpath)[0]
+ absdir = os.path.dirname(libpath)
rel_to_src = absdir[len(self.environment.get_source_dir()) + 1:]
assert(not os.path.isabs(rel_to_src))
paths.append(os.path.join(self.build_to_src, rel_to_src))
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index e1f3909..35e697c 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -38,8 +38,12 @@ else:
execute_wrapper = ''
rmfile_prefix = 'rm -f {} &&'
-def ninja_quote(text):
- for char in ('$', ' ', ':'):
+def ninja_quote(text, is_build_line=False):
+ if is_build_line:
+ qcs = ('$', ' ', ':')
+ else:
+ qcs = ('$', ' ')
+ for char in qcs:
text = text.replace(char, '$' + char)
if '\n' in text:
errmsg = '''Ninja does not support newlines in rules. The content was:
@@ -87,13 +91,13 @@ class NinjaBuildElement:
def write(self, outfile):
self.check_outputs()
- line = 'build %s: %s %s' % (' '.join([ninja_quote(i) for i in self.outfilenames]),
+ line = 'build %s: %s %s' % (' '.join([ninja_quote(i, True) for i in self.outfilenames]),
self.rule,
- ' '.join([ninja_quote(i) for i in self.infilenames]))
+ ' '.join([ninja_quote(i, True) for i in self.infilenames]))
if len(self.deps) > 0:
- line += ' | ' + ' '.join([ninja_quote(x) for x in self.deps])
+ line += ' | ' + ' '.join([ninja_quote(x, True) for x in self.deps])
if len(self.orderdeps) > 0:
- line += ' || ' + ' '.join([ninja_quote(x) for x in self.orderdeps])
+ line += ' || ' + ' '.join([ninja_quote(x, True) for x in self.orderdeps])
line += '\n'
# This is the only way I could find to make this work on all
# platforms including Windows command shell. Slash is a dir separator
@@ -823,7 +827,7 @@ int dummy;
if subdir is None:
subdir = os.path.join(manroot, 'man' + num)
srcabs = f.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())
- dstabs = os.path.join(subdir, os.path.split(f.fname)[1] + '.gz')
+ dstabs = os.path.join(subdir, os.path.basename(f.fname) + '.gz')
i = [srcabs, dstabs]
d.man.append(i)
@@ -836,24 +840,21 @@ int dummy;
subdir = de.install_dir
for f in de.sources:
assert(isinstance(f, mesonlib.File))
- plain_f = os.path.split(f.fname)[1]
+ plain_f = os.path.basename(f.fname)
dstabs = os.path.join(subdir, plain_f)
i = [f.absolute_path(srcdir, builddir), dstabs, de.install_mode]
d.data.append(i)
def generate_subdir_install(self, d):
for sd in self.build.get_install_subdirs():
- inst_subdir = sd.installable_subdir.rstrip('/')
- idir_parts = inst_subdir.split('/')
- if len(idir_parts) > 1:
- subdir = os.path.join(sd.source_subdir, '/'.join(idir_parts[:-1]))
- inst_dir = idir_parts[-1]
- else:
- subdir = sd.source_subdir
- inst_dir = sd.installable_subdir
- src_dir = os.path.join(self.environment.get_source_dir(), subdir)
- dst_dir = os.path.join(self.environment.get_prefix(), sd.install_dir)
- d.install_subdirs.append([src_dir, inst_dir, dst_dir, sd.install_mode, sd.exclude])
+ src_dir = os.path.join(self.environment.get_source_dir(),
+ sd.source_subdir,
+ sd.installable_subdir).rstrip('/')
+ dst_dir = os.path.join(self.environment.get_prefix(),
+ sd.install_dir,
+ os.path.basename(src_dir))
+ d.install_subdirs.append([src_dir, dst_dir, sd.install_mode,
+ sd.exclude])
def generate_tests(self, outfile):
self.serialize_tests()
@@ -1278,7 +1279,7 @@ int dummy;
# Target names really should not have slashes in them, but
# unfortunately we did not check for that and some downstream projects
# now have them. Once slashes are forbidden, remove this bit.
- target_slashname_workaround_dir = os.path.join(os.path.split(target.name)[0],
+ target_slashname_workaround_dir = os.path.join(os.path.dirname(target.name),
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
@@ -1405,7 +1406,7 @@ int dummy;
objects = [] # Relative to swift invocation dir
rel_objects = [] # Relative to build.ninja
for i in abssrc + abs_generated:
- base = os.path.split(i)[1]
+ base = os.path.basename(i)
oname = os.path.splitext(base)[0] + '.o'
objects.append(oname)
rel_objects.append(os.path.join(self.get_target_private_dir(target), oname))
@@ -1934,7 +1935,7 @@ rule FORTRAN_DEP_HACK
# Check if a source uses a module it exports itself.
# Potential bug if multiple targets have a file with
# the same name.
- if mod_source_file.fname == os.path.split(src)[1]:
+ if mod_source_file.fname == os.path.basename(src):
continue
mod_name = compiler.module_name_to_filename(
usematch.group(1))
@@ -2277,7 +2278,7 @@ rule FORTRAN_DEP_HACK
commands = []
commands += self.generate_basic_compiler_args(target, compiler)
- just_name = os.path.split(header)[1]
+ just_name = os.path.basename(header)
(objname, pch_args) = compiler.gen_pch_args(just_name, source, dst)
commands += pch_args
commands += self.get_compile_debugfile_args(compiler, target, objname)
@@ -2287,7 +2288,7 @@ rule FORTRAN_DEP_HACK
def generate_gcc_pch_command(self, target, compiler, pch):
commands = self._generate_single_compile(target, compiler)
dst = os.path.join(self.get_target_private_dir(target),
- os.path.split(pch)[-1] + '.' + compiler.get_pch_suffix())
+ os.path.basename(pch) + '.' + compiler.get_pch_suffix())
dep = dst + '.' + compiler.get_depfile_suffix()
return commands, dep, dst, [] # Gcc does not create an object file during pch generation.
@@ -2482,7 +2483,7 @@ rule FORTRAN_DEP_HACK
# unfortunately we did not check for that and some downstream projects
# now have them. Once slashes are forbidden, remove this bit.
target_slashname_workaround_dir = os.path.join(
- os.path.split(target.name)[0],
+ os.path.dirname(target.name),
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 1722db7..057e7c9 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -1034,7 +1034,7 @@ class Vs2010Backend(backends.Backend):
pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile')
# 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]
+ pch_file.text = os.path.basename(header)
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)
diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py
index aca3aea..3ae31e4 100644
--- a/mesonbuild/backend/xcodebackend.py
+++ b/mesonbuild/backend/xcodebackend.py
@@ -311,7 +311,7 @@ class XCodeBackend(backends.Backend):
for fname, idval in self.filemap.items():
fullpath = os.path.join(self.environment.get_source_dir(), fname)
xcodetype = self.get_xcodetype(fname)
- name = os.path.split(fname)[-1]
+ name = os.path.basename(fname)
path = fname
self.ofile.write(src_templ % (idval, fullpath, xcodetype, name, path))
target_templ = '%s /* %s */ = { isa = PBXFileReference; explicitFileType = "%s"; path = %s; refType = %d; sourceTree = BUILT_PRODUCTS_DIR; };\n'
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 5eab794..dc19b73 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1065,7 +1065,7 @@ class Generator:
depfile = kwargs['depfile']
if not isinstance(depfile, str):
raise InvalidArguments('Depfile must be a string.')
- if os.path.split(depfile)[1] != depfile:
+ if os.path.basename(depfile) != depfile:
raise InvalidArguments('Depfile must be a plain filename without a subdirectory.')
self.depfile = depfile
if 'capture' in kwargs:
@@ -1075,7 +1075,7 @@ class Generator:
self.capture = capture
def get_base_outnames(self, inname):
- plainname = os.path.split(inname)[1]
+ plainname = os.path.basename(inname)
basename = os.path.splitext(plainname)[0]
bases = [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs]
return bases
@@ -1083,12 +1083,12 @@ class Generator:
def get_dep_outname(self, inname):
if self.depfile is None:
raise InvalidArguments('Tried to get dep name for rule that does not have dependency file defined.')
- plainname = os.path.split(inname)[1]
+ plainname = os.path.basename(inname)
basename = os.path.splitext(plainname)[0]
return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname)
def get_arglist(self, inname):
- plainname = os.path.split(inname)[1]
+ plainname = os.path.basename(inname)
basename = os.path.splitext(plainname)[0]
return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist]
@@ -1130,7 +1130,7 @@ class GeneratedList:
in_abs = infile.absolute_path(state.environment.source_dir, state.environment.build_dir)
assert(os.path.isabs(self.preserve_path_from))
rel = os.path.relpath(in_abs, self.preserve_path_from)
- path_segment = os.path.split(rel)[0]
+ path_segment = os.path.dirname(rel)
for of in outfiles:
result.append(os.path.join(path_segment, of))
return result
@@ -1637,6 +1637,10 @@ class CustomTarget(Target):
for i in self.outputs:
if not(isinstance(i, str)):
raise InvalidArguments('Output argument not a string.')
+ if i == '':
+ raise InvalidArguments('Output must not be empty.')
+ if i.strip() == '':
+ raise InvalidArguments('Output must not consist only of whitespace.')
if '/' in i:
raise InvalidArguments('Output must not contain a path segment.')
if '@INPUT@' in i or '@INPUT0@' in i:
@@ -1659,7 +1663,7 @@ class CustomTarget(Target):
depfile = kwargs['depfile']
if not isinstance(depfile, str):
raise InvalidArguments('Depfile must be a string.')
- if os.path.split(depfile)[1] != depfile:
+ if os.path.basename(depfile) != depfile:
raise InvalidArguments('Depfile must be a plain filename without a subdirectory.')
self.depfile = depfile
self.command = self.flatten_command(kwargs['command'])
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 4c6e3a2..f738615 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -172,10 +172,10 @@ class CCompiler(Compiler):
return ' '.join(self.exelist)
def get_pch_use_args(self, pch_dir, header):
- return ['-include', os.path.split(header)[-1]]
+ return ['-include', os.path.basename(header)]
def get_pch_name(self, header_name):
- return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix()
+ return os.path.basename(header_name) + '.' + self.get_pch_suffix()
def get_linker_search_args(self, dirname):
return ['-L' + dirname]
@@ -804,6 +804,13 @@ class CCompiler(Compiler):
return ['-pthread']
def has_multi_arguments(self, args, env):
+ for arg in args:
+ if arg.startswith('-Wl,'):
+ mlog.warning('''{} looks like a linker argument, but has_argument
+and other similar methods only support checking compiler arguments.
+Using them to check linker arguments are never supported, and results
+are likely to be wrong regardless of the compiler you are using.
+'''.format(arg))
return self.compiles('int i;\n', env, extra_args=args)
@@ -875,7 +882,7 @@ class GnuCCompiler(GnuCompiler, CCompiler):
return ['-shared']
def get_pch_use_args(self, pch_dir, header):
- return ['-fpch-preprocess', '-include', os.path.split(header)[-1]]
+ return ['-fpch-preprocess', '-include', os.path.basename(header)]
class IntelCCompiler(IntelCompiler, CCompiler):
@@ -954,13 +961,13 @@ class VisualStudioCCompiler(CCompiler):
return 'pch'
def get_pch_name(self, header):
- chopped = os.path.split(header)[-1].split('.')[:-1]
+ chopped = os.path.basename(header).split('.')[:-1]
chopped.append(self.get_pch_suffix())
pchname = '.'.join(chopped)
return pchname
def get_pch_use_args(self, pch_dir, header):
- base = os.path.split(header)[-1]
+ base = os.path.basename(header)
pchname = self.get_pch_name(header)
return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)]
@@ -1087,7 +1094,7 @@ class VisualStudioCCompiler(CCompiler):
mlog.debug('Running VS compile:')
mlog.debug('Command line: ', ' '.join(commands))
mlog.debug('Code:\n', code)
- p, stdo, stde = Popen_safe(commands, cwd=os.path.split(srcname)[0])
+ p, stdo, stde = Popen_safe(commands, cwd=os.path.dirname(srcname))
if p.returncode != 0:
return False
return not(warning_text in stde or warning_text in stdo)
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 2602d14..dbaf730 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -1040,7 +1040,7 @@ class GnuCompiler:
return 'gch'
def split_shlib_to_parts(self, fname):
- return os.path.split(fname)[0], fname
+ return os.path.dirname(fname), fname
def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module)
@@ -1188,10 +1188,10 @@ class IntelCompiler:
self.lang_header, '-include', header, '-x', 'none']
def get_pch_name(self, header_name):
- return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix()
+ return os.path.basename(header_name) + '.' + self.get_pch_suffix()
def split_shlib_to_parts(self, fname):
- return os.path.split(fname)[0], fname
+ return os.path.dirname(fname), fname
def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
if self.icc_type == ICC_STANDARD:
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 5e32ace..c10f38e 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -14,6 +14,7 @@
import os.path
+from .. import mlog
from .. import coredata
from ..mesonlib import version_compare
@@ -129,7 +130,7 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
return []
def get_pch_use_args(self, pch_dir, header):
- return ['-fpch-preprocess', '-include', os.path.split(header)[-1]]
+ return ['-fpch-preprocess', '-include', os.path.basename(header)]
class IntelCPPCompiler(IntelCompiler, CPPCompiler):
@@ -174,6 +175,13 @@ class IntelCPPCompiler(IntelCompiler, CPPCompiler):
return []
def has_multi_arguments(self, args, env):
+ for arg in args:
+ if arg.startswith('-Wl,'):
+ mlog.warning('''{} looks like a linker argument, but has_argument
+and other similar methods only support checking compiler arguments.
+Using them to check linker arguments are never supported, and results
+are likely to be wrong regardless of the compiler you are using.
+'''.format(arg))
return super().has_multi_arguments(args + ['-diag-error', '10006'], env)
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 1b42bfa..f9fcc1c 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -91,7 +91,7 @@ end program prog
return gnulike_buildtype_linker_args[buildtype]
def split_shlib_to_parts(self, fname):
- return os.path.split(fname)[0], fname
+ return os.path.dirname(fname), fname
def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module)
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index e29d4de..f89e631 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -16,7 +16,7 @@
# Custom logic for several other packages are in separate files.
import os
-import sys
+import re
import stat
import shlex
import shutil
@@ -207,10 +207,12 @@ class ConfigToolDependency(ExternalDependency):
tools = None
tool_name = None
+ __strip_version = re.compile(r'^[0-9.]*')
def __init__(self, name, environment, language, kwargs):
super().__init__('config-tool', environment, language, kwargs)
self.name = name
+ self.native = kwargs.get('native', False)
self.tools = listify(kwargs.get('tools', self.tools))
req_version = kwargs.get('version', None)
@@ -222,6 +224,15 @@ class ConfigToolDependency(ExternalDependency):
return
self.version = version
+ def _sanitize_version(self, version):
+ """Remove any non-numeric, non-point version suffixes."""
+ m = self.__strip_version.match(version)
+ if m:
+ # Ensure that there isn't a trailing '.', such as an input like
+ # `1.2.3.git-1234`
+ return m.group(0).rstrip('.')
+ return version
+
@classmethod
def factory(cls, name, environment, language, kwargs, tools, tool_name):
"""Constructor for use in dependencies that can be found multiple ways.
@@ -250,8 +261,20 @@ class ConfigToolDependency(ExternalDependency):
if not isinstance(versions, list) and versions is not None:
versions = listify(versions)
+ if self.env.is_cross_build() and not self.native:
+ cross_file = self.env.cross_info.config['binaries']
+ try:
+ tools = [cross_file[self.tool_name]]
+ except KeyError:
+ mlog.warning('No entry for {0} specified in your cross file. '
+ 'Falling back to searching PATH. This may find a '
+ 'native version of {0}!'.format(self.tool_name))
+ tools = self.tools
+ else:
+ tools = self.tools
+
best_match = (None, None)
- for tool in self.tools:
+ for tool in tools:
try:
p, out = Popen_safe([tool, '--version'])[:2]
except (FileNotFoundError, PermissionError):
@@ -259,10 +282,10 @@ class ConfigToolDependency(ExternalDependency):
if p.returncode != 0:
continue
- out = out.strip()
+ out = self._sanitize_version(out.strip())
# Some tools, like pcap-config don't supply a version, but also
- # dont fail with --version, in that case just assume that there is
- # only one verison and return it.
+ # don't fail with --version, in that case just assume that there is
+ # only one version and return it.
if not out:
return (tool, 'none')
if versions:
@@ -532,6 +555,14 @@ class PkgConfigDependency(ExternalDependency):
(self.type_string, self.name))
else:
variable = out.strip()
+
+ # pkg-config doesn't distinguish between empty and non-existent variables
+ # use the variable list to check for variable existence
+ if not variable:
+ ret, out = self._call_pkgbin(['--print-variables', self.name])
+ if not re.search(r'^' + variable_name + r'$', out, re.MULTILINE):
+ mlog.warning("pkgconfig variable '%s' not defined for dependency %s." % (variable_name, self.name))
+
mlog.debug('Got pkgconfig variable %s : %s' % (variable_name, variable))
return variable
diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py
index 25316df..c254947 100644
--- a/mesonbuild/dependencies/dev.py
+++ b/mesonbuild/dependencies/dev.py
@@ -146,16 +146,6 @@ class LLVMDependency(ConfigToolDependency):
return
self.static = kwargs.get('static', False)
- # Currently meson doesn't really attempt to handle pre-release versions,
- # so strip the 'svn' off the end, since it will probably cuase problems
- # for users who want the patch version.
- #
- # If LLVM is built from svn then "svn" will be appended to the version
- # string, if it's built from a git mirror then "git-<very short sha>"
- # will be appended instead.
- self.version = self.version.rstrip('svn')
- self.version = self.version.split('git')[0]
-
self.provided_modules = self.get_config_value(['--components'], 'modules')
modules = stringlistify(extract_as_list(kwargs, 'modules'))
self.check_components(modules)
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 9614f1f..542de39 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -63,9 +63,12 @@ from .base import (
# **On Unix**, official packaged versions of boost libraries follow the following schemes:
#
-# Linux / Debian: libboost_<module>.so.1.66.0 -> libboost_<module>.so
-# Linux / Red Hat: libboost_<module>.so.1.66.0 -> libboost_<module>.so
-# Linux / OpenSuse: libboost_<module>.so.1.66.0 -> libboost_<module>.so
+# Linux / Debian: libboost_<module>.so -> libboost_<module>.so.1.66.0
+# Linux / Red Hat: libboost_<module>.so -> libboost_<module>.so.1.66.0
+# Linux / OpenSuse: libboost_<module>.so -> libboost_<module>.so.1.66.0
+# Win / Cygwin: libboost_<module>.dll.a (location = /usr/lib)
+# libboost_<module>.a
+# cygboost_<module>_1_64.dll (location = /usr/bin)
# Mac / homebrew: libboost_<module>.dylib + libboost_<module>-mt.dylib (location = /usr/local/lib)
# Mac / macports: libboost_<module>.dylib + libboost_<module>-mt.dylib (location = /opt/local/lib)
#
@@ -147,6 +150,28 @@ class BoostDependency(ExternalDependency):
self.log_fail()
return
+ if self.check_invalid_modules():
+ return
+
+ mlog.debug('Boost library root dir is', mlog.bold(self.boost_root))
+ mlog.debug('Boost include directory is', mlog.bold(self.incdir))
+
+ self.lib_modules = {}
+ self.detect_version()
+ if self.is_found:
+ self.detect_lib_modules()
+ mlog.debug('Boost library directory is', mlog.bold(self.libdir))
+ for m in self.requested_modules:
+ if 'boost_' + m not in self.lib_modules:
+ mlog.debug('Requested Boost library {!r} not found'.format(m))
+ self.log_fail()
+ self.is_found = False
+ return
+ self.log_success()
+ else:
+ self.log_fail()
+
+ def check_invalid_modules(self):
invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS]
# previous versions of meson allowed include dirs as modules
@@ -163,21 +188,9 @@ class BoostDependency(ExternalDependency):
if invalid_modules:
mlog.log(mlog.red('ERROR:'), 'Invalid Boost modules: ' + ', '.join(invalid_modules))
self.log_fail()
- return
-
- mlog.debug('Boost library root dir is', mlog.bold(self.boost_root))
- mlog.debug('Boost include directory is', mlog.bold(self.incdir))
-
- self.lib_modules = {}
- self.detect_version()
- if self.is_found:
- self.detect_lib_modules()
- mlog.debug('Boost library directory is', mlog.bold(self.libdir))
- self.validate_requested()
- self.log_success()
+ return True
else:
- self.log_fail()
-
+ return False
def log_fail(self):
module_str = ', '.join(self.requested_modules)
@@ -262,12 +275,6 @@ class BoostDependency(ExternalDependency):
raise DependencyException('Boost module argument is not a string.')
return candidates
- def validate_requested(self):
- for m in self.requested_modules:
- if 'boost_' + m not in self.lib_modules:
- msg = 'Requested Boost library {!r} not found'
- raise DependencyException(msg.format(m))
-
def detect_version(self):
try:
version = self.compiler.get_define('BOOST_LIB_VERSION', '#include <boost/version.hpp>', self.env, self.get_compile_args(), [])
@@ -360,15 +367,23 @@ class BoostDependency(ExternalDependency):
fname = os.path.basename(entry)
self.lib_modules[self.modname_from_filename(fname)] = [fname]
+ # - Linux leaves off -mt but libraries are multithreading-aware.
+ # - Cygwin leaves off -mt but libraries are multithreading-aware.
+ # - Mac requires -mt for multithreading, so should not fall back
+ # to non-mt libraries.
+ def abi_tag(self):
+ if mesonlib.for_windows(self.want_cross, self.env):
+ return None
+ if self.is_multithreading and mesonlib.for_darwin(self.want_cross, self.env):
+ return '-mt'
+ else:
+ return ''
+
def detect_lib_modules_nix(self):
all_found = True
for module in self.requested_modules:
- args = None
- libname = 'boost_' + module
- if self.is_multithreading and mesonlib.for_darwin(self.want_cross, self.env):
- # - Linux leaves off -mt but libraries are multithreading-aware.
- # - Mac requires -mt for multithreading, so should not fall back to non-mt libraries.
- libname = libname + '-mt'
+ libname = 'boost_' + module + self.abi_tag()
+
args = self.compiler.find_library(libname, self.env, self.extra_lib_dirs())
if args is None:
mlog.debug('Couldn\'t find library "{}" for boost module "{}"'.format(module, libname))
@@ -417,29 +432,17 @@ class BoostDependency(ExternalDependency):
if modname not in self.lib_modules:
self.lib_modules[modname] = [entry]
- def get_win_link_args(self):
- args = []
- # TODO: should this check self.libdir?
- if self.libdir:
- args.append('-L' + self.libdir)
- for lib in self.requested_modules:
- args += self.lib_modules['boost_' + lib]
- return args
-
def extra_lib_dirs(self):
- dirs = []
- if self.boost_root:
- dirs = [os.path.join(self.boost_root, 'lib')]
- elif self.libdir:
- dirs = [self.libdir]
- return dirs
+ if self.libdir:
+ return [self.libdir]
+ elif self.boost_root:
+ return [os.path.join(self.boost_root, 'lib')]
+ return []
def get_link_args(self):
- if mesonlib.is_windows():
- return self.get_win_link_args()
args = []
for dir in self.extra_lib_dirs():
- args += ['-L' + dir]
+ args += self.compiler.get_linker_search_args(self.libdir)
for lib in self.requested_modules:
args += self.lib_modules['boost_' + lib]
return args
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 0e5dff0..52c670a 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -595,7 +595,7 @@ class Environment:
return self.scratch_dir
def get_depfixer(self):
- path = os.path.split(__file__)[0]
+ path = os.path.dirname(__file__)
return os.path.join(path, 'depfixer.py')
def detect_objc_compiler(self, want_cross):
@@ -977,7 +977,7 @@ class CrossBuildInfo:
def get_properties(self):
return self.config['properties']
- # Wehn compiling a cross compiler we use the native compiler for everything.
+ # When compiling a cross compiler we use the native compiler for everything.
# But not when cross compiling a cross compiler.
def need_cross_compiler(self):
return 'host_machine' in self.config
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index fb29fe9..2273b71 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2017 The Meson development team
+# Copyright 2012-2018 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -36,8 +36,6 @@ from collections import namedtuple
import importlib
-run_depr_printed = False
-
def stringifyUserArguments(args):
if isinstance(args, list):
return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
@@ -1170,6 +1168,7 @@ class MesonMain(InterpreterObject):
'add_postconf_script': self.add_postconf_script_method,
'install_dependency_manifest': self.install_dependency_manifest_method,
'project_version': self.project_version_method,
+ 'project_license': self.project_license_method,
'version': self.version_method,
'project_name': self.project_name_method,
'get_cross_property': self.get_cross_property_method,
@@ -1283,6 +1282,9 @@ class MesonMain(InterpreterObject):
def project_version_method(self, args, kwargs):
return self.build.dep_manifest[self.interpreter.active_projectname]['version']
+ def project_license_method(self, args, kwargs):
+ return self.build.dep_manifest[self.interpreter.active_projectname]['license']
+
def version_method(self, args, kwargs):
return coredata.version
@@ -1379,7 +1381,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
'build_target': build_target_kwargs,
'configure_file': {'input', 'output', 'configuration', 'command', 'install_dir', 'capture', 'install'},
'custom_target': {'input', 'output', 'command', 'install', 'install_dir', 'build_always', 'capture', 'depends', 'depend_files', 'depfile', 'build_by_default'},
- 'dependency': {'default_options', 'fallback', 'language', 'method', 'modules', 'optional_modules', 'native', 'required', 'static', 'version'},
+ 'dependency': {'default_options', 'fallback', 'language', 'main', 'method', 'modules', 'optional_modules', 'native', 'required', 'static', 'version'},
'declare_dependency': {'include_directories', 'link_with', 'sources', 'dependencies', 'compile_args', 'link_args', 'version'},
'executable': exe_kwargs,
'find_program': {'required', 'native'},
@@ -1585,7 +1587,7 @@ class Interpreter(InterpreterBase):
modname = args[0]
if modname.startswith('unstable-'):
plainname = modname.split('-', 1)[1]
- mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases' % modname, location=node)
+ mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node)
modname = 'unstable_' + plainname
if modname not in self.environment.coredata.modules:
try:
@@ -2138,7 +2140,7 @@ to directly access options of other subprojects.''')
return progobj
def func_find_library(self, node, args, kwargs):
- mlog.log(mlog.red('DEPRECATION:'), 'find_library() is removed, use the corresponding method in compiler object instead.')
+ raise InvalidCode('find_library() is removed, use the corresponding method in a compiler object instead.')
def _find_cached_dep(self, name, kwargs):
# Check if we want this as a cross-dep or a native-dep
@@ -2447,15 +2449,8 @@ root and issuing %s.
@permittedKwargs(permitted_kwargs['run_target'])
def func_run_target(self, node, args, kwargs):
- global run_depr_printed
if len(args) > 1:
- if not run_depr_printed:
- mlog.log(mlog.red('DEPRECATION'), 'positional version of run_target is deprecated, use the keyword version instead.')
- run_depr_printed = True
- if 'command' in kwargs:
- raise InterpreterException('Can not have command both in positional and keyword arguments.')
- all_args = args[1:]
- deps = []
+ raise InvalidCode('Run_target takes only one positional argument: the target name.')
elif len(args) == 1:
if 'command' not in kwargs:
raise InterpreterException('Missing "command" keyword argument')
@@ -2686,7 +2681,7 @@ root and issuing %s.
raise InvalidArguments('Exclude argument not a string.')
elif os.path.isabs(f):
raise InvalidArguments('Exclude argument cannot be absolute.')
- exclude_files = {os.path.join(subdir, f) for f in exclude}
+ exclude_files = set(exclude)
else:
exclude_files = set()
if 'exclude_directories' in kwargs:
@@ -2696,7 +2691,7 @@ root and issuing %s.
raise InvalidArguments('Exclude argument not a string.')
elif os.path.isabs(d):
raise InvalidArguments('Exclude argument cannot be absolute.')
- exclude_directories = {os.path.join(subdir, f) for f in exclude}
+ exclude_directories = set(exclude)
else:
exclude_directories = set()
exclude = (exclude_files, exclude_directories)
@@ -2748,7 +2743,7 @@ root and issuing %s.
values = mesonlib.get_filenames_templates_dict([ifile_abs], None)
outputs = mesonlib.substitute_values([output], values)
output = outputs[0]
- if os.path.split(output)[0] != '':
+ if os.path.dirname(output) != '':
raise InterpreterException('Output file name must not contain a subdirectory.')
(ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output))
ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname)
@@ -2765,7 +2760,7 @@ root and issuing %s.
var_list = ", ".join(map(repr, sorted(missing_variables)))
mlog.warning(
"The variable(s) %s in the input file %s are not "
- "present in the given configuration data" % (
+ "present in the given configuration data." % (
var_list, inputfile), location=node)
else:
mesonlib.dump_conf_header(ofile_abs, conf.held_object)
@@ -2986,7 +2981,7 @@ different subdirectory.
norm = os.path.relpath(norm, self.environment.source_dir)
assert(not os.path.isabs(norm))
(num_sps, sproj_name) = self.evaluate_subproject_info(norm, self.subproject_dir)
- plain_filename = os.path.split(norm)[-1]
+ plain_filename = os.path.basename(norm)
if num_sps == 0:
if self.subproject == '':
return
@@ -2999,6 +2994,8 @@ different subdirectory.
def source_strings_to_files(self, sources):
results = []
mesonlib.check_direntry_issues(sources)
+ if not isinstance(sources, list):
+ sources = [sources]
for s in sources:
if isinstance(s, (mesonlib.File, GeneratedListHolder,
CustomTargetHolder, CustomTargetIndexHolder)):
@@ -3015,6 +3012,8 @@ different subdirectory.
def add_target(self, name, tobj):
if name == '':
raise InterpreterException('Target name must not be empty.')
+ if name.strip() == '':
+ raise InterpreterException('Target name must not consist only of whitespace.')
if name.startswith('meson-'):
raise InvalidArguments("Target names starting with 'meson-' are reserved "
"for Meson's internal use. Please rename.")
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index 9dc6b0f..6618dc8 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -74,7 +74,7 @@ class permittedKwargs:
loc = None
for k in kwargs:
if k not in self.permitted:
- mlog.warning('''Passed invalid keyword argument "{}"'''.format(k), location=loc)
+ mlog.warning('''Passed invalid keyword argument "{}".'''.format(k), location=loc)
mlog.warning('This will become a hard error in the future.')
return f(s, node_or_state, args, kwargs)
return wrapped
@@ -265,6 +265,12 @@ class InterpreterBase:
if not isinstance(node.elseblock, mparser.EmptyNode):
self.evaluate_codeblock(node.elseblock)
+ def validate_comparison_types(self, val1, val2):
+ if type(val1) != type(val2):
+ mlog.warning('''Trying to compare values of different types ({}, {}).
+The result of this is undefined and will become a hard error
+in a future Meson release.'''.format(type(val1).__name__, type(val2).__name__))
+
def evaluate_comparison(self, node):
val1 = self.evaluate_statement(node.left)
if is_disabler(val1):
@@ -272,15 +278,11 @@ class InterpreterBase:
val2 = self.evaluate_statement(node.right)
if is_disabler(val2):
return val2
+ self.validate_comparison_types(val1, val2)
if node.ctype == '==':
return val1 == val2
elif node.ctype == '!=':
return val1 != val2
- elif not isinstance(val1, type(val2)):
- raise InterpreterException(
- 'Values of different types ({}, {}) cannot be compared using {}.'.format(type(val1).__name__,
- type(val2).__name__,
- node.ctype))
elif not self.is_elementary_type(val1):
raise InterpreterException('{} can only be compared for equality.'.format(node.left.value))
elif not self.is_elementary_type(val2):
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 4871bf7..a90cb6e 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -576,7 +576,8 @@ def do_conf_file(src, dst, confdata):
return missing_variables
def dump_conf_header(ofilename, cdata):
- with open(ofilename, 'w', encoding='utf-8') as ofile:
+ ofilename_tmp = ofilename + '~'
+ with open(ofilename_tmp, 'w', encoding='utf-8') as ofile:
ofile.write('''/*
* Autogenerated by the Meson build system.
* Do not edit, your changes will be lost.
@@ -598,6 +599,7 @@ def dump_conf_header(ofilename, cdata):
ofile.write('#define %s %s\n\n' % (k, v))
else:
raise MesonException('Unknown data type in configuration file entry: ' + k)
+ replace_if_different(ofilename, ofilename_tmp)
def replace_if_different(dst, dst_tmp):
# If contents are identical, don't touch the file to prevent
@@ -855,7 +857,7 @@ def get_filenames_templates_dict(inputs, outputs):
values['@INPUT{}@'.format(ii)] = vv
if len(inputs) == 1:
# Just one value, substitute @PLAINNAME@ and @BASENAME@
- values['@PLAINNAME@'] = plain = os.path.split(inputs[0])[1]
+ values['@PLAINNAME@'] = plain = os.path.basename(inputs[0])
values['@BASENAME@'] = os.path.splitext(plain)[0]
if outputs:
# Gather values derived from the outputs, similar to above.
@@ -863,7 +865,7 @@ def get_filenames_templates_dict(inputs, outputs):
for (ii, vv) in enumerate(outputs):
values['@OUTPUT{}@'.format(ii)] = vv
# Outdir should be the same for all outputs
- values['@OUTDIR@'] = os.path.split(outputs[0])[0]
+ values['@OUTDIR@'] = os.path.dirname(outputs[0])
# Many external programs fail on empty arguments.
if values['@OUTDIR@'] == '':
values['@OUTDIR@'] = '.'
@@ -893,7 +895,7 @@ def detect_subprojects(spdir_name, current_dir='', result=None):
if not os.path.exists(spdir):
return result
for trial in glob(os.path.join(spdir, '*')):
- basename = os.path.split(trial)[1]
+ basename = os.path.basename(trial)
if trial == 'packagecache':
continue
append_this = True
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index e48122f..619aa39 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -296,8 +296,6 @@ def run(original_args, mainfile=None):
# FALLTHROUGH like it's 1972.
elif cmd_name == 'introspect':
return mintro.run(remaining_args)
- elif cmd_name == 'test':
- return mtest.run(remaining_args)
elif cmd_name == 'rewrite':
return rewriter.run(remaining_args)
elif cmd_name == 'configure':
@@ -368,10 +366,11 @@ def run(original_args, mainfile=None):
app.generate()
except Exception as e:
if isinstance(e, MesonException):
+ mlog.log()
if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'):
- mlog.log(mlog.red('\nMeson encountered an error in file %s, line %d, column %d:' % (e.file, e.lineno, e.colno)))
+ mlog.log('%s:%d:%d:' % (e.file, e.lineno, e.colno), mlog.red('ERROR: '), end='')
else:
- mlog.log(mlog.red('\nMeson encountered an error:'))
+ mlog.log(mlog.red('ERROR: '), end='')
# Error message
mlog.log(e)
# Path to log file
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index b23869f..aaaf8fc 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -49,14 +49,14 @@ parser.add_argument('builddir', nargs='?', help='The build directory')
def determine_installed_path(target, installdata):
install_target = None
for i in installdata.targets:
- if os.path.split(i[0])[1] == target.get_filename(): # FIXME, might clash due to subprojects.
+ if os.path.basename(i[0]) == target.get_filename(): # FIXME, might clash due to subprojects.
install_target = i
break
if install_target is None:
raise RuntimeError('Something weird happened. File a bug.')
fname = i[0]
outdir = i[1]
- outname = os.path.join(installdata.prefix, outdir, os.path.split(fname)[-1])
+ outname = os.path.join(installdata.prefix, outdir, os.path.basename(fname))
# Normalize the path by using os.path.sep consistently, etc.
# Does not change the effective path.
return str(pathlib.PurePath(outname))
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
index aa2ac20..273552d 100644
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -105,12 +105,15 @@ def log(*args, **kwargs):
def warning(*args, **kwargs):
from . import environment
+ args = (yellow('WARNING:'),) + args
+
if kwargs.get('location'):
location = kwargs['location']
del kwargs['location']
- args += ('in file {}, line {}.'.format(os.path.join(location.subdir, environment.build_filename), location.lineno),)
+ location = '{}:{}:'.format(os.path.join(location.subdir, environment.build_filename), location.lineno)
+ args = (location,) + args
- log(yellow('WARNING:'), *args, **kwargs)
+ log(*args, **kwargs)
# Format a list for logging purposes as a string. It separates
# all but the last item with commas, and the last with 'and'.
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 54c2126..5573a2e 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -66,13 +66,15 @@ class DependenciesHelper:
elif hasattr(obj, 'generated_pc'):
processed_reqs.append(obj.generated_pc)
elif isinstance(obj, dependencies.PkgConfigDependency):
- processed_reqs.append(obj.name)
+ if obj.found():
+ processed_reqs.append(obj.name)
elif isinstance(obj, dependencies.ThreadDependency):
processed_libs += obj.get_compiler().thread_link_flags(obj.env)
processed_cflags += obj.get_compiler().thread_flags(obj.env)
elif isinstance(obj, dependencies.Dependency):
- processed_libs += obj.get_link_args()
- processed_cflags += obj.get_compile_args()
+ if obj.found():
+ processed_libs += obj.get_link_args()
+ processed_cflags += obj.get_compile_args()
elif isinstance(obj, (build.SharedLibrary, build.StaticLibrary)):
processed_libs.append(obj)
if public:
diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py
index 54e2c73..f5ce1ed 100644
--- a/mesonbuild/modules/qt.py
+++ b/mesonbuild/modules/qt.py
@@ -73,7 +73,7 @@ class QtBaseModule:
def parse_qrc(self, state, fname):
abspath = os.path.join(state.environment.source_dir, state.subdir, fname)
- relative_part = os.path.split(fname)[0]
+ relative_part = os.path.dirname(fname)
try:
tree = ET.parse(abspath)
root = tree.getroot()
@@ -83,7 +83,7 @@ class QtBaseModule:
mlog.warning("malformed rcc file: ", os.path.join(state.subdir, fname))
break
else:
- result.append(os.path.join(state.subdir, relative_part, child.text))
+ result.append(os.path.join(relative_part, child.text))
return result
except Exception:
return []
@@ -116,7 +116,7 @@ class QtBaseModule:
sources.append(res_target)
else:
for rcc_file in rcc_files:
- basename = os.path.split(rcc_file)[1]
+ basename = os.path.basename(rcc_file)
name = 'qt' + str(self.qt_version) + '-' + basename.replace('.', '_')
rcc_kwargs = {'input': rcc_file,
'output': name + '.cpp',
diff --git a/mesonbuild/modules/unstable_icestorm.py b/mesonbuild/modules/unstable_icestorm.py
new file mode 100644
index 0000000..0b7b339
--- /dev/null
+++ b/mesonbuild/modules/unstable_icestorm.py
@@ -0,0 +1,85 @@
+# Copyright 2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .. import mesonlib, compilers, mlog
+
+from . import ExtensionModule
+
+class IceStormModule(ExtensionModule):
+
+ def __init__(self):
+ super().__init__()
+ self.snippets.add('project')
+ self.yosys_bin = None
+
+ def detect_binaries(self, interpreter):
+ self.yosys_bin = interpreter.func_find_program(None, ['yosys'], {})
+ self.arachne_bin = interpreter.func_find_program(None, ['arachne-pnr'], {})
+ self.icepack_bin = interpreter.func_find_program(None, ['icepack'], {})
+ self.iceprog_bin = interpreter.func_find_program(None, ['iceprog'], {})
+ self.icetime_bin = interpreter.func_find_program(None, ['icetime'], {})
+
+ def project(self, interpreter, state, args, kwargs):
+ if not self.yosys_bin:
+ self.detect_binaries(interpreter)
+ result = []
+ if not len(args):
+ raise mesonlib.MesonException('Project requires at least one argument, which is the project name.')
+ proj_name = args[0]
+ arg_sources = args[1:]
+ if not isinstance(proj_name, str):
+ raise mesonlib.MesonException('Argument must be a string.')
+ kwarg_sources = kwargs.get('sources', [])
+ if not isinstance(kwarg_sources, list):
+ kwarg_sources = [kwarg_sources]
+ all_sources = interpreter.source_strings_to_files(interpreter.flatten(arg_sources + kwarg_sources))
+ if 'constraint_file' not in kwargs:
+ raise mesonlib.MesonException('Constraint file not specified.')
+
+ constraint_file = interpreter.source_strings_to_files(kwargs['constraint_file'])
+ if len(constraint_file) != 1:
+ raise mesonlib.MesonException('Constraint file must contain one and only one entry.')
+ blif_name = proj_name + '_blif'
+ blif_fname = proj_name + '.blif'
+ asc_name = proj_name + '_asc'
+ asc_fname = proj_name + '.asc'
+ bin_name = proj_name + '_bin'
+ bin_fname = proj_name + '.bin'
+ time_name = proj_name + '-time'
+ upload_name = proj_name + '-upload'
+
+ blif_target = interpreter.func_custom_target(None, [blif_name], {
+ 'input': all_sources,
+ 'output': blif_fname,
+ 'command': [self.yosys_bin, '-q', '-p', 'synth_ice40 -blif @OUTPUT@', '@INPUT@']})
+
+ asc_target = interpreter.func_custom_target(None, [asc_name], {
+ 'input': blif_target,
+ 'output': asc_fname,
+ 'command': [self.arachne_bin, '-q', '-d', '1k', '-p', constraint_file, '@INPUT@', '-o', '@OUTPUT@']})
+
+ bin_target = interpreter.func_custom_target(None, [bin_name], {
+ 'input': asc_target,
+ 'output': bin_fname,
+ 'command': [self.icepack_bin, '@INPUT@', '@OUTPUT@'],
+ 'build_by_default' : True})
+
+ up_target = interpreter.func_run_target(None, [upload_name], {
+ 'command': [self.iceprog_bin, bin_target]})
+
+ time_target = interpreter.func_run_target(None, [time_name], {
+ 'command' : [self.icetime_bin, bin_target]})
+
+def initialize():
+ return IceStormModule()
diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py
index eb03393..5df056f 100644
--- a/mesonbuild/mparser.py
+++ b/mesonbuild/mparser.py
@@ -368,7 +368,7 @@ class ArgumentNode:
def set_kwarg(self, name, value):
if name in self.kwargs:
- mlog.warning('Keyword argument "{}" defined multiple times'.format(name), location=self)
+ mlog.warning('Keyword argument "{}" defined multiple times.'.format(name), location=self)
mlog.warning('This will be an error in future Meson releases.')
self.kwargs[name] = value
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index b39f5af..95e532c 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -241,8 +241,8 @@ class TestHarness:
stdout = subprocess.PIPE
stderr = subprocess.PIPE if self.options and self.options.split else subprocess.STDOUT
- if not is_windows():
- setsid = os.setsid
+ if not is_windows():
+ setsid = os.setsid
p = subprocess.Popen(cmd,
stdout=stdout,
@@ -251,6 +251,7 @@ class TestHarness:
cwd=test.workdir,
preexec_fn=setsid)
timed_out = False
+ kill_test = False
if test.timeout is None:
timeout = None
else:
@@ -261,6 +262,11 @@ class TestHarness:
if self.options.verbose:
print("%s time out (After %d seconds)" % (test.name, timeout))
timed_out = True
+ except KeyboardInterrupt:
+ mlog.warning("CTRL-C detected while running %s" % (test.name))
+ kill_test = True
+
+ if kill_test or timed_out:
# Python does not provide multiplatform support for
# killing a process and all its children so we need
# to roll our own.
@@ -438,7 +444,7 @@ TIMEOUT: %4d
logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase)
if self.options.wrapper:
- namebase = os.path.split(self.get_wrapper()[0])[1]
+ namebase = os.path.basename(self.get_wrapper()[0])
elif self.options.setup:
namebase = self.options.setup
diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py
index 25451d4..d1fad11 100644
--- a/mesonbuild/scripts/coverage.py
+++ b/mesonbuild/scripts/coverage.py
@@ -14,7 +14,7 @@
from mesonbuild import environment
-import sys, os, subprocess
+import sys, os, subprocess, pathlib
def remove_dir_from_trace(lcov_command, covfile, dirname):
tmpfile = covfile + '.tmp'
@@ -68,6 +68,15 @@ def coverage(source_root, build_root, log_dir):
'--show-details',
'--branch-coverage',
covinfo])
+ if gcovr_exe:
+ print('')
+ print('XML coverage report can be found at',
+ pathlib.Path(log_dir, 'coverage.xml').as_uri())
+ print('Text coverage report can be found at',
+ pathlib.Path(log_dir, 'coverage.txt').as_uri())
+ if lcov_exe and genhtml_exe:
+ print('Html coverage report can be found at',
+ pathlib.Path(htmloutdir, 'index.html').as_uri())
return 0
def run(args):
diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py
index 30ac54c..f308c5a 100644
--- a/mesonbuild/scripts/gettext.py
+++ b/mesonbuild/scripts/gettext.py
@@ -81,7 +81,7 @@ def do_install(src_sub, bld_sub, dest, pkgname, langs):
srcfile = os.path.join(bld_sub, l + '.gmo')
outfile = os.path.join(dest, l, 'LC_MESSAGES',
pkgname + '.mo')
- os.makedirs(os.path.split(outfile)[0], exist_ok=True)
+ os.makedirs(os.path.dirname(outfile), exist_ok=True)
shutil.copyfile(srcfile, outfile)
shutil.copystat(srcfile, outfile)
print('Installing %s to %s' % (srcfile, outfile))
diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py
index fe1de1f..44e4d69 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -128,20 +128,42 @@ def do_copyfile(from_file, to_file):
selinux_updates.append(to_file)
append_to_log(to_file)
-def do_copydir(data, src_prefix, src_dir, dst_dir, exclude):
+def do_copydir(data, src_dir, dst_dir, exclude):
'''
- Copies the directory @src_prefix (full path) into @dst_dir
-
- @src_dir is simply the parent directory of @src_prefix
+ Copies the contents of directory @src_dir into @dst_dir.
+
+ For directory
+ /foo/
+ bar/
+ excluded
+ foobar
+ file
+ do_copydir(..., '/foo', '/dst/dir', {'bar/excluded'}) creates
+ /dst/
+ dir/
+ bar/
+ foobar
+ file
+
+ Args:
+ src_dir: str, absolute path to the source directory
+ dst_dir: str, absolute path to the destination directory
+ exclude: (set(str), set(str)), tuple of (exclude_files, exclude_dirs),
+ each element of the set is a path relative to src_dir.
'''
+ if not os.path.isabs(src_dir):
+ raise ValueError('src_dir must be absolute, got %s' % src_dir)
+ if not os.path.isabs(dst_dir):
+ raise ValueError('dst_dir must be absolute, got %s' % dst_dir)
if exclude is not None:
exclude_files, exclude_dirs = exclude
else:
exclude_files = exclude_dirs = set()
- for root, dirs, files in os.walk(src_prefix):
+ for root, dirs, files in os.walk(src_dir):
+ assert os.path.isabs(root)
for d in dirs[:]:
- abs_src = os.path.join(src_dir, root, d)
- filepart = abs_src[len(src_dir) + 1:]
+ abs_src = os.path.join(root, d)
+ filepart = os.path.relpath(abs_src, start=src_dir)
abs_dst = os.path.join(dst_dir, filepart)
# Remove these so they aren't visited by os.walk at all.
if filepart in exclude_dirs:
@@ -155,8 +177,8 @@ def do_copydir(data, src_prefix, src_dir, dst_dir, exclude):
data.dirmaker.makedirs(abs_dst)
shutil.copystat(abs_src, abs_dst)
for f in files:
- abs_src = os.path.join(src_dir, root, f)
- filepart = abs_src[len(src_dir) + 1:]
+ abs_src = os.path.join(root, f)
+ filepart = os.path.relpath(abs_src, start=src_dir)
if filepart in exclude_files:
continue
abs_dst = os.path.join(dst_dir, filepart)
@@ -164,10 +186,10 @@ def do_copydir(data, src_prefix, src_dir, dst_dir, exclude):
print('Tried to copy file %s but a directory of that name already exists.' % abs_dst)
if os.path.exists(abs_dst):
os.unlink(abs_dst)
- parent_dir = os.path.split(abs_dst)[0]
+ parent_dir = os.path.dirname(abs_dst)
if not os.path.isdir(parent_dir):
os.mkdir(parent_dir)
- shutil.copystat(os.path.split(abs_src)[0], parent_dir)
+ shutil.copystat(os.path.dirname(abs_src), parent_dir)
shutil.copy2(abs_src, abs_dst, follow_symlinks=False)
append_to_log(abs_dst)
@@ -195,23 +217,19 @@ def do_install(datafilename):
run_install_script(d)
def install_subdirs(d):
- for (src_dir, inst_dir, dst_dir, mode, exclude) in d.install_subdirs:
- if src_dir.endswith('/') or src_dir.endswith('\\'):
- src_dir = src_dir[:-1]
- src_prefix = os.path.join(src_dir, inst_dir)
- print('Installing subdir %s to %s' % (src_prefix, dst_dir))
+ for (src_dir, dst_dir, mode, exclude) in d.install_subdirs:
+ print('Installing subdir %s to %s' % (src_dir, dst_dir))
dst_dir = get_destdir_path(d, dst_dir)
d.dirmaker.makedirs(dst_dir, exist_ok=True)
- do_copydir(d, src_prefix, src_dir, dst_dir, exclude)
- dst_prefix = os.path.join(dst_dir, inst_dir)
- set_mode(dst_prefix, mode)
+ do_copydir(d, src_dir, dst_dir, exclude)
+ set_mode(dst_dir, mode)
def install_data(d):
for i in d.data:
fullfilename = i[0]
outfilename = get_destdir_path(d, i[1])
mode = i[2]
- outdir = os.path.split(outfilename)[0]
+ outdir = os.path.dirname(outfilename)
d.dirmaker.makedirs(outdir, exist_ok=True)
print('Installing %s to %s' % (fullfilename, outdir))
do_copyfile(fullfilename, outfilename)
@@ -221,7 +239,7 @@ def install_man(d):
for m in d.man:
full_source_filename = m[0]
outfilename = get_destdir_path(d, m[1])
- outdir = os.path.split(outfilename)[0]
+ outdir = os.path.dirname(outfilename)
d.dirmaker.makedirs(outdir, exist_ok=True)
print('Installing %s to %s' % (full_source_filename, outdir))
if outfilename.endswith('.gz') and not full_source_filename.endswith('.gz'):
@@ -238,7 +256,7 @@ def install_man(d):
def install_headers(d):
for t in d.headers:
fullfilename = t[0]
- fname = os.path.split(fullfilename)[1]
+ fname = os.path.basename(fullfilename)
outdir = get_destdir_path(d, t[1])
outfilename = os.path.join(outdir, fname)
print('Installing %s to %s' % (fname, outdir))
@@ -304,7 +322,7 @@ def install_targets(d):
for t in d.targets:
fname = check_for_stampfile(t[0])
outdir = get_destdir_path(d, t[1])
- outname = os.path.join(outdir, os.path.split(fname)[-1])
+ outname = os.path.join(outdir, os.path.basename(fname))
aliases = t[2]
should_strip = t[3]
install_rpath = t[4]
@@ -316,7 +334,7 @@ def install_targets(d):
do_copyfile(fname, outname)
if should_strip and d.strip_bin is not None:
if fname.endswith('.jar'):
- print('Not stripping jar target:', os.path.split(fname)[1])
+ print('Not stripping jar target:', os.path.basename(fname))
continue
print('Stripping target {!r}'.format(fname))
ps, stdo, stde = Popen_safe(d.strip_bin + [outname])
@@ -332,7 +350,7 @@ def install_targets(d):
do_copyfile(pdb_filename, pdb_outname)
elif os.path.isdir(fname):
fname = os.path.join(d.build_dir, fname.rstrip('/'))
- do_copydir(d, fname, os.path.dirname(fname), outdir, None)
+ do_copydir(d, fname, os.path.join(outdir, os.path.basename(fname)), None)
else:
raise RuntimeError('Unknown file type for {!r}'.format(fname))
printed_symlink_error = False
@@ -366,7 +384,7 @@ def run(args):
print('Installer script for Meson. Do not run on your own, mmm\'kay?')
print('meson_install.py [install info file]')
datafilename = args[0]
- private_dir = os.path.split(datafilename)[0]
+ private_dir = os.path.dirname(datafilename)
log_dir = os.path.join(private_dir, '../meson-logs')
with open(os.path.join(log_dir, 'install-log.txt'), 'w') as lf:
install_log_file = lf
diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py
index 0bdc417..09a0289 100644
--- a/mesonbuild/wrap/wraptool.py
+++ b/mesonbuild/wrap/wraptool.py
@@ -150,7 +150,7 @@ def do_promotion(from_path, spdir_name):
assert(from_path.endswith('.wrap'))
shutil.copy(from_path, spdir_name)
elif os.path.isdir(from_path):
- sproj_name = os.path.split(from_path)[1]
+ sproj_name = os.path.basename(from_path)
outputdir = os.path.join(spdir_name, sproj_name)
if os.path.exists(outputdir):
sys.exit('Output dir %s already exists. Will not overwrite.' % outputdir)
@@ -178,7 +178,7 @@ def promote(argument):
def status():
print('Subproject status')
for w in glob('subprojects/*.wrap'):
- name = os.path.split(w)[1][:-5]
+ name = os.path.basename(w)[:-5]
try:
(latest_branch, latest_revision) = get_latest_version(name)
except Exception:
diff --git a/run_project_tests.py b/run_project_tests.py
index d191e28..1d17000 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -31,7 +31,7 @@ import argparse
import xml.etree.ElementTree as ET
import time
import multiprocessing
-import concurrent.futures as conc
+from concurrent.futures import ProcessPoolExecutor
import re
from run_unittests import get_fake_options, run_configure
@@ -59,50 +59,6 @@ class TestResult:
self.buildtime = buildtime
self.testtime = testtime
-class DummyFuture(conc.Future):
- '''
- Dummy Future implementation that executes the provided function when you
- ask for the result. Used on platforms where sem_open() is not available:
- MSYS2, OpenBSD, etc: https://bugs.python.org/issue3770
- '''
- def set_function(self, fn, *args, **kwargs):
- self.fn = fn
- self.fn_args = args
- self.fn_kwargs = kwargs
-
- def result(self, **kwargs):
- try:
- result = self.fn(*self.fn_args, **self.fn_kwargs)
- except BaseException as e:
- self.set_exception(e)
- else:
- self.set_result(result)
- return super().result(**kwargs)
-
-
-class DummyExecutor(conc.Executor):
- '''
- Dummy single-thread 'concurrent' executor for use on platforms where
- sem_open is not available: https://bugs.python.org/issue3770
- '''
-
- def __init__(self):
- from threading import Lock
- self._shutdown = False
- self._shutdownLock = Lock()
-
- def submit(self, fn, *args, **kwargs):
- with self._shutdownLock:
- if self._shutdown:
- raise RuntimeError('Cannot schedule new futures after shutdown')
- f = DummyFuture()
- f.set_function(fn, *args, **kwargs)
- return f
-
- def shutdown(self, wait=True):
- with self._shutdownLock:
- self._shutdown = True
-
class AutoDeletedDir:
def __init__(self, d):
@@ -548,11 +504,7 @@ def _run_tests(all_tests, log_name_base, extra_args):
# Remove this once the following issue has been resolved:
# https://github.com/mesonbuild/meson/pull/2082
num_workers *= 2
- try:
- executor = conc.ProcessPoolExecutor(max_workers=num_workers)
- except ImportError:
- print('Platform doesn\'t ProcessPoolExecutor, falling back to single-threaded testing\n')
- executor = DummyExecutor()
+ executor = ProcessPoolExecutor(max_workers=num_workers)
for name, test_cases, skipped in all_tests:
current_suite = ET.SubElement(junit_root, 'testsuite', {'name': name, 'tests': str(len(test_cases))})
diff --git a/run_unittests.py b/run_unittests.py
index f61544f..103847a 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -433,14 +433,8 @@ class BasePlatformTests(unittest.TestCase):
src_root = os.path.dirname(__file__)
src_root = os.path.join(os.getcwd(), src_root)
self.src_root = src_root
- # In case the directory is inside a symlinked directory, find the real
- # path otherwise we might not find the srcdir from inside the builddir.
- self.builddir = os.path.realpath(tempfile.mkdtemp())
- self.logdir = os.path.join(self.builddir, 'meson-logs')
self.prefix = '/usr'
self.libdir = os.path.join(self.prefix, 'lib')
- self.installdir = os.path.join(self.builddir, 'install')
- self.distdir = os.path.join(self.builddir, 'meson-dist')
# Get the backend
# FIXME: Extract this from argv?
self.backend = getattr(Backend, os.environ.get('MESON_UNIT_TEST_BACKEND', 'ninja'))
@@ -449,7 +443,6 @@ class BasePlatformTests(unittest.TestCase):
self.meson_command = meson_command + self.meson_args
self.mconf_command = meson_command + ['configure']
self.mintro_command = meson_command + ['introspect']
- self.mtest_command = meson_command + ['test', '-C', self.builddir]
self.wrap_command = meson_command + ['wrap']
# Backend-specific build commands
self.build_command, self.clean_command, self.test_command, self.install_command, \
@@ -468,6 +461,20 @@ class BasePlatformTests(unittest.TestCase):
# XCode backend is untested with unit tests, help welcome!
self.no_rebuild_stdout = 'UNKNOWN BACKEND {!r}'.format(self.backend.name)
+ self.builddirs = []
+ self.new_builddir()
+
+ def new_builddir(self):
+ # In case the directory is inside a symlinked directory, find the real
+ # path otherwise we might not find the srcdir from inside the builddir.
+ self.builddir = os.path.realpath(tempfile.mkdtemp())
+ self.privatedir = os.path.join(self.builddir, 'meson-private')
+ self.logdir = os.path.join(self.builddir, 'meson-logs')
+ self.installdir = os.path.join(self.builddir, 'install')
+ self.distdir = os.path.join(self.builddir, 'meson-dist')
+ self.mtest_command = meson_command + ['test', '-C', self.builddir]
+ self.builddirs.append(self.builddir)
+
def _print_meson_log(self):
log = os.path.join(self.logdir, 'meson-log.txt')
if not os.path.isfile(log):
@@ -477,10 +484,11 @@ class BasePlatformTests(unittest.TestCase):
print(f.read())
def tearDown(self):
- try:
- windows_proof_rmtree(self.builddir)
- except FileNotFoundError:
- pass
+ for path in self.builddirs:
+ try:
+ windows_proof_rmtree(path)
+ except FileNotFoundError:
+ pass
os.environ = self.orig_env
super().tearDown()
@@ -1702,16 +1710,16 @@ int main(int argc, char **argv) {
self.build()
def test_warning_location(self):
- tdir = os.path.join(self.unit_test_dir, '20 warning location')
+ tdir = os.path.join(self.unit_test_dir, '21 warning location')
out = self.init(tdir)
for expected in [
- r'WARNING: Keyword argument "link_with" defined multiple times in file meson.build, line 4',
- r'WARNING: Keyword argument "link_with" defined multiple times in file sub' + os.path.sep + r'meson.build, line 3',
- r'WARNING: a warning of some sort in file meson.build, line 6',
- r'WARNING: subdir warning in file sub' + os.path.sep + r'meson.build, line 4',
- r'WARNING: Module unstable-simd has no backwards or forwards compatibility and might not exist in future releases in file meson.build, line 7',
- r"WARNING: The variable(s) 'MISSING' in the input file conf.in are not present in the given configuration data in file meson.build, line 10",
- r'WARNING: Passed invalid keyword argument "invalid" in file meson.build, line 1'
+ r'meson.build:4: WARNING: Keyword argument "link_with" defined multiple times.',
+ r'sub' + os.path.sep + r'meson.build:3: WARNING: Keyword argument "link_with" defined multiple times.',
+ r'meson.build:6: WARNING: a warning of some sort',
+ r'sub' + os.path.sep + r'meson.build:4: WARNING: subdir warning',
+ r'meson.build:7: WARNING: Module unstable-simd has no backwards or forwards compatibility and might not exist in future releases.',
+ r"meson.build:10: WARNING: The variable(s) 'MISSING' in the input file conf.in are not present in the given configuration data.",
+ r'meson.build:1: WARNING: Passed invalid keyword argument "invalid".',
]:
self.assertRegex(out, re.escape(expected))
@@ -2059,11 +2067,17 @@ class LinuxlikeTests(BasePlatformTests):
'''
Test that generated pkg-config files correctly handle dependencies
'''
-
testdir = os.path.join(self.common_test_dir, '51 pkgconfig-gen')
self.init(testdir)
+ privatedir1 = self.privatedir
- os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir
+ self.new_builddir()
+ os.environ['PKG_CONFIG_LIBDIR'] = privatedir1
+ testdir = os.path.join(self.common_test_dir, '51 pkgconfig-gen', 'dependencies')
+ self.init(testdir)
+ privatedir2 = self.privatedir
+
+ os.environ['PKG_CONFIG_LIBDIR'] = os.pathsep.join([privatedir1, privatedir2])
cmd = ['pkg-config', 'dependency-test']
out = self._run(cmd + ['--print-requires']).strip().split()
@@ -2085,6 +2099,12 @@ class LinuxlikeTests(BasePlatformTests):
'-llibinternal', '-lcustom2',
'-lfoo']))
+ def test_pkg_unfound(self):
+ testdir = os.path.join(self.unit_test_dir, '22 unfound pkgconfig')
+ self.init(testdir)
+ pcfile = open(os.path.join(self.privatedir, 'somename.pc')).read()
+ self.assertFalse('blub_blob_blib' in pcfile)
+
def test_vala_c_warnings(self):
'''
Test that no warnings are emitted for C code generated by Vala. This
diff --git a/test cases/common/140 get define/meson.build b/test cases/common/140 get define/meson.build
index fd87177..9f5539b 100644
--- a/test cases/common/140 get define/meson.build
+++ b/test cases/common/140 get define/meson.build
@@ -66,8 +66,8 @@ foreach lang : ['c', 'cpp']
if meson.is_cross_build()
# Can't use an empty array as a fallback here because of
# https://github.com/mesonbuild/meson/issues/1481
- lang_args = meson.get_cross_property(lang + '_args', false)
- if lang_args != false
+ lang_args = meson.get_cross_property(lang + '_args', [])
+ if lang_args.length() != 0
foreach lang_arg : lang_args
if lang_arg.contains('MESON_TEST_ISSUE_1665')
run_1665_test = true
diff --git a/test cases/common/175 get project license/bar.c b/test cases/common/175 get project license/bar.c
new file mode 100644
index 0000000..864869b
--- /dev/null
+++ b/test cases/common/175 get project license/bar.c
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+int main(int argc, char **argv) {
+ printf("I'm a main project bar.\n");
+ return 0;
+}
diff --git a/test cases/common/175 get project license/meson.build b/test cases/common/175 get project license/meson.build
new file mode 100644
index 0000000..37303e3
--- /dev/null
+++ b/test cases/common/175 get project license/meson.build
@@ -0,0 +1,8 @@
+project('bar', 'c', license: 'Apache')
+
+executable('bar', 'bar.c')
+
+license = meson.project_license()[0]
+if license != 'Apache'
+ error('The license should be Apache, but it is: ' + license)
+endif
diff --git a/test cases/common/51 pkgconfig-gen/dependencies/exposed.c b/test cases/common/51 pkgconfig-gen/dependencies/exposed.c
new file mode 100644
index 0000000..005202e
--- /dev/null
+++ b/test cases/common/51 pkgconfig-gen/dependencies/exposed.c
@@ -0,0 +1,3 @@
+int exposed_function() {
+ return 42;
+}
diff --git a/test cases/common/51 pkgconfig-gen/dependencies/internal.c b/test cases/common/51 pkgconfig-gen/dependencies/internal.c
new file mode 100644
index 0000000..1a41b11
--- /dev/null
+++ b/test cases/common/51 pkgconfig-gen/dependencies/internal.c
@@ -0,0 +1,3 @@
+int internal_function() {
+ return 42;
+}
diff --git a/test cases/common/51 pkgconfig-gen/dependencies/meson.build b/test cases/common/51 pkgconfig-gen/dependencies/meson.build
new file mode 100644
index 0000000..a767eb5
--- /dev/null
+++ b/test cases/common/51 pkgconfig-gen/dependencies/meson.build
@@ -0,0 +1,38 @@
+project('pkgconfig-gen-dependencies', 'c')
+
+pkgg = import('pkgconfig')
+
+# libmain internally use libinternal and expose libexpose in its API
+exposed_lib = shared_library('libexposed', 'exposed.c')
+internal_lib = shared_library('libinternal', 'internal.c')
+main_lib = shared_library('libmain', link_with : [exposed_lib, internal_lib])
+
+pkgg.generate(libraries : exposed_lib,
+ version : '1.0',
+ name : 'libexposed',
+ description : 'An exposed library in dependency test.'
+)
+
+# Declare a few different Dependency objects
+pc_dep = dependency('libfoo')
+notfound_dep = dependency('notfound', required : false)
+threads_dep = dependency('threads')
+custom_dep = declare_dependency(link_args : ['-lcustom'], compile_args : ['-DCUSTOM'])
+custom2_dep = declare_dependency(link_args : ['-lcustom2'], compile_args : ['-DCUSTOM2'])
+
+# Generate a PC file:
+# - Having libmain in libraries should pull implicitely libexposed and libinternal in Libs.private
+# - Having libexposed in libraries should remove it from Libs.private
+# - We generated a pc file for libexposed so it should be in Requires instead of Libs
+# - Having threads_dep in libraries should add '-pthread' in both Libs and Cflags
+# - Having custom_dep in libraries and libraries_private should only add it in Libs
+# - Having custom2_dep in libraries_private should not add its Cflags
+# - Having pc_dep in libraries_private should add it in Requires.private
+# - notfound_dep is not required so it shouldn't appear in the pc file.
+pkgg.generate(libraries : [main_lib, exposed_lib, threads_dep , custom_dep],
+ libraries_private : [custom_dep, custom2_dep, pc_dep, notfound_dep],
+ version : '1.0',
+ name : 'dependency-test',
+ filebase : 'dependency-test',
+ description : 'A dependency test.'
+)
diff --git a/test cases/common/51 pkgconfig-gen/meson.build b/test cases/common/51 pkgconfig-gen/meson.build
index a8dd092..f9d7f7f 100644
--- a/test cases/common/51 pkgconfig-gen/meson.build
+++ b/test cases/common/51 pkgconfig-gen/meson.build
@@ -46,36 +46,3 @@ pkgg.generate(
description : 'A foo library.',
variables : ['foo=bar', 'datadir=${prefix}/data']
)
-
-# libmain internally use libinternal and expose libexpose in its API
-exposed_lib = shared_library('libexposed', 'simple.c')
-internal_lib = shared_library('libinternal', 'simple.c')
-main_lib = shared_library('libmain', link_with : [exposed_lib, internal_lib])
-
-pkgg.generate(libraries : exposed_lib,
- version : libver,
- name : 'libexposed',
- description : 'An exposed library in dependency test.'
-)
-
-# Declare a few different Dependency objects
-pc_dep = dependency('libfoo', required : false)
-threads_dep = dependency('threads', required : false)
-custom_dep = declare_dependency(link_args : ['-lcustom'], compile_args : ['-DCUSTOM'])
-custom2_dep = declare_dependency(link_args : ['-lcustom2'], compile_args : ['-DCUSTOM2'])
-
-# Generate a PC file:
-# - Having libmain in libraries should pull implicitely libexposed and libinternal in Libs.private
-# - Having libexposed in libraries should remove it from Libs.private
-# - We generated a pc file for libexposed so it should be in Requires instead of Libs
-# - Having threads_dep in libraries should add '-pthread' in both Libs and Cflags
-# - Having custom_dep in libraries and libraries_private should only add it in Libs
-# - Having custom2_dep in libraries_private should not add its Cflags
-# - Having pc_dep in libraries_private should add it in Requires.private
-pkgg.generate(libraries : [main_lib, exposed_lib, threads_dep , custom_dep],
- libraries_private : [custom_dep, custom2_dep, pc_dep],
- version : libver,
- name : 'dependency-test',
- filebase : 'dependency-test',
- description : 'A dependency test.'
-)
diff --git a/test cases/common/58 run target/meson.build b/test cases/common/58 run target/meson.build
index 686db1f..93a4ad0 100644
--- a/test cases/common/58 run target/meson.build
+++ b/test cases/common/58 run target/meson.build
@@ -1,8 +1,5 @@
project('run target', 'c')
-# deprecated format, fix once we remove support for it.
-run_target('mycommand','scripts/script.sh')
-
# Make it possible to run built programs.
# In cross builds exe_wrapper should be added if it exists.
diff --git a/test cases/common/90 identical target name in subproject/meson.build b/test cases/common/90 identical target name in subproject/meson.build
index 98e4891..e804d3c 100644
--- a/test cases/common/90 identical target name in subproject/meson.build
+++ b/test cases/common/90 identical target name in subproject/meson.build
@@ -3,4 +3,4 @@ project('toplevel bar', 'c')
subproject('foo')
executable('bar', 'bar.c')
-run_target('nop', 'true')
+run_target('nop', command : ['true'])
diff --git a/test cases/common/90 identical target name in subproject/subprojects/foo/meson.build b/test cases/common/90 identical target name in subproject/subprojects/foo/meson.build
index a7a31b1..3f22337 100644
--- a/test cases/common/90 identical target name in subproject/subprojects/foo/meson.build
+++ b/test cases/common/90 identical target name in subproject/subprojects/foo/meson.build
@@ -1,4 +1,4 @@
project('subfoo', 'c')
executable('bar', 'bar.c')
-run_target('nop', 'true')
+run_target('nop', command : ['true'])
diff --git a/test cases/failing/68 subproj different versions/meson.build b/test cases/failing/68 subproj different versions/meson.build
index 7690277..e964e42 100644
--- a/test cases/failing/68 subproj different versions/meson.build
+++ b/test cases/failing/68 subproj different versions/meson.build
@@ -3,7 +3,7 @@ project('super', 'c')
# A will use version 1 of C
a_dep = dependency('a', fallback: ['a', 'a_dep'])
-# B will fail becuase it requests version 2 of C
+# B will fail because it requests version 2 of C
b_dep = dependency('b', fallback: ['b', 'b_dep'])
main = executable('main', files('main.c'), dependencies: [a_dep, b_dep])
diff --git a/test cases/fpga/1 simple/meson.build b/test cases/fpga/1 simple/meson.build
new file mode 100644
index 0000000..eff8088
--- /dev/null
+++ b/test cases/fpga/1 simple/meson.build
@@ -0,0 +1,9 @@
+project('lattice', 'c')
+
+is = import('unstable_icestorm')
+
+is.project('spin',
+ 'spin.v',
+ constraint_file : 'spin.pcf',
+)
+
diff --git a/test cases/fpga/1 simple/spin.pcf b/test cases/fpga/1 simple/spin.pcf
new file mode 100644
index 0000000..de06f5d
--- /dev/null
+++ b/test cases/fpga/1 simple/spin.pcf
@@ -0,0 +1,6 @@
+set_io LED1 99
+set_io LED2 98
+set_io LED3 97
+set_io LED4 96
+set_io LED5 95
+set_io clk 21
diff --git a/test cases/fpga/1 simple/spin.v b/test cases/fpga/1 simple/spin.v
new file mode 100644
index 0000000..edc40c4
--- /dev/null
+++ b/test cases/fpga/1 simple/spin.v
@@ -0,0 +1,32 @@
+
+module top(input clk, output LED1, output LED2, output LED3, output LED4, output LED5);
+
+ reg ready = 0;
+ reg [23:0] divider;
+ reg [3:0] spin;
+
+ always @(posedge clk) begin
+ if (ready)
+ begin
+ if (divider == 6000000)
+ begin
+ divider <= 0;
+ spin <= {spin[2], spin[3], spin[0], spin[1]};
+ end
+ else
+ divider <= divider + 1;
+ end
+ else
+ begin
+ ready <= 1;
+ spin <= 4'b1010;
+ divider <= 0;
+ end
+ end
+
+ assign LED1 = spin[0];
+ assign LED2 = spin[1];
+ assign LED3 = spin[2];
+ assign LED4 = spin[3];
+ assign LED5 = 1;
+endmodule
diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build
index 7c33268..b0e848d 100644
--- a/test cases/frameworks/4 qt/meson.build
+++ b/test cases/frameworks/4 qt/meson.build
@@ -92,5 +92,8 @@ foreach qt : ['qt4', 'qt5']
plugin = library(qt + 'plugin', 'plugin/plugin.cpp', pluginpreprocess,
include_directories : plugin_includes,
dependencies : qtcore)
+ if qt == 'qt5'
+ subdir('subfolder')
+ endif
endif
endforeach
diff --git a/test cases/frameworks/4 qt/subfolder/main.cpp b/test cases/frameworks/4 qt/subfolder/main.cpp
new file mode 100644
index 0000000..61cc9d4
--- /dev/null
+++ b/test cases/frameworks/4 qt/subfolder/main.cpp
@@ -0,0 +1,10 @@
+#include <QImage>
+
+int main(int argc, char **argv) {
+ Q_INIT_RESOURCE(stuff3);
+ QImage qi(":/thing.png");
+ if(qi.width() != 640) {
+ return 1;
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/test cases/frameworks/4 qt/subfolder/meson.build b/test cases/frameworks/4 qt/subfolder/meson.build
new file mode 100644
index 0000000..d3ff609
--- /dev/null
+++ b/test cases/frameworks/4 qt/subfolder/meson.build
@@ -0,0 +1,4 @@
+
+qresources = qtmodule.preprocess(qresources : 'resources/stuff3.qrc')
+
+app = executable('subfolder', 'main.cpp', qresources, dependencies : qtdep)
diff --git a/test cases/frameworks/4 qt/subfolder/resources/stuff3.qrc b/test cases/frameworks/4 qt/subfolder/resources/stuff3.qrc
new file mode 100644
index 0000000..fdfb58e
--- /dev/null
+++ b/test cases/frameworks/4 qt/subfolder/resources/stuff3.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file>thing.png</file>
+ </qresource>
+</RCC>
diff --git a/test cases/frameworks/4 qt/subfolder/resources/thing.png b/test cases/frameworks/4 qt/subfolder/resources/thing.png
new file mode 100644
index 0000000..4b001bd
--- /dev/null
+++ b/test cases/frameworks/4 qt/subfolder/resources/thing.png
Binary files differ
diff --git a/test cases/unit/20 warning location/a.c b/test cases/unit/21 warning location/a.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/a.c
+++ b/test cases/unit/21 warning location/a.c
diff --git a/test cases/unit/20 warning location/b.c b/test cases/unit/21 warning location/b.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/b.c
+++ b/test cases/unit/21 warning location/b.c
diff --git a/test cases/unit/20 warning location/conf.in b/test cases/unit/21 warning location/conf.in
index a2903ed..a2903ed 100644
--- a/test cases/unit/20 warning location/conf.in
+++ b/test cases/unit/21 warning location/conf.in
diff --git a/test cases/unit/20 warning location/main.c b/test cases/unit/21 warning location/main.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/main.c
+++ b/test cases/unit/21 warning location/main.c
diff --git a/test cases/unit/20 warning location/meson.build b/test cases/unit/21 warning location/meson.build
index 15295a9..15295a9 100644
--- a/test cases/unit/20 warning location/meson.build
+++ b/test cases/unit/21 warning location/meson.build
diff --git a/test cases/unit/20 warning location/sub/c.c b/test cases/unit/21 warning location/sub/c.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/sub/c.c
+++ b/test cases/unit/21 warning location/sub/c.c
diff --git a/test cases/unit/20 warning location/sub/d.c b/test cases/unit/21 warning location/sub/d.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/sub/d.c
+++ b/test cases/unit/21 warning location/sub/d.c
diff --git a/test cases/unit/20 warning location/sub/meson.build b/test cases/unit/21 warning location/sub/meson.build
index 27f6778..27f6778 100644
--- a/test cases/unit/20 warning location/sub/meson.build
+++ b/test cases/unit/21 warning location/sub/meson.build
diff --git a/test cases/unit/20 warning location/sub/sub.c b/test cases/unit/21 warning location/sub/sub.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/sub/sub.c
+++ b/test cases/unit/21 warning location/sub/sub.c
diff --git a/test cases/unit/22 unfound pkgconfig/meson.build b/test cases/unit/22 unfound pkgconfig/meson.build
new file mode 100644
index 0000000..1285c0a
--- /dev/null
+++ b/test cases/unit/22 unfound pkgconfig/meson.build
@@ -0,0 +1,15 @@
+project('foobar', 'c')
+
+unfound = dependency('blub_blob_blib', required : false)
+
+pkgg = import('pkgconfig')
+
+l = shared_library('somename', 'some.c',
+ dependencies : unfound)
+
+pkgg.generate(
+ libraries : l,
+ name : 'somename',
+ version : '1.0.0',
+ description : 'A test library.',
+)
diff --git a/test cases/unit/22 unfound pkgconfig/some.c b/test cases/unit/22 unfound pkgconfig/some.c
new file mode 100644
index 0000000..fb765fb
--- /dev/null
+++ b/test cases/unit/22 unfound pkgconfig/some.c
@@ -0,0 +1,3 @@
+int some() {
+ return 6;
+}