aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/syntax-highlighting/vim/syntax/meson.vim4
-rw-r--r--docs/markdown/Build-options.md36
-rw-r--r--docs/markdown/Configuration.md28
-rw-r--r--docs/markdown/Dependencies.md4
-rw-r--r--docs/markdown/Generating-sources.md4
-rw-r--r--docs/markdown/Gnome-module.md19
-rw-r--r--docs/markdown/Installing.md2
-rw-r--r--docs/markdown/Reference-manual.md6
-rw-r--r--docs/markdown/Release-notes-for-0.38.0.md2
-rw-r--r--docs/markdown/Style-guide.md36
-rw-r--r--docs/markdown/Subprojects.md4
-rw-r--r--docs/markdown/Users.md24
-rw-r--r--docs/markdown/Using-wraptool.md22
-rw-r--r--docs/markdown/_Sidebar.md2
-rw-r--r--docs/markdown/i18n-module.md2
-rw-r--r--docs/markdown/snippets/intopt.md6
-rw-r--r--docs/markdown/snippets/yield.md8
-rw-r--r--docs/sitemap.txt1
-rw-r--r--mesonbuild/backend/backends.py23
-rw-r--r--mesonbuild/compilers/c.py2
-rw-r--r--mesonbuild/compilers/compilers.py7
-rw-r--r--mesonbuild/coredata.py36
-rw-r--r--mesonbuild/dependencies/base.py64
-rw-r--r--mesonbuild/dependencies/misc.py120
-rw-r--r--mesonbuild/dependencies/ui.py104
-rw-r--r--mesonbuild/interpreter.py41
-rw-r--r--mesonbuild/mesonmain.py9
-rw-r--r--mesonbuild/mintro.py2
-rw-r--r--mesonbuild/modules/gnome.py4
-rw-r--r--mesonbuild/mtest.py6
-rw-r--r--mesonbuild/optinterpreter.py79
-rw-r--r--mesonbuild/scripts/coverage.py17
-rw-r--r--mesonbuild/wrap/wrap.py13
-rw-r--r--test cases/common/15 mixed pch/meson.build19
-rw-r--r--test cases/common/174 dependency factory/meson.build51
-rw-r--r--test cases/common/176 yield/meson.build6
-rw-r--r--test cases/common/176 yield/meson_options.txt2
-rw-r--r--test cases/common/176 yield/subprojects/sub/meson.build4
-rw-r--r--test cases/common/176 yield/subprojects/sub/meson_options.txt2
-rw-r--r--test cases/common/47 options/meson.build4
-rw-r--r--test cases/common/47 options/meson_options.txt1
-rw-r--r--test cases/linuxlike/1 pkg-config/meson.build2
-rw-r--r--test cases/unit/19 bad command line options/subprojects/one/meson.build2
43 files changed, 563 insertions, 267 deletions
diff --git a/data/syntax-highlighting/vim/syntax/meson.vim b/data/syntax-highlighting/vim/syntax/meson.vim
index e06b2df..83dd66a 100644
--- a/data/syntax-highlighting/vim/syntax/meson.vim
+++ b/data/syntax-highlighting/vim/syntax/meson.vim
@@ -29,7 +29,7 @@ endif
let s:cpo_save = &cpo
setlocal cpo&vim
-" https://github.com/mesonbuild/meson/wiki/Syntax
+" http://mesonbuild.com/Syntax.html
syn keyword mesonConditional elif else if endif
syn keyword mesonRepeat foreach endforeach
syn keyword mesonOperator and not or
@@ -55,7 +55,7 @@ syn match mesonEscape "\\N{\a\+\%(\s\a\+\)*}" contained
syn match mesonEscape "\\$"
" Meson only supports integer numbers
-" https://github.com/mesonbuild/meson/wiki/Syntax#numbers
+" http://mesonbuild.com/Syntax.html#numbers
syn match mesonNumber "\<\d\+\>"
" booleans
diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md
index cd7f07d..9ccdf83 100644
--- a/docs/markdown/Build-options.md
+++ b/docs/markdown/Build-options.md
@@ -16,6 +16,7 @@ Here is a simple option file.
option('someoption', type : 'string', value : 'optval', description : 'An option')
option('other_one', type : 'boolean', value : false)
option('combo_opt', type : 'combo', choices : ['one', 'two', 'three'], value : 'three')
+option('integer_opt', type : 'integer', min : 0, max : 5, value : 3) # Since 0.45.0
option('free_array_opt', type : 'array', value : ['one', 'two'])
option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two'])
```
@@ -39,6 +40,14 @@ A combo allows any one of the values in the `choices` parameter to be
selected. If no default value is set then the first value will be the
default.
+## Integers
+
+An integer option contains a single integer with optional upper and
+lower values that are specified with the `min` and `max` keyword
+arguments.
+
+This type is available since Meson version 0.45.0.
+
### Arrays
Arrays represent an array of strings. By default the array can contain
@@ -49,7 +58,7 @@ empty. The `value` parameter specifies the default value of the option
and if it is unset then the values of `choices` will be used as the
default.
-This type is new in version 0.44.0
+This type is available since version 0.44.0
## Using build options
@@ -98,6 +107,31 @@ $ meson configure "-Doption=['a,b', 'c,d']"
The inner values must always be single quotes and the outer ones
double quotes.
+To change values in subprojects prepend the name of the subproject and
+a colon:
+
+```console
+$ meson configure -Dsubproject:option=newvalue
+```
+
**NOTE:** If you cannot call `meson configure` you likely have a old
version of Meson. In that case you can call `mesonconf` instead, but
that is deprecated in newer versions
+
+## Yielding to superproject option
+
+Suppose you have a master project and a subproject. In some cases it
+might be useful to have an option that has the same value in both of
+them. This can be achieved with the `yield` keyword. Suppose you have
+an option definition like this:
+
+```meson
+option('some_option', type : 'string', value : 'value', yield : true)
+```
+
+If you build this project on its own, this option behaves like
+usual. However if you build this project as a subproject of another
+project which also has an option called `some_option`, then calling
+`get_option` returns the value of the superproject. If the value of
+`yield` is `false`, `get_option` returns the value of the subproject's
+option.
diff --git a/docs/markdown/Configuration.md b/docs/markdown/Configuration.md
index 9db6370..d8fa54e 100644
--- a/docs/markdown/Configuration.md
+++ b/docs/markdown/Configuration.md
@@ -58,7 +58,7 @@ Note that if you want to define a C string, you need to do the quoting
yourself like this:
```meson
-conf.set('TOKEN', '"value"')
+conf_data.set('TOKEN', '"value"')
```
Since this is such a common operation, Meson provides a convenience
@@ -66,7 +66,7 @@ method:
```meson
plain_var = 'value'
-conf.set_quoted('TOKEN', plain_var) # becomes #define TOKEN "value"
+conf_data.set_quoted('TOKEN', plain_var) # becomes #define TOKEN "value"
```
Often you have a boolean value in Meson but need to define the C/C++
@@ -74,12 +74,12 @@ token as 0 or 1. Meson provides a convenience function for this use
case.
```meson
-conf.set10(token, boolean_value)
+conf_data.set10(token, boolean_value)
# The line above is equivalent to this:
if boolean_value
- conf.set(token, 1)
+ conf_data.set(token, 1)
else
- conf.set(token, 0)
+ conf_data.set(token, 0)
endif
```
@@ -90,19 +90,19 @@ file all the entries in the configuration data object. The
replacements are the same as when generating `#mesondefine` entries:
```meson
-cdata.set('FOO', '"string"') => #define FOO "string"
-cdata.set('FOO', 'a_token') => #define FOO a_token
-cdata.set('FOO', true) => #define FOO
-cdata.set('FOO', false) => #undef FOO
-cdata.set('FOO', 1) => #define FOO 1
-cdata.set('FOO', 0) => #define FOO 0
+conf_data.set('FOO', '"string"') => #define FOO "string"
+conf_data.set('FOO', 'a_token') => #define FOO a_token
+conf_data.set('FOO', true) => #define FOO
+conf_data.set('FOO', false) => #undef FOO
+conf_data.set('FOO', 1) => #define FOO 1
+conf_data.set('FOO', 0) => #define FOO 0
```
In this mode, you can also specify a comment which will be placed
before the value so that your generated files are self-documenting.
```meson
-cdata.set('BAR', true, description : 'Set BAR if it is available')
+conf_data.set('BAR', true, description : 'Set BAR if it is available')
```
Will produce:
@@ -129,9 +129,11 @@ subprojects.
At the top level we generate the file:
```meson
+conf_data = configuration_data()
+# Set data
configure_file(input : 'projconfig.h.in',
output : 'projconfig.h',
- configuration : cdata_object)
+ configuration : conf_data)
```
Immediately afterwards we generate the include object.
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md
index 189db72..6653cc1 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -89,12 +89,16 @@ to build dependencies manually when they are not.
To make this work, the dependency must have Meson build definitions
and it must declare its own dependency like this:
+```meson
foo_dep = declare_dependency(...)
+```
Then any project that wants to use it can write out the following
declaration in their main `meson.build` file.
+```meson
foo_dep = dependency('foo', fallback : ['foo', 'foo_dep'])
+```
What this declaration means is that first Meson tries to look up the
dependency from the system (such as by using pkg-config). If it is not
diff --git a/docs/markdown/Generating-sources.md b/docs/markdown/Generating-sources.md
index ae1302b..2ea1021 100644
--- a/docs/markdown/Generating-sources.md
+++ b/docs/markdown/Generating-sources.md
@@ -4,7 +4,7 @@ short-description: Generation of source files before compilation
# Generating sources
- Sometimes source files need to be preprocessed before they are passed to the actual compiler. As an example you might want build an IDL compiler and then run some files through that to generate actual source files. In Meson this is done with [`generator()`](https://github.com/mesonbuild/meson/wiki/Reference-manual#generator) or [`custom_target()`](https://github.com/mesonbuild/meson/wiki/Reference-manual#custom_target).
+ Sometimes source files need to be preprocessed before they are passed to the actual compiler. As an example you might want build an IDL compiler and then run some files through that to generate actual source files. In Meson this is done with [`generator()`](Reference-manual.md#generator) or [`custom_target()`](Reference-manual.md#custom_target).
## Using custom_target()
@@ -45,7 +45,7 @@ Generators are similar to custom targets, except that we define a *generator*, w
Note that generators should only be used for outputs that will only be used as inputs for a build target or a custom target. When you use the processed output of a generator in multiple targets, the generator will be run multiple times to create outputs for each target. Each output will be created in a target-private directory `@BUILD_DIR@`.
-If you want to generate files for general purposes such as for generating headers to be used by several sources, or data that will be installed, and so on, use a [`custom_target()`](https://github.com/mesonbuild/meson/wiki/Reference-manual#custom_target) instead.
+If you want to generate files for general purposes such as for generating headers to be used by several sources, or data that will be installed, and so on, use a [`custom_target()`](Reference-manual.md#custom_target) instead.
```meson
diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md
index b33009d..fbf9530 100644
--- a/docs/markdown/Gnome-module.md
+++ b/docs/markdown/Gnome-module.md
@@ -46,6 +46,25 @@ file called `foobar.h`, which you can then include in your sources.
Returns an array containing: `[c_source, header_file]` or
`[gresource_bundle]`
+Example:
+
+```meson
+gnome = import('gnome')
+
+asresources = gnome.compile_resources(
+ 'as-resources', 'data/asresources.gresource.xml',
+ source_dir: 'data',
+ c_name: 'as'
+)
+
+executable(
+ meson.project_name(),
+ asresources,
+ dependencies: my_deps,
+ install: true
+)
+```
+
### gnome.generate_gir()
Generates GObject introspection data. Takes one positional argument,
diff --git a/docs/markdown/Installing.md b/docs/markdown/Installing.md
index 2663ff4..4670544 100644
--- a/docs/markdown/Installing.md
+++ b/docs/markdown/Installing.md
@@ -26,7 +26,7 @@ Other install commands are the following.
```meson
install_headers('header.h', subdir : 'projname') # -> include/projname/header.h
install_man('foo.1') # -> share/man/man1/foo.1.gz
-install_data('datafile.cat', install_dir : join_paths(get_option('datadir'), 'progname')) # -> share/progname/datafile.dat
+install_data('datafile.dat', install_dir : join_paths(get_option('datadir'), 'progname')) # -> share/progname/datafile.dat
```
Sometimes you want to copy an entire subtree directly. For this use case there is the `install_subdir` command, which can be used like this.
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index ca28643..a557f0c 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -416,7 +416,7 @@ be passed to [shared and static libraries](#library).
dynamically exported, allowing modules built using the
[`shared_module`](#shared_module) function to refer to functions,
variables and other symbols defined in the executable itself. Implies
- the `implib` argument. Since 0.44.0
+ the `implib` argument. Since 0.45.0
- `implib` when set to true, an import library is generated for the
executable (the name of the import library is based on *exe_name*).
Alternatively, when set to a string, that gives the base name for
@@ -1585,7 +1585,7 @@ The following methods are defined for all [arrays](Syntax.md#arrays):
- `length()`, the size of the array
You can also iterate over arrays with the [`foreach`
-statement](https://github.com/mesonbuild/meson/wiki/Syntax#foreach-statements).
+statement](Syntax.md#foreach-statements).
## Returned objects
@@ -1682,6 +1682,8 @@ an external dependency with the following methods:
dependency, error out. (*Added 0.44.0*) You can also redefine a
variable by passing a list to the `define_variable` parameter
that can affect the retrieved variable: `['prefix', '/'])`.
+ (*Added 0.45.0*) A warning is issued if the variable is not defined,
+ unless a `default` parameter is specified.
- `get_configtool_variable(varname)` (*Added 0.44.0*) will get the
command line argument from the config tool (with `--` prepended), or,
diff --git a/docs/markdown/Release-notes-for-0.38.0.md b/docs/markdown/Release-notes-for-0.38.0.md
index ca6602e..741c349 100644
--- a/docs/markdown/Release-notes-for-0.38.0.md
+++ b/docs/markdown/Release-notes-for-0.38.0.md
@@ -78,7 +78,7 @@ When using compilers that implement the [`__has_include()` preprocessor macro](h
# Array indexing now supports fallback values
-The second argument to the array [`.get()`](https://github.com/mesonbuild/meson/wiki/Reference-manual#array-object) function is now returned if the specified index could not be found
+The second argument to the array [`.get()`](Reference-manual.md#array-object) function is now returned if the specified index could not be found
```meson
array = [10, 11, 12, 13]
array.get(0) # this will return `10`
diff --git a/docs/markdown/Style-guide.md b/docs/markdown/Style-guide.md
new file mode 100644
index 0000000..9008592
--- /dev/null
+++ b/docs/markdown/Style-guide.md
@@ -0,0 +1,36 @@
+---
+short-description: Style recommendations for Meson files
+...
+
+# Style recommendations
+
+This page lists some recommendations on organizing and formatting your
+Meson build files.
+
+## Tabs or spaces?
+
+Always spaces.
+
+## Naming options
+
+There are two ways of naming project options. As an example for
+booleans the first one is `foo` and the second one is
+`enable-foo`. The former style is recommended, because in Meson
+options have strong type, rather than being just strings.
+
+You should try to name options the same as is common in other
+projects. This is especially important for yielding options, because
+they require that both the parent and subproject options have the same
+name.
+
+# Global arguments
+
+Prefer `add_project_arguments` to `add_global_arguments` because using
+the latter prevents using the project as a subproject.
+
+# Cross compilation arguments
+
+Try to keep cross compilation arguments away from your build files as
+much as possible. Keep them in the cross file instead. This adds
+portability, since all changes needed to compile to a different
+platform are isolated in one place.
diff --git a/docs/markdown/Subprojects.md b/docs/markdown/Subprojects.md
index 14f01d4..0d1442e 100644
--- a/docs/markdown/Subprojects.md
+++ b/docs/markdown/Subprojects.md
@@ -18,7 +18,7 @@ becomes a transparent part of the project. The basic idiom goes
something like this.
```meson
-dep = dependency('foo', fallback : [subproject_name, variable_name]
+dep = dependency('foo', fallback : [subproject_name, variable_name])
```
As an example, suppose we have a simple project that provides a shared
@@ -40,7 +40,7 @@ this.
```meson
project('master', 'c')
-dep = dependency('simple', fallback : ['simple', 'simple_dep']
+dep = dependency('simple', fallback : ['simple', 'simple_dep'])
exe = executable('prog', 'prog.c',
dependencies : dep, install : true)
```
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index 0b7734d..1665922 100644
--- a/docs/markdown/Users.md
+++ b/docs/markdown/Users.md
@@ -10,9 +10,13 @@ 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
+ - [cinnamon-desktop](https://github.com/linuxmint/cinnamon-desktop), the cinnamon desktop library
+ - [dbus-broker](https://github.com/bus1/dbus-broker), Linux D-Bus Message Broker
- [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
+ - [DXVK](https://github.com/doitsujin/dxvk), a Vulkan-based Direct3D 11 implementation for Linux using Wine
- [Emeus](https://github.com/ebassi/emeus), Constraint based layout manager for GTK+
- [Frida](https://www.frida.re/), a dynamic binary instrumentation toolkit
+ - [fwupd](https://github.com/hughsie/fwupd), a simple daemon to allow session software to update firmware
- [Geary](https://wiki.gnome.org/Apps/Geary), an email application built around conversations, for the GNOME 3 desktop.
- [GLib](https://git.gnome.org/browse/glib/), cross-platform C library used by GTK+ and GStreamer (not the default yet)
- [Gnome Builder](https://git.gnome.org/browse/gnome-builder/), an IDE for the Gnome platform
@@ -25,31 +29,45 @@ If you have a project that uses Meson that you want to add to this list, let us
- [GStreamer](https://cgit.freedesktop.org/gstreamer/gstreamer/), multimedia framework (not the default yet)
- [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
+ - [Hardcode-Tray](https://github.com/bil-elmoussaoui/Hardcode-Tray), fixes hardcoded tray icons in Linux
- [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.
+ - [JsonCpp](https://github.com/open-source-parsers/jsoncpp), a C++ library for interacting with JSON
- [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
+ - [libfuse](https://github.com/libfuse/libfuse), the reference implementation of the Linux FUSE (Filesystem in Userspace) interface
- [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
+ - [Libosmscout](https://github.com/Framstag/libosmscout), a C++ library for offline map rendering, routing and location
+lookup based on OpenStreetMap data
+ - [Libva](https://github.com/intel/libva), an implementation for the VA (VIdeo Acceleration) API
- [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
+ - [MiracleCast](https://github.com/albfan/miraclecast), connect external monitors to your system via Wifi-Display specification aka Miracast
+ - [Nautilus](https://git.gnome.org/browse/nautilus/commit/?id=ed5652c89ac0654df2e82b54b00b27d51c825465), the Gnome file manager
+ - [Nemo](https://github.com/linuxmint/nemo), the file manager for the Cinnamon desktop environment
- [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
+ - [Pithos](https://github.com/pithos/pithos), a Pandora Radio client
- [Pitivi](http://pitivi.org/), a nonlinear video editor
- [Polari](https://git.gnome.org/browse/polari), an IRC client
+ - [radare2](https://github.com/radare/radare2), unix-like reverse engineering framework and commandline tools (not the default)
+ - [SSHFS](https://github.com/libfuse/sshfs), allows you to mount a remote filesystem using SFTP
- [Sysprof](https://wiki.gnome.org/Apps/Sysprof), a profiling tool
- [systemd](https://github.com/systemd/systemd), the init system
+ - [szl](https://github.com/dimkr/szl), a lightweight, embeddable scripting language
- [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)
+ - [xi-gtk](https://github.com/eyelash/xi-gtk), a GTK+ front-end for the Xi editor
+ - [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)
- - [ZStandard](https://github.com/facebook/zstd/commit/4dca56ed832c6a88108a2484a8f8ff63d8d76d91) a compression algorithm developed at Facebook (not used by default)
+ - [wlroots](https://github.com/swaywm/wlroots), a modular Wayland compositor library
+ - [ZStandard](https://github.com/facebook/zstd/commit/4dca56ed832c6a88108a2484a8f8ff63d8d76d91), a compression algorithm developed at Facebook (not used by default)
Note that a more up-to-date list of GNOME projects that use Meson can be found [here](https://wiki.gnome.org/Initiatives/GnomeGoals/MesonPorting).
diff --git a/docs/markdown/Using-wraptool.md b/docs/markdown/Using-wraptool.md
index 08b1bfa..f6023e8 100644
--- a/docs/markdown/Using-wraptool.md
+++ b/docs/markdown/Using-wraptool.md
@@ -1,9 +1,9 @@
# Using wraptool
-Wraptool is a helper tool that allows you to manage your source
-dependencies using the WrapDB database. It gives you all things you
-would expect, such as installing and updating dependencies. The wrap
-tool works on all platforms, the only limitation is that the wrap
+Wraptool is a subcommand of Meson that allows you to manage your
+source dependencies using the WrapDB database. It gives you all things
+you would expect, such as installing and updating dependencies. The
+wrap tool works on all platforms, the only limitation is that the wrap
definition works on your target platform. If you find some Wraps that
don't work, please file bugs or, even better, patches.
@@ -16,7 +16,7 @@ are commands to type.
The simplest operation to do is to query the list of packages
available. To list them all issue the following command:
- $ wraptool list
+ $ meson wrap list
box2d
enet
gtest
@@ -33,13 +33,13 @@ available. To list them all issue the following command:
Usually you want to search for a specific package. This can be done
with the `search` command:
- $ wraptool search jpeg
+ $ meson wrap search jpeg
libjpeg
To determine which versions of libjpeg are available to install, issue
the `info` command:
- $ wraptool info libjpeg
+ $ meson wrap info libjpeg
Available versions of libjpeg:
9a 2
@@ -54,7 +54,7 @@ Installing dependencies is just as straightforward. First just create
the `subprojects` directory at the top of your source tree and issue
the install command.
- $ wraptool install libjpeg
+ $ meson wrap install libjpeg
Installed libjpeg branch 9a revision 2
Now you can issue a `subproject('libjpeg')` in your `meson.build` file
@@ -62,7 +62,7 @@ to use it.
To check if your projects are up to date you can issue the `status` command.
- $ wraptool status
+ $ meson wrap status
Subproject status
libjpeg up to date. Branch 9a, revision 2.
zlib not up to date. Have 1.2.8 2, but 1.2.8 4 is available.
@@ -70,12 +70,12 @@ To check if your projects are up to date you can issue the `status` command.
In this case `zlib` has a newer release available. Updating it is
straightforward:
- $ wraptool update zlib
+ $ meson wrap update zlib
Updated zlib to branch 1.2.8 revision 4
Wraptool can do other things besides these. Documentation for these
can be found in the command line help, which can be accessed by
-`wraptool --help`.
+`meson wrap --help`.
## Promoting dependencies
diff --git a/docs/markdown/_Sidebar.md b/docs/markdown/_Sidebar.md
index 89fc523..2637d68 100644
--- a/docs/markdown/_Sidebar.md
+++ b/docs/markdown/_Sidebar.md
@@ -7,7 +7,7 @@
* [Tests](Unit-tests.md)
* [Syntax](Syntax.md)
-### [Modules](https://github.com/mesonbuild/meson/wiki/Module-reference.md)
+### [Modules](Module-reference.md)
* [gnome](Gnome-module.md)
* [i18n](i18n-module.md)
diff --git a/docs/markdown/i18n-module.md b/docs/markdown/i18n-module.md
index 8fb650a..88f059b 100644
--- a/docs/markdown/i18n-module.md
+++ b/docs/markdown/i18n-module.md
@@ -40,7 +40,7 @@ This function also defines targets for maintainers to use:
### i18n.merge_file()
This merges translations into a text file using `msgfmt`. See
-[custom_target](https://github.com/mesonbuild/meson/wiki/Reference%20manual#custom_target)
+[custom_target](Reference-manual.md#custom_target)
for normal keywords. In addition it accepts these keywords:
* `data_dirs`: (*Added 0.41.0*) list of directories for its files (See
diff --git a/docs/markdown/snippets/intopt.md b/docs/markdown/snippets/intopt.md
new file mode 100644
index 0000000..daf660b
--- /dev/null
+++ b/docs/markdown/snippets/intopt.md
@@ -0,0 +1,6 @@
+## Integer options
+
+There is a new integer option type with optional minimum and maximum
+values. It can be specified like this in the `meson_options.txt` file:
+
+ option('integer_option', type : 'integer', min : 0, max : 5, value : 3)
diff --git a/docs/markdown/snippets/yield.md b/docs/markdown/snippets/yield.md
new file mode 100644
index 0000000..3880e67
--- /dev/null
+++ b/docs/markdown/snippets/yield.md
@@ -0,0 +1,8 @@
+## Yielding subproject option to superproject
+
+Normally project options are specific to the current project. However
+sometimes you want to have an option whose value is the same over all
+projects. This can be achieved with the new `yield` keyword for
+options. When set to `true`, getting the value of this option in
+`meson.build` files gets the value from the option with the same name
+in the master project (if such an option exists).
diff --git a/docs/sitemap.txt b/docs/sitemap.txt
index d40c3a0..144ca4a 100644
--- a/docs/sitemap.txt
+++ b/docs/sitemap.txt
@@ -52,6 +52,7 @@ index.md
Project-templates.md
Reference-manual.md
Reference-tables.md
+ Style-guide.md
FAQ.md
Reproducible-builds.md
howtox.md
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 292b027..62cc756 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -323,9 +323,12 @@ class Backend:
if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so']:
continue
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))
+ if absdir.startswith(self.environment.get_source_dir()):
+ rel_to_src = absdir[len(self.environment.get_source_dir()) + 1:]
+ assert not os.path.isabs(rel_to_src), 'rel_to_src: {} is absolute'.format(rel_to_src)
+ paths.append(os.path.join(self.build_to_src, rel_to_src))
+ else:
+ paths.append(absdir)
return paths
def determine_rpath_dirs(self, target):
@@ -407,16 +410,10 @@ class Backend:
args = []
pchpath = self.get_target_private_dir(target)
includeargs = compiler.get_include_args(pchpath, False)
- for lang in ['c', 'cpp']:
- p = target.get_pch(lang)
- if not p:
- continue
- if compiler.can_compile(p[-1]):
- header = p[0]
- args += compiler.get_pch_use_args(pchpath, header)
- if len(args) > 0:
- args = includeargs + args
- return args
+ p = target.get_pch(compiler.get_language())
+ if p:
+ args += compiler.get_pch_use_args(pchpath, p[0])
+ return includeargs + args
@staticmethod
def escape_extra_args(compiler, args):
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index f738615..a59b7d3 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -184,7 +184,7 @@ class CCompiler(Compiler):
return []
def gen_export_dynamic_link_args(self, env):
- if for_windows(env.is_cross_build(), env):
+ if for_windows(env.is_cross_build(), env) or for_cygwin(env.is_cross_build(), env):
return ['-Wl,--export-all-symbols']
elif for_darwin(env.is_cross_build(), env):
return []
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index dbaf730..034fef4 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -137,8 +137,11 @@ gnulike_buildtype_linker_args = {'plain': [],
msvc_buildtype_linker_args = {'plain': [],
'debug': [],
'debugoptimized': [],
- 'release': [],
- 'minsize': ['/INCREMENTAL:NO'],
+ # The otherwise implicit REF and ICF linker
+ # optimisations are disabled by /DEBUG.
+ # REF implies ICF.
+ 'release': ['/OPT:REF'],
+ 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
}
java_buildtype_args = {'plain': [],
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 0fdac8b..f87e62c 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -1,5 +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.
@@ -25,12 +24,19 @@ import ast
version = '0.45.0.dev1'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'xcode']
+default_yielding = False
+
class UserOption:
- def __init__(self, name, description, choices):
+ def __init__(self, name, description, choices, yielding):
super().__init__()
self.name = name
self.choices = choices
self.description = description
+ if yielding is None:
+ yielding = default_yielding
+ if not isinstance(yielding, bool):
+ raise MesonException('Value of "yielding" must be a boolean.')
+ self.yielding = yielding
# Check that the input is a valid value and return the
# "cleaned" or "native" version. For example the Boolean
@@ -39,8 +45,8 @@ class UserOption:
raise RuntimeError('Derived option class did not override validate_value.')
class UserStringOption(UserOption):
- def __init__(self, name, description, value, choices=None):
- super().__init__(name, description, choices)
+ def __init__(self, name, description, value, choices=None, yielding=None):
+ super().__init__(name, description, choices, yielding)
self.set_value(value)
def validate(self, value):
@@ -56,8 +62,8 @@ class UserStringOption(UserOption):
return value
class UserBooleanOption(UserOption):
- def __init__(self, name, description, value):
- super().__init__(name, description, [True, False])
+ def __init__(self, name, description, value, yielding=None):
+ super().__init__(name, description, [True, False], yielding)
self.set_value(value)
def tobool(self, thing):
@@ -79,11 +85,17 @@ class UserBooleanOption(UserOption):
return self.tobool(value)
class UserIntegerOption(UserOption):
- def __init__(self, name, description, min_value, max_value, value):
- super().__init__(name, description, [True, False])
+ def __init__(self, name, description, min_value, max_value, value, yielding=None):
+ super().__init__(name, description, [True, False], yielding)
self.min_value = min_value
self.max_value = max_value
self.set_value(value)
+ c = []
+ if min_value is not None:
+ c.append('>=' + str(min_value))
+ if max_value is not None:
+ c.append('<=' + str(max_value))
+ self.choices = ', '.join(c)
def set_value(self, newvalue):
if isinstance(newvalue, str):
@@ -106,8 +118,8 @@ class UserIntegerOption(UserOption):
return self.toint(value)
class UserComboOption(UserOption):
- def __init__(self, name, description, choices, value):
- super().__init__(name, description, choices)
+ def __init__(self, name, description, choices, value, yielding=None):
+ super().__init__(name, description, choices, yielding)
if not isinstance(self.choices, list):
raise MesonException('Combo choices must be an array.')
for i in self.choices:
@@ -128,7 +140,7 @@ class UserComboOption(UserOption):
class UserArrayOption(UserOption):
def __init__(self, name, description, value, **kwargs):
- super().__init__(name, description, kwargs.get('choices', []))
+ super().__init__(name, description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None))
self.set_value(value, user_input=False)
def validate(self, value, user_input):
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index f89e631..66bc3b4 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -61,21 +61,14 @@ class DependencyMethods(Enum):
class Dependency:
- def __init__(self, type_name, kwargs):
- self.name = "null"
- self.version = 'none'
- self.language = None # None means C-like
- self.is_found = False
- self.type_name = type_name
- self.compile_args = []
- self.link_args = []
- self.sources = []
+ @classmethod
+ def _process_method_kw(cls, kwargs):
method = kwargs.get('method', 'auto')
if method not in [e.value for e in DependencyMethods]:
raise DependencyException('method {!r} is invalid'.format(method))
method = DependencyMethods(method)
- # This sets per-too config methods which are deprecated to to the new
+ # This sets per-tool config methods which are deprecated to to the new
# generic CONFIG_TOOL value.
if method in [DependencyMethods.SDLCONFIG, DependencyMethods.CUPSCONFIG,
DependencyMethods.PCAPCONFIG, DependencyMethods.LIBWMFCONFIG]:
@@ -88,14 +81,27 @@ class Dependency:
# Set the detection method. If the method is set to auto, use any available method.
# If method is set to a specific string, allow only that detection method.
if method == DependencyMethods.AUTO:
- self.methods = self.get_methods()
- elif method in self.get_methods():
- self.methods = [method]
+ methods = cls.get_methods()
+ elif method in cls.get_methods():
+ methods = [method]
else:
raise DependencyException(
'Unsupported detection method: {}, allowed methods are {}'.format(
method.value,
- mlog.format_list([x.value for x in [DependencyMethods.AUTO] + self.get_methods()])))
+ mlog.format_list([x.value for x in [DependencyMethods.AUTO] + cls.get_methods()])))
+
+ return methods
+
+ def __init__(self, type_name, kwargs):
+ self.name = "null"
+ self.version = 'none'
+ self.language = None # None means C-like
+ self.is_found = False
+ self.type_name = type_name
+ self.compile_args = []
+ self.link_args = []
+ self.sources = []
+ self.methods = self._process_method_kw(kwargs)
def __repr__(self):
s = '<{0} {1}: {2}>'
@@ -115,7 +121,8 @@ class Dependency:
As an example, gtest-all.cc when using GTest."""
return self.sources
- def get_methods(self):
+ @staticmethod
+ def get_methods():
return [DependencyMethods.AUTO]
def get_name(self):
@@ -246,14 +253,17 @@ class ConfigToolDependency(ExternalDependency):
# instantiated and returned. The reduce function (method) is also
# attached, since python's pickle module won't be able to do anything
# with this dynamically generated class otherwise.
- def reduce(_):
- return (cls.factory,
- (name, environment, language, kwargs, tools, tool_name))
+ def reduce(self):
+ return (cls._unpickle, (), self.__dict__)
sub = type('{}Dependency'.format(name.capitalize()), (cls, ),
{'tools': tools, 'tool_name': tool_name, '__reduce__': reduce})
return sub(name, environment, language, kwargs)
+ @classmethod
+ def _unpickle(cls):
+ return cls.__new__(cls)
+
def find_config(self, versions=None):
"""Helper method that searchs for config tool binaries in PATH and
returns the one that best matches the given version requirements.
@@ -331,7 +341,8 @@ class ConfigToolDependency(ExternalDependency):
return []
return shlex.split(out)
- def get_methods(self):
+ @staticmethod
+ def get_methods():
return [DependencyMethods.AUTO, DependencyMethods.CONFIG_TOOL]
def get_configtool_variable(self, variable_name):
@@ -561,12 +572,16 @@ class PkgConfigDependency(ExternalDependency):
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))
+ if 'default' in kwargs:
+ variable = kwargs['default']
+ else:
+ 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
- def get_methods(self):
+ @staticmethod
+ def get_methods():
return [DependencyMethods.PKGCONFIG]
def check_pkgconfig(self):
@@ -915,7 +930,12 @@ def find_external_dependency(name, env, kwargs):
if lname in packages:
if lname not in _packages_accept_language and 'language' in kwargs:
raise DependencyException('%s dependency does not accept "language" keyword argument' % (lname, ))
- dep = packages[lname](env, kwargs)
+ # Create the dependency object using a factory class method, if one
+ # exists, otherwise it is just constructed directly.
+ if getattr(packages[lname], '_factory', None):
+ dep = packages[lname]._factory(env, kwargs)
+ else:
+ dep = packages[lname](env, kwargs)
if required and not dep.found():
raise DependencyException('Dependency "%s" not found' % name)
return dep
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 8511b46..9e9441f 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -839,7 +839,8 @@ class Python3Dependency(ExternalDependency):
self.version = sysconfig.get_config_var('py_version')
self.is_found = True
- def get_methods(self):
+ @staticmethod
+ def get_methods():
if mesonlib.is_windows():
return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSCONFIG]
elif mesonlib.is_osx():
@@ -857,90 +858,80 @@ class Python3Dependency(ExternalDependency):
class PcapDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('pcap', environment, None, kwargs)
- kwargs['required'] = False
- if DependencyMethods.PKGCONFIG in self.methods:
+
+ @classmethod
+ def _factory(cls, environment, kwargs):
+ methods = cls._process_method_kw(kwargs)
+ if DependencyMethods.PKGCONFIG in methods:
try:
pcdep = PkgConfigDependency('pcap', environment, kwargs)
if pcdep.found():
- self.type_name = 'pkgconfig'
- self.is_found = True
- self.compile_args = pcdep.get_compile_args()
- self.link_args = pcdep.get_link_args()
- self.version = pcdep.get_version()
- self.pcdep = pcdep
- return
+ return pcdep
except Exception as e:
mlog.debug('Pcap not found via pkgconfig. Trying next, error was:', str(e))
- if DependencyMethods.CONFIG_TOOL in self.methods:
+ if DependencyMethods.CONFIG_TOOL in methods:
try:
ctdep = ConfigToolDependency.factory(
'pcap', environment, None, kwargs, ['pcap-config'], 'pcap-config')
if ctdep.found():
- self.config = ctdep.config
- self.type_name = 'config-tool'
- self.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
- self.link_args = ctdep.get_config_value(['--libs'], 'link_args')
- self.version = self.get_pcap_lib_version()
- self.is_found = True
- return
+ ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
+ ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
+ ctdep.version = cls.get_pcap_lib_version(ctdep)
+ return ctdep
except Exception as e:
mlog.debug('Pcap not found via pcap-config. Trying next, error was:', str(e))
- def get_methods(self):
+ return PcapDependency(environment, kwargs)
+
+ @staticmethod
+ def get_methods():
if mesonlib.is_osx():
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK]
else:
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
- def get_pcap_lib_version(self):
- return self.compiler.get_return_value('pcap_lib_version', 'string',
- '#include <pcap.h>', self.env, [], [self])
+ @staticmethod
+ def get_pcap_lib_version(ctdep):
+ return ctdep.compiler.get_return_value('pcap_lib_version', 'string',
+ '#include <pcap.h>', ctdep.env, [], [ctdep])
class CupsDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('cups', environment, None, kwargs)
- kwargs['required'] = False
- if DependencyMethods.PKGCONFIG in self.methods:
+
+ @classmethod
+ def _factory(cls, environment, kwargs):
+ methods = cls._process_method_kw(kwargs)
+ if DependencyMethods.PKGCONFIG in methods:
try:
pcdep = PkgConfigDependency('cups', environment, kwargs)
if pcdep.found():
- self.type_name = 'pkgconfig'
- self.is_found = True
- self.compile_args = pcdep.get_compile_args()
- self.link_args = pcdep.get_link_args()
- self.version = pcdep.get_version()
- self.pcdep = pcdep
- return
+ return pcdep
except Exception as e:
mlog.debug('cups not found via pkgconfig. Trying next, error was:', str(e))
- if DependencyMethods.CONFIG_TOOL in self.methods:
+ if DependencyMethods.CONFIG_TOOL in methods:
try:
ctdep = ConfigToolDependency.factory(
'cups', environment, None, kwargs, ['cups-config'], 'cups-config')
if ctdep.found():
- self.config = ctdep.config
- self.type_name = 'config-tool'
- self.version = ctdep.version
- self.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
- self.link_args = ctdep.get_config_value(['--ldflags', '--libs'], 'link_args')
- self.is_found = True
- return
+ ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
+ ctdep.link_args = ctdep.get_config_value(['--ldflags', '--libs'], 'link_args')
+ return ctdep
except Exception as e:
mlog.debug('cups not found via cups-config. Trying next, error was:', str(e))
- if DependencyMethods.EXTRAFRAMEWORK in self.methods:
+ if DependencyMethods.EXTRAFRAMEWORK in methods:
if mesonlib.is_osx():
- fwdep = ExtraFrameworkDependency('cups', False, None, self.env,
- self.language, kwargs)
+ fwdep = ExtraFrameworkDependency('cups', False, None, environment,
+ kwargs.get('language', None), kwargs)
if fwdep.found():
- self.is_found = True
- self.compile_args = fwdep.get_compile_args()
- self.link_args = fwdep.get_link_args()
- self.version = fwdep.get_version()
- return
- mlog.log('Dependency', mlog.bold('cups'), 'found:', mlog.red('NO'))
+ return fwdep
+ mlog.log('Dependency', mlog.bold('cups'), 'found:', mlog.red('NO'))
+
+ return CupsDependency(environment, kwargs)
- def get_methods(self):
+ @staticmethod
+ def get_methods():
if mesonlib.is_osx():
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK]
else:
@@ -950,36 +941,33 @@ class CupsDependency(ExternalDependency):
class LibWmfDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('libwmf', environment, None, kwargs)
- if DependencyMethods.PKGCONFIG in self.methods:
+
+ @classmethod
+ def _factory(cls, environment, kwargs):
+ methods = cls._process_method_kw(kwargs)
+ if DependencyMethods.PKGCONFIG in methods:
try:
kwargs['required'] = False
pcdep = PkgConfigDependency('libwmf', environment, kwargs)
if pcdep.found():
- self.type_name = 'pkgconfig'
- self.is_found = True
- self.compile_args = pcdep.get_compile_args()
- self.link_args = pcdep.get_link_args()
- self.version = pcdep.get_version()
- self.pcdep = pcdep
- return
+ return pcdep
except Exception as e:
mlog.debug('LibWmf not found via pkgconfig. Trying next, error was:', str(e))
- if DependencyMethods.CONFIG_TOOL in self.methods:
+ if DependencyMethods.CONFIG_TOOL in methods:
try:
ctdep = ConfigToolDependency.factory(
'libwmf', environment, None, kwargs, ['libwmf-config'], 'libwmf-config')
if ctdep.found():
- self.config = ctdep.config
- self.type_name = 'config-too'
- self.version = ctdep.version
- self.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
- self.link_args = ctdep.get_config_value(['--libs'], 'link_args')
- self.is_found = True
- return
+ ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
+ ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
+ return ctdep
except Exception as e:
mlog.debug('cups not found via libwmf-config. Trying next, error was:', str(e))
- def get_methods(self):
+ return LibWmfDependency(environment, kwargs)
+
+ @staticmethod
+ def get_methods():
if mesonlib.is_osx():
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK]
else:
diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py
index c066c31..a6307c4 100644
--- a/mesonbuild/dependencies/ui.py
+++ b/mesonbuild/dependencies/ui.py
@@ -38,19 +38,6 @@ from .base import ConfigToolDependency
class GLDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('gl', environment, None, kwargs)
- if DependencyMethods.PKGCONFIG in self.methods:
- try:
- pcdep = PkgConfigDependency('gl', environment, kwargs)
- if pcdep.found():
- self.type_name = 'pkgconfig'
- self.is_found = True
- self.compile_args = pcdep.get_compile_args()
- self.link_args = pcdep.get_link_args()
- self.version = pcdep.get_version()
- self.pcdep = pcdep
- return
- except Exception:
- pass
if DependencyMethods.SYSTEM in self.methods:
if mesonlib.is_osx():
self.is_found = True
@@ -67,7 +54,19 @@ class GLDependency(ExternalDependency):
self.version = '1'
return
- def get_methods(self):
+ @classmethod
+ def _factory(cls, environment, kwargs):
+ if DependencyMethods.PKGCONFIG in cls._process_method_kw(kwargs):
+ try:
+ pcdep = PkgConfigDependency('gl', environment, kwargs)
+ if pcdep.found():
+ return pcdep
+ except Exception:
+ pass
+ return GLDependency(environment, kwargs)
+
+ @staticmethod
+ def get_methods():
if mesonlib.is_osx() or mesonlib.is_windows():
return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
else:
@@ -337,7 +336,8 @@ class QtBaseDependency(ExternalDependency):
else:
return qvars['QT_INSTALL_BINS']
- def get_methods(self):
+ @staticmethod
+ def get_methods():
return [DependencyMethods.PKGCONFIG, DependencyMethods.QMAKE]
def get_exe_args(self, compiler):
@@ -380,47 +380,40 @@ class Qt5Dependency(QtBaseDependency):
class SDL2Dependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('sdl2', environment, None, kwargs)
- kwargs['required'] = False
- if DependencyMethods.PKGCONFIG in self.methods:
+
+ @classmethod
+ def _factory(cls, environment, kwargs):
+ methods = cls._process_method_kw(kwargs)
+ if DependencyMethods.PKGCONFIG in methods:
try:
pcdep = PkgConfigDependency('sdl2', environment, kwargs)
if pcdep.found():
- self.type_name = 'pkgconfig'
- self.is_found = True
- self.compile_args = pcdep.get_compile_args()
- self.link_args = pcdep.get_link_args()
- self.version = pcdep.get_version()
- self.pcdep = pcdep
- return
+ return pcdep
except Exception as e:
mlog.debug('SDL 2 not found via pkgconfig. Trying next, error was:', str(e))
- if DependencyMethods.CONFIG_TOOL in self.methods:
+ if DependencyMethods.CONFIG_TOOL in methods:
try:
ctdep = ConfigToolDependency.factory(
'sdl2', environment, None, kwargs, ['sdl2-config'], 'sdl2-config')
if ctdep.found():
- self.type_name = 'config-tool'
- self.config = ctdep.config
- self.version = ctdep.version
- self.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
- self.links_args = ctdep.get_config_value(['--libs'], 'link_args')
- self.is_found = True
- return
+ ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
+ ctdep.links_args = ctdep.get_config_value(['--libs'], 'link_args')
+ return ctdep
except Exception as e:
mlog.debug('SDL 2 not found via sdl2-config. Trying next, error was:', str(e))
- if DependencyMethods.EXTRAFRAMEWORK in self.methods:
+ if DependencyMethods.EXTRAFRAMEWORK in methods:
if mesonlib.is_osx():
- fwdep = ExtraFrameworkDependency('sdl2', False, None, self.env,
- self.language, kwargs)
+ fwdep = ExtraFrameworkDependency('sdl2', False, None, environment,
+ kwargs.get('language', None), kwargs)
if fwdep.found():
- self.is_found = True
- self.compile_args = fwdep.get_compile_args()
- self.link_args = fwdep.get_link_args()
- self.version = '2' # FIXME
- return
+ fwdep.version = '2' # FIXME
+ return fwdep
mlog.log('Dependency', mlog.bold('sdl2'), 'found:', mlog.red('NO'))
- def get_methods(self):
+ return SDL2Dependency(environment, kwargs)
+
+ @staticmethod
+ def get_methods():
if mesonlib.is_osx():
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK]
else:
@@ -456,20 +449,6 @@ class VulkanDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('vulkan', environment, None, kwargs)
- if DependencyMethods.PKGCONFIG in self.methods:
- try:
- pcdep = PkgConfigDependency('vulkan', environment, kwargs)
- if pcdep.found():
- self.type_name = 'pkgconfig'
- self.is_found = True
- self.compile_args = pcdep.get_compile_args()
- self.link_args = pcdep.get_link_args()
- self.version = pcdep.get_version()
- self.pcdep = pcdep
- return
- except Exception:
- pass
-
if DependencyMethods.SYSTEM in self.methods:
try:
self.vulkan_sdk = os.environ['VULKAN_SDK']
@@ -526,5 +505,18 @@ class VulkanDependency(ExternalDependency):
self.link_args.append(lib)
return
- def get_methods(self):
+ @classmethod
+ def _factory(cls, environment, kwargs):
+ if DependencyMethods.PKGCONFIG in cls._process_method_kw(kwargs):
+ try:
+ pcdep = PkgConfigDependency('vulkan', environment, kwargs)
+ if pcdep.found():
+ return pcdep
+ except Exception:
+ pass
+
+ return VulkanDependency(environment, kwargs)
+
+ @staticmethod
+ def get_methods():
return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index f68e25f..c2c4fe3 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -683,6 +683,8 @@ class SubprojectHolder(InterpreterObject, ObjectHolder):
varname = args[0]
if not isinstance(varname, str):
raise InterpreterException('Get_variable takes a string argument.')
+ if varname not in self.held_object.variables:
+ raise InvalidArguments('Requested variable "{0}" not found.'.format(varname))
return self.held_object.variables[varname]
class CompilerHolder(InterpreterObject):
@@ -1579,6 +1581,8 @@ class Interpreter(InterpreterBase):
self.build.cross_stdlibs[l] = subproj.get_variable_method([depname], {})
except KeyError:
pass
+ except InvalidArguments:
+ pass
@stringArgs
@noKwargs
@@ -1684,7 +1688,14 @@ external dependencies (including libraries) must go to "dependencies".''')
raise InterpreterException('Program or command {!r} not found '
'or not executable'.format(cmd))
cmd = prog
- cmd_path = os.path.relpath(cmd.get_path(), start=srcdir)
+ try:
+ cmd_path = os.path.relpath(cmd.get_path(), start=srcdir)
+ except ValueError:
+ # On Windows a relative path can't be evaluated for
+ # paths on two different drives (i.e. c:\foo and f:\bar).
+ # The only thing left to is is to use the original absolute
+ # path.
+ cmd_path = cmd.get_path()
if not cmd_path.startswith('..') and cmd_path not in self.build_def_files:
self.build_def_files.append(cmd_path)
expanded_args = []
@@ -1700,7 +1711,7 @@ external dependencies (including libraries) must go to "dependencies".''')
for a in expanded_args:
if not os.path.isabs(a):
a = os.path.join(builddir if in_builddir else srcdir, self.subdir, a)
- if os.path.exists(a):
+ if os.path.isfile(a):
a = os.path.relpath(a, start=srcdir)
if not a.startswith('..'):
if a not in self.build_def_files:
@@ -1724,8 +1735,16 @@ external dependencies (including libraries) must go to "dependencies".''')
return self.do_subproject(dirname, kwargs)
def do_subproject(self, dirname, kwargs):
- if '/' in dirname or '\\' in dirname:
- raise InterpreterException('Subproject name must not contain a path separator.')
+ if dirname == '':
+ raise InterpreterException('Subproject dir name must not be empty.')
+ if dirname[0] == '.':
+ raise InterpreterException('Subproject dir name must not start with a period.')
+ if '..' in dirname:
+ raise InterpreterException('Subproject name must not contain a ".." path segment.')
+ if os.path.isabs(dirname):
+ raise InterpreterException('Subproject name must not be an absolute path.')
+ if '\\' in dirname or '/' in dirname:
+ mlog.warning('Subproject name has a path separator. This may cause unexpected behaviour.')
if dirname in self.subproject_stack:
fullstack = self.subproject_stack + [dirname]
incpath = ' => '.join(fullstack)
@@ -1768,7 +1787,7 @@ external dependencies (including libraries) must go to "dependencies".''')
def func_get_option(self, nodes, args, kwargs):
if len(args) != 1:
raise InterpreterException('Argument required for get_option.')
- optname = args[0]
+ undecorated_optname = optname = args[0]
if ':' in optname:
raise InterpreterException('''Having a colon in option name is forbidden, projects are not allowed
to directly access options of other subprojects.''')
@@ -1787,7 +1806,11 @@ to directly access options of other subprojects.''')
if not coredata.is_builtin_option(optname) and self.is_subproject():
optname = self.subproject + ':' + optname
try:
- return self.environment.coredata.user_options[optname].value
+ opt = self.environment.coredata.user_options[optname]
+ if opt.yielding and ':' in optname:
+ # If option not present in superproject, keep the original.
+ opt = self.environment.coredata.user_options.get(undecorated_optname, opt)
+ return opt.value
except KeyError:
pass
if optname.endswith('_link_args'):
@@ -2187,10 +2210,10 @@ to directly access options of other subprojects.''')
def get_subproject_dep(self, name, dirname, varname, required):
try:
dep = self.subprojects[dirname].get_variable_method([varname], {})
- except KeyError:
+ except InvalidArguments as e:
if required:
- raise DependencyException('Could not find dependency {} in subproject {}'
- ''.format(varname, dirname))
+ raise DependencyException('Could not find dependency {} in subproject {}; {}'
+ ''.format(varname, dirname, str(e)))
# If the dependency is not required, don't raise an exception
subproj_path = os.path.join(self.subproject_dir, dirname)
mlog.log('Dependency', mlog.bold(name), 'from subproject',
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 619aa39..073e505 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -147,10 +147,7 @@ class MesonApp:
def generate(self):
env = environment.Environment(self.source_dir, self.build_dir, self.meson_script_launcher, self.options, self.original_cmd_line_args)
mlog.initialize(env.get_log_dir())
- try:
- self._generate(env)
- finally:
- mlog.shutdown()
+ self._generate(env)
def _generate(self, env):
mlog.debug('Build started at', datetime.datetime.now().isoformat())
@@ -374,6 +371,7 @@ def run(original_args, mainfile=None):
# Error message
mlog.log(e)
# Path to log file
+ mlog.shutdown()
logfile = os.path.join(app.build_dir, environment.Environment.log_dir, mlog.log_fname)
mlog.log("\nA full log can be found at", mlog.bold(logfile))
if os.environ.get('MESON_FORCE_BACKTRACE'):
@@ -383,4 +381,7 @@ def run(original_args, mainfile=None):
raise
traceback.print_exc()
return 1
+ finally:
+ mlog.shutdown()
+
return 0
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index aaaf8fc..8cf66af 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -139,6 +139,8 @@ def add_keys(optlist, options):
elif isinstance(opt, coredata.UserComboOption):
optdict['choices'] = opt.choices
typestr = 'combo'
+ elif isinstance(opt, coredata.UserIntegerOption):
+ typestr = 'integer'
elif isinstance(opt, coredata.UserArrayOption):
typestr = 'array'
else:
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index db85420..218e3b3 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -362,7 +362,7 @@ class GnomeModule(ExtensionModule):
ldflags.update([lib])
if isinstance(dep, PkgConfigDependency):
- girdir = dep.get_pkgconfig_variable("girdir", {})
+ girdir = dep.get_pkgconfig_variable("girdir", {'default': ''})
if girdir:
gi_includes.update([girdir])
elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
@@ -553,7 +553,7 @@ class GnomeModule(ExtensionModule):
if subdir not in typelib_includes:
typelib_includes.append(subdir)
elif isinstance(dep, PkgConfigDependency):
- girdir = dep.get_pkgconfig_variable("girdir", {})
+ girdir = dep.get_pkgconfig_variable("girdir", {'default': ''})
if girdir and girdir not in typelib_includes:
typelib_includes.append(girdir)
# ldflags will be misinterpreted by gir scanner (showing
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index 95e532c..a697106 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -228,10 +228,10 @@ class TestHarness:
# If MALLOC_PERTURB_ is not set, or if it is set to an empty value,
# (i.e., the test or the environment don't explicitly set it), set
- # it ourselves. We do this unconditionally because it is extremely
- # useful to have in tests.
+ # it ourselves. We do this unconditionally for regular tests
+ # because it is extremely useful to have.
# Setting MALLOC_PERTURB_="0" will completely disable this feature.
- if 'MALLOC_PERTURB_' not in child_env or not child_env['MALLOC_PERTURB_']:
+ if ('MALLOC_PERTURB_' not in child_env or not child_env['MALLOC_PERTURB_']) and not self.options.benchmark:
child_env['MALLOC_PERTURB_'] = str(random.randint(1, 255))
setsid = None
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index df945ab..16eaf78 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -64,16 +64,21 @@ def permitted_kwargs(permitted):
optname_regex = re.compile('[^a-zA-Z0-9_-]')
-@permitted_kwargs({'value'})
+@permitted_kwargs({'value', 'yield'})
def StringParser(name, description, kwargs):
- return coredata.UserStringOption(name, description,
- kwargs.get('value', ''), kwargs.get('choices', []))
+ return coredata.UserStringOption(name,
+ description,
+ kwargs.get('value', ''),
+ kwargs.get('choices', []),
+ kwargs.get('yield', coredata.default_yielding))
-@permitted_kwargs({'value'})
+@permitted_kwargs({'value', 'yield'})
def BooleanParser(name, description, kwargs):
- return coredata.UserBooleanOption(name, description, kwargs.get('value', True))
+ return coredata.UserBooleanOption(name, description,
+ kwargs.get('value', True),
+ kwargs.get('yield', coredata.default_yielding))
-@permitted_kwargs({'value', 'choices'})
+@permitted_kwargs({'value', 'yiel', 'choices'})
def ComboParser(name, description, kwargs):
if 'choices' not in kwargs:
raise OptionException('Combo option missing "choices" keyword.')
@@ -83,9 +88,25 @@ def ComboParser(name, description, kwargs):
for i in choices:
if not isinstance(i, str):
raise OptionException('Combo choice elements must be strings.')
- return coredata.UserComboOption(name, description, choices, kwargs.get('value', choices[0]))
-
-@permitted_kwargs({'value', 'choices'})
+ return coredata.UserComboOption(name,
+ description,
+ choices,
+ kwargs.get('value', choices[0]),
+ kwargs.get('yield', coredata.default_yielding),)
+
+
+@permitted_kwargs({'value', 'min', 'max', 'yield'})
+def IntegerParser(name, description, kwargs):
+ if 'value' not in kwargs:
+ raise OptionException('Integer option must contain value argument.')
+ return coredata.UserIntegerOption(name,
+ description,
+ kwargs.get('min', None),
+ kwargs.get('max', None),
+ kwargs['value'],
+ kwargs.get('yield', coredata.default_yielding))
+
+@permitted_kwargs({'value', 'yield', 'choices'})
def string_array_parser(name, description, kwargs):
if 'choices' in kwargs:
choices = kwargs['choices']
@@ -100,11 +121,16 @@ def string_array_parser(name, description, kwargs):
value = kwargs.get('value', [])
if not isinstance(value, list):
raise OptionException('Array choices must be passed as an array.')
- return coredata.UserArrayOption(name, description, value, choices=choices)
+ return coredata.UserArrayOption(name,
+ description,
+ value,
+ choices=choices,
+ yielding=kwargs.get('yield', coredata.default_yielding))
option_types = {'string': StringParser,
'boolean': BooleanParser,
'combo': ComboParser,
+ 'integer': IntegerParser,
'array': string_array_parser,
}
@@ -128,6 +154,30 @@ class OptionInterpreter:
continue
self.cmd_line_options[key] = value
+ def get_bad_options(self):
+ subproj_len = len(self.subproject)
+ if subproj_len > 0:
+ subproj_len += 1
+ retval = []
+ # The options need to be sorted (e.g. here) to get consistent
+ # error messages (on all platforms) which is required by some test
+ # cases that check (also) the order of these options.
+ for option in sorted(self.cmd_line_options):
+ if option in list(self.options) + forbidden_option_names:
+ continue
+ if any(option[subproj_len:].startswith(p) for p in forbidden_prefixes):
+ continue
+ retval += [option]
+ return retval
+
+ def check_for_bad_options(self):
+ bad = self.get_bad_options()
+ if bad:
+ sub = 'In subproject {}: '.format(self.subproject) if self.subproject else ''
+ mlog.warning(
+ '{}Unknown command line options: "{}"\n'
+ 'This will become a hard error in a future Meson release.'.format(sub, ', '.join(bad)))
+
def process(self, option_file):
try:
with open(option_file, 'r', encoding='utf8') as f:
@@ -147,14 +197,7 @@ class OptionInterpreter:
e.colno = cur.colno
e.file = os.path.join('meson_options.txt')
raise e
- bad = [o for o in sorted(self.cmd_line_options) if not
- (o in list(self.options) + forbidden_option_names or
- any(o.startswith(p) for p in forbidden_prefixes))]
- if bad:
- sub = 'In subproject {}: '.format(self.subproject) if self.subproject else ''
- mlog.warning(
- '{}Unknown command line options: "{}"\n'
- 'This will become a hard error in a future Meson release.'.format(sub, ', '.join(bad)))
+ self.check_for_bad_options()
def reduce_single(self, arg):
if isinstance(arg, str):
diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py
index d1fad11..47f4cda 100644
--- a/mesonbuild/scripts/coverage.py
+++ b/mesonbuild/scripts/coverage.py
@@ -16,11 +16,6 @@ from mesonbuild import environment
import sys, os, subprocess, pathlib
-def remove_dir_from_trace(lcov_command, covfile, dirname):
- tmpfile = covfile + '.tmp'
- subprocess.check_call([lcov_command, '--remove', covfile, dirname, '-o', tmpfile])
- os.replace(tmpfile, covfile)
-
def coverage(source_root, build_root, log_dir):
(gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools()
if gcovr_exe:
@@ -38,6 +33,7 @@ def coverage(source_root, build_root, log_dir):
covinfo = os.path.join(log_dir, 'coverage.info')
initial_tracefile = covinfo + '.initial'
run_tracefile = covinfo + '.run'
+ raw_tracefile = covinfo + '.raw'
subprocess.check_call([lcov_exe,
'--directory', build_root,
'--capture',
@@ -55,11 +51,12 @@ def coverage(source_root, build_root, log_dir):
subprocess.check_call([lcov_exe,
'-a', initial_tracefile,
'-a', run_tracefile,
- '-o', covinfo])
- remove_dir_from_trace(lcov_exe, covinfo, '/usr/include/*')
- remove_dir_from_trace(lcov_exe, covinfo, '/usr/local/include/*')
- remove_dir_from_trace(lcov_exe, covinfo, '/usr/src/*')
- remove_dir_from_trace(lcov_exe, covinfo, '/usr/lib/llvm-*/include/*')
+ '-o', raw_tracefile])
+ # Remove all directories outside the source_root from the covinfo
+ subprocess.check_call([lcov_exe,
+ '--extract', raw_tracefile,
+ os.path.join(source_root, '*'),
+ '--output-file', covinfo])
subprocess.check_call([genhtml_exe,
'--prefix', build_root,
'--output-directory', htmloutdir,
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index 26a3489..bd440a1 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -164,17 +164,20 @@ class Resolver:
if not ret:
return False
# Submodule has not been added, add it
- if out.startswith(b'-'):
+ if out.startswith(b'+'):
+ mlog.warning('submodule {} might be out of date'.format(dirname))
+ return True
+ elif out.startswith(b'U'):
+ raise RuntimeError('submodule {} has merge conflicts'.format(dirname))
+ elif out.startswith(b'-'):
if subprocess.call(['git', '-C', self.subdir_root, 'submodule', 'update', '--init', dirname]) != 0:
return False
# Submodule was added already, but it wasn't populated. Do a checkout.
elif out.startswith(b' '):
if subprocess.call(['git', 'checkout', '.'], cwd=dirname):
return True
- else:
- m = 'Unknown git submodule output: {!r}'
- raise AssertionError(m.format(out))
- return True
+ m = 'Unknown git submodule output: {!r}'
+ raise RuntimeError(m.format(out))
def get_git(self, p):
checkoutdir = os.path.join(self.subdir_root, p.get('directory'))
diff --git a/test cases/common/15 mixed pch/meson.build b/test cases/common/15 mixed pch/meson.build
index 19129d8..8e9da93 100644
--- a/test cases/common/15 mixed pch/meson.build
+++ b/test cases/common/15 mixed pch/meson.build
@@ -1,6 +1,19 @@
project('mixed C and C++ pch test', 'cpp', 'c')
-exe = executable('prog', 'main.cc', 'func.c',
-c_pch : ['pch/func.h', 'pch/func_pch.c'],
-cpp_pch : ['pch/main_pch.cc', 'pch/main.h'])
+exe = executable(
+ 'prog',
+ files('main.cc', 'func.c'),
+ c_pch : ['pch/func.h', 'pch/func_pch.c'],
+ cpp_pch : ['pch/main_pch.cc', 'pch/main.h'],
+)
+
+cc = meson.get_compiler('c')
+if cc.get_id() != 'msvc'
+ exe2 = executable(
+ 'prog2',
+ files('main.cc', 'func.c'),
+ c_pch : 'pch/func.h',
+ cpp_pch : 'pch/main.h',
+ )
+endif
diff --git a/test cases/common/174 dependency factory/meson.build b/test cases/common/174 dependency factory/meson.build
new file mode 100644
index 0000000..54f7d26
--- /dev/null
+++ b/test cases/common/174 dependency factory/meson.build
@@ -0,0 +1,51 @@
+project('dependency factory')
+
+dep = dependency('gl', method: 'pkg-config', required: false)
+if dep.found() and dep.type_name() == 'pkgconfig'
+ dep.get_pkgconfig_variable('prefix')
+endif
+
+dep = dependency('SDL2', method: 'pkg-config', required: false)
+if dep.found() and dep.type_name() == 'pkgconfig'
+ dep.get_pkgconfig_variable('prefix')
+endif
+
+dep = dependency('SDL2', method: 'config-tool', required: false)
+if dep.found() and dep.type_name() == 'configtool'
+ dep.get_configtool_variable('prefix')
+endif
+
+dep = dependency('Vulkan', method: 'pkg-config', required: false)
+if dep.found() and dep.type_name() == 'pkgconfig'
+ dep.get_pkgconfig_variable('prefix')
+endif
+
+dep = dependency('pcap', method: 'pkg-config', required: false)
+if dep.found() and dep.type_name() == 'pkgconfig'
+ dep.get_pkgconfig_variable('prefix')
+endif
+
+dep = dependency('pcap', method: 'config-tool', required: false)
+if dep.found() and dep.type_name() == 'configtool'
+ dep.get_configtool_variable('prefix')
+endif
+
+dep = dependency('cups', method: 'pkg-config', required: false)
+if dep.found() and dep.type_name() == 'pkgconfig'
+ dep.get_pkgconfig_variable('prefix')
+endif
+
+dep = dependency('cups', method: 'config-tool', required: false)
+if dep.found() and dep.type_name() == 'configtool'
+ dep.get_configtool_variable('prefix')
+endif
+
+dep = dependency('libwmf', method: 'pkg-config', required: false)
+if dep.found() and dep.type_name() == 'pkgconfig'
+ dep.get_pkgconfig_variable('prefix')
+endif
+
+dep = dependency('libwmf', method: 'config-tool', required: false)
+if dep.found() and dep.type_name() == 'configtool'
+ dep.get_configtool_variable('prefix')
+endif
diff --git a/test cases/common/176 yield/meson.build b/test cases/common/176 yield/meson.build
new file mode 100644
index 0000000..ba3e426
--- /dev/null
+++ b/test cases/common/176 yield/meson.build
@@ -0,0 +1,6 @@
+project('yield_options', 'c')
+
+subproject('sub')
+
+assert(get_option('unshared_option') == 'one', 'Unshared option has wrong value in superproject.')
+assert(get_option('shared_option') == 'two', 'Unshared option has wrong value in superproject..')
diff --git a/test cases/common/176 yield/meson_options.txt b/test cases/common/176 yield/meson_options.txt
new file mode 100644
index 0000000..36bad4b
--- /dev/null
+++ b/test cases/common/176 yield/meson_options.txt
@@ -0,0 +1,2 @@
+option('unshared_option', type : 'string', value : 'one')
+option('shared_option', type : 'string', value : 'two')
diff --git a/test cases/common/176 yield/subprojects/sub/meson.build b/test cases/common/176 yield/subprojects/sub/meson.build
new file mode 100644
index 0000000..3a506e0
--- /dev/null
+++ b/test cases/common/176 yield/subprojects/sub/meson.build
@@ -0,0 +1,4 @@
+project('subbie', 'c')
+
+assert(get_option('unshared_option') == 'three', 'Unshared option has wrong value in subproject.')
+assert(get_option('shared_option') == 'two', 'Shared option has wrong value in subproject.')
diff --git a/test cases/common/176 yield/subprojects/sub/meson_options.txt b/test cases/common/176 yield/subprojects/sub/meson_options.txt
new file mode 100644
index 0000000..a96c307
--- /dev/null
+++ b/test cases/common/176 yield/subprojects/sub/meson_options.txt
@@ -0,0 +1,2 @@
+option('unshared_option', type : 'string', value : 'three', yield : false)
+option('shared_option', type : 'string', value : 'four', yield : true)
diff --git a/test cases/common/47 options/meson.build b/test cases/common/47 options/meson.build
index 863703c..f177aa4 100644
--- a/test cases/common/47 options/meson.build
+++ b/test cases/common/47 options/meson.build
@@ -25,3 +25,7 @@ endif
if get_option('includedir') != 'include'
error('Incorrect value in builtin option.')
endif
+
+if get_option('integer_opt') != 3
+ error('Incorrect value in integer option.')
+endif
diff --git a/test cases/common/47 options/meson_options.txt b/test cases/common/47 options/meson_options.txt
index 6bd0346..4e1c8d8 100644
--- a/test cases/common/47 options/meson_options.txt
+++ b/test cases/common/47 options/meson_options.txt
@@ -3,3 +3,4 @@ option('other_one', type : 'boolean', value : false)
option('combo_opt', type : 'combo', choices : ['one', 'two', 'combo'], value : 'combo')
option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two'])
option('free_array_opt', type : 'array')
+option('integer_opt', type : 'integer', min : 0, max : 5, value : 3)
diff --git a/test cases/linuxlike/1 pkg-config/meson.build b/test cases/linuxlike/1 pkg-config/meson.build
index 30e5d25..17ee192 100644
--- a/test cases/linuxlike/1 pkg-config/meson.build
+++ b/test cases/linuxlike/1 pkg-config/meson.build
@@ -17,6 +17,8 @@ test('zlibtest', exe)
zprefix = dep.get_pkgconfig_variable('prefix') # Always set but we can't be sure what the value is.
# pkg-config returns empty string for not defined variables
assert(dep.get_pkgconfig_variable('nonexisting') == '', 'Value of unknown variable is not empty.')
+# ... unless default: is used
+assert(dep.get_pkgconfig_variable('nonexisting', default: 'foo') == 'foo', 'Value of unknown variable is not defaulted.')
# pkg-config is able to replace variables
assert(dep.get_pkgconfig_variable('prefix', define_variable: ['prefix', '/tmp']) == '/tmp', 'prefix variable has not been replaced.')
diff --git a/test cases/unit/19 bad command line options/subprojects/one/meson.build b/test cases/unit/19 bad command line options/subprojects/one/meson.build
index 39ae07e..85ef742 100644
--- a/test cases/unit/19 bad command line options/subprojects/one/meson.build
+++ b/test cases/unit/19 bad command line options/subprojects/one/meson.build
@@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-project('one subproject')
+project('one subproject', default_options : [ 'b_colorout=never' ])