aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Build-options.md15
-rw-r--r--docs/markdown/Dependencies.md12
-rw-r--r--docs/markdown/Gnome-module.md19
-rw-r--r--docs/markdown/Icestorm-module.md2
-rw-r--r--docs/markdown/Localisation.md52
-rw-r--r--docs/markdown/Python-3-module.md4
-rw-r--r--docs/markdown/Users.md13
-rw-r--r--docs/markdown/Using-wraptool.md22
-rw-r--r--mesonbuild/backend/backends.py23
-rw-r--r--mesonbuild/dependencies/misc.py206
-rw-r--r--mesonbuild/interpreter.py33
-rw-r--r--mesonbuild/mesonmain.py9
-rw-r--r--mesonbuild/mtest.py6
-rw-r--r--mesonbuild/optinterpreter.py33
-rw-r--r--test cases/common/15 mixed pch/meson.build19
-rw-r--r--test cases/unit/19 bad command line options/subprojects/one/meson.build2
16 files changed, 315 insertions, 155 deletions
diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md
index 74d2355..9ccdf83 100644
--- a/docs/markdown/Build-options.md
+++ b/docs/markdown/Build-options.md
@@ -16,7 +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)
+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'])
```
@@ -44,7 +44,9 @@ default.
An integer option contains a single integer with optional upper and
lower values that are specified with the `min` and `max` keyword
-arguments. Available since Meson version 0.45.0.
+arguments.
+
+This type is available since Meson version 0.45.0.
### Arrays
@@ -56,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
@@ -105,6 +107,13 @@ $ 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
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md
index 6653cc1..74a918a 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -252,3 +252,15 @@ llvm_dep = dependency(
'llvm', version : '>= 4.0', modules : ['amdgpu'], optional_modules : ['inteljitevents'],
)
```
+
+## Python3
+
+Python3 is handled specially by meson:
+1. Meson tries to use `pkg-config`.
+1. If `pkg-config` fails meson uses fallback:
+ - On Windows fallback is current `python3` interpreter.
+ - On OSX fallback is framework dependency from `/Library/Frameworks`.
+
+Note that `python3` found by this dependency might differ from the one used in
+`python3` module because modules uses current interpreter but dependency tries
+`pkg-config` first.
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/Icestorm-module.md b/docs/markdown/Icestorm-module.md
index 896311f..6aa8481 100644
--- a/docs/markdown/Icestorm-module.md
+++ b/docs/markdown/Icestorm-module.md
@@ -1,4 +1,4 @@
-# Unstable SIMD module
+# Unstable IceStorm module
This module provides is available since version 0.45.0.
diff --git a/docs/markdown/Localisation.md b/docs/markdown/Localisation.md
index 34cad8d..517b642 100644
--- a/docs/markdown/Localisation.md
+++ b/docs/markdown/Localisation.md
@@ -4,37 +4,57 @@ short-description: Localization with GNU Gettext
# Localisation
-Localising your application with GNU gettext takes a little effort but is quite straightforward. This documentation assumes that you have a `po` subdirectory at your project root directory that contains all the localisation info.
+Localising your application with GNU gettext takes a little effort but is quite straightforward. We'll create a `po` subdirectory at your project root directory for all the localisation info.
-The first thing you need is a file called `POTFILES`. It lists all the source files that gettext should scan in order to find strings to translate. The syntax of the file is one line per source file and the line must contain the relative path from source root. A sample POTFILES might look like this.
+## Generating .pot and .po files
+In your main meson.build file include the `po` subdirectory in the build proces.
+
+ subdir('po')
+
+In this `po` subdirectory we need:
+- `LINGUAS`: Space separated list of languages
+- `POTFILES`: List of source files to scan for translatable strings.
+- `meson.build`: Localization specific meson file
+
+### LINGUAS
+File with space separated list of languages. A sample LINGUAS might look like this.
+
+ aa ab ae af
+
+### POTFILES
+File that lists all the source files that gettext should scan in order to find strings to translate. The syntax of the file is one line per source file and the line must contain the relative path from source root. A sample POTFILES might look like this.
src/file1.c
src/file2.c
src/subdir/file3.c
include/mything/somefile.h
-We also need to define an array of strings containing all the locales we want to generate. This is done in the Meson file in the `po` subdirectory. Assuming we want to generate Finnish and German localisations, the definition would look like this.
-
+### meson.build
+Localization specific meson file. It imports and uses the `i18n` module. If not defined before it needs to define the `GETTEXT_PACKAGE` global.
```meson
-langs = ['fi', 'de']
+i18n = import('i18n')
+# define GETTEXT_PACKAGE
+add_project_arguments('-DGETTEXT_PACKAGE="intltest"', language:'c')
+i18n.gettext(meson.project_name(),
+ args: '--directory=' + meson.source_root()
+)
```
+The first command imports the `i18n` module that provides gettext features. The fourth line does the actual invocation. The first argument is the gettext package name. This causes two things to happen. The first is that Meson will generate binary mo files and put them to their proper locations when doing an install. The second is that it creates a build rule to regenerate the main pot file. If you are using the Ninja backend, this is how you would invoke the rebuild.
-Then we need to generate the main pot file. Usually this is generated manually or exists already. If not, see later on how to generate it using Meson. The potfile can have any name but is usually the name of the gettext package. Let's say the project is called *intltest*. In this case the corresponding pot file would be called `intltest.pot`.
+### generate .pot file
-For each language listed in the array above we need a corresponding `.po` file. This has to be generated manually, see the gettext manual for details. Once we have all this, we can define the localisation to Meson with these lines.
+Then we need to generate the main pot file. The potfile can have any name but is usually the name of the gettext package. Let's say the project is called *intltest*. In this case the corresponding pot file would be called `intltest.pot`.
-```meson
-i18n = import('i18n')
-langs = ['fi', 'de']
-i18n.gettext('intltest', languages : langs)
-```
-
-The first command imports the `i18n` module that provides gettext features. The third line does the actual invocation. The first argument is the gettext package name. This causes two things to happen. The first is that Meson will generate binary mo files and put them to their proper locations when doing an install. The second is that it creates a build rule to regenerate the main pot file. If you are using the Ninja backend, this is how you would invoke the rebuild.
+Run the following command from your build folder to generate the pot file. It is recommended to inspect it manually afterwards and fill in e.g. proper copyright and contact information.
```console
$ ninja intltest-pot
```
-If the pot file does not yet exist, it will be created. It is recommended to inspect it manually afterwards and fill in e.g. proper copyright and contact information.
+### generate .po files
-Meson does not currently have built in commands for generating po files from the pot file. This is because translations are usually done by people who are not developers and thus have their own workflows.
+For each language listed in the array above we need a corresponding `.po` file. Those can be generated by running the following command from your build folder.
+
+```console
+$ ninja intltest-update-po
+```
diff --git a/docs/markdown/Python-3-module.md b/docs/markdown/Python-3-module.md
index dc6f571..7dda672 100644
--- a/docs/markdown/Python-3-module.md
+++ b/docs/markdown/Python-3-module.md
@@ -18,6 +18,10 @@ conventions of the target platform. All positional and keyword
arguments are the same as for
[shared_module](Reference-manual.md#shared_module).
+`extension_module` does not add any dependencies to the library so user may
+need to add `dependencies : dependency('python3')`, see
+[Python3 dependency](Dependencies.md#Python3).
+
*Added 0.38.0*
## language_version
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index 34abc96..1665922 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
+ - [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
@@ -36,7 +37,7 @@ If you have a project that uses Meson that you want to add to this list, let us
- [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)
+ - [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
@@ -46,23 +47,27 @@ lookup based on OpenStreetMap data
- [Kiwix libraries](https://github.com/kiwix/kiwix-lib)
- [Mesa](https://www.mesa3d.org/), An open source graphics driver project
- [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
+ - [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)
- [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)
+ - [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/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/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index af80160..9e9441f 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -18,7 +18,6 @@ import glob
import os
import re
import shlex
-import shutil
import sysconfig
from pathlib import Path
@@ -44,6 +43,10 @@ from .base import (
# - $BOOST_ROOT/boost/*.hpp
# - $BOOST_ROOT/lib<arch>-<compiler>/*.lib where arch=32/64 and compiler=msvc-14.1
#
+# Note that we should also try to support:
+# mingw-w64 / Windows : libboost_<module>-mt.a (location = <prefix>/mingw64/lib/)
+# libboost_<module>-mt.dll.a
+#
# Library names supported:
# - libboost_<module>-<compiler>-mt-gd-x_x.lib (static)
# - boost_<module>-<compiler>-mt-gd-x_x.lib|.dll (shared)
@@ -97,18 +100,13 @@ from .base import (
# 2.2. Find boost libraries with unknown suffixes using file-name globbing.
# TODO: Unix: Don't assume we know where the boost dir is, rely on -Idir and -Ldir being set.
-# TODO: Determine a suffix (e.g. "-mt" or "") and use it.
-# TODO: Get_win_link_args( ) and get_link_args( )
-# TODO: Genericize: 'args += ['-L' + dir] => args += self.compiler.get_linker_search_args(dir)
# TODO: Allow user to specify suffix in BOOST_SUFFIX, or add specific options like BOOST_DEBUG for 'd' for debug.
-# TODO: fix cross:
-# is_windows() -> for_windows(self.want_cross, self.env)
-# is_osx() and self.want_cross -> for_darwin(self.want_cross, self.env)
class BoostDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('boost', environment, 'cpp', kwargs)
self.need_static_link = ['boost_exception', 'boost_test_exec_monitor']
+ # FIXME: is this the right way to find the build type?
self.is_debug = environment.cmd_line_options.buildtype.startswith('debug')
threading = kwargs.get("threading", "multi")
self.is_multithreading = threading == "multi"
@@ -131,42 +129,34 @@ class BoostDependency(ExternalDependency):
self.libdir = os.environ['BOOST_LIBRARYDIR']
if self.boost_root is None:
- if mesonlib.is_windows():
+ if mesonlib.for_windows(self.want_cross, self.env):
self.boost_roots = self.detect_win_roots()
else:
self.boost_roots = self.detect_nix_roots()
- if self.boost_root is None and not self.boost_roots:
- self.log_fail()
- return
-
if self.incdir is None:
- if mesonlib.is_windows():
+ if mesonlib.for_windows(self.want_cross, self.env):
self.incdir = self.detect_win_incdir()
else:
self.incdir = self.detect_nix_incdir()
- if self.incdir is None and mesonlib.is_windows():
- self.log_fail()
- return
-
if self.check_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()
+ # 1. check if we can find BOOST headers.
+ self.detect_headers_and_version()
+
+ # 2. check if we can find BOOST libraries.
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
+
+ # 3. Report success or failure
+ if self.is_found:
self.log_success()
else:
self.log_fail()
@@ -187,7 +177,6 @@ class BoostDependency(ExternalDependency):
if invalid_modules:
mlog.log(mlog.red('ERROR:'), 'Invalid Boost modules: ' + ', '.join(invalid_modules))
- self.log_fail()
return True
else:
return False
@@ -275,7 +264,7 @@ class BoostDependency(ExternalDependency):
raise DependencyException('Boost module argument is not a string.')
return candidates
- def detect_version(self):
+ def detect_headers_and_version(self):
try:
version = self.compiler.get_define('BOOST_LIB_VERSION', '#include <boost/version.hpp>', self.env, self.get_compile_args(), [])
except mesonlib.EnvironmentException:
@@ -289,9 +278,23 @@ class BoostDependency(ExternalDependency):
self.is_found = True
def detect_lib_modules(self):
- if mesonlib.is_windows():
- return self.detect_lib_modules_win()
- return self.detect_lib_modules_nix()
+ self.lib_modules = {}
+
+ # 1. Try to find modules using compiler.find_library( )
+ if self.find_libraries_with_abi_tags(self.abi_tags()):
+ pass
+ # 2. Fall back to the old method
+ else:
+ if mesonlib.for_windows(self.want_cross, self.env):
+ self.detect_lib_modules_win()
+ else:
+ self.detect_lib_modules_nix()
+
+ # 3. Check if we can find the modules
+ 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.is_found = False
def modname_from_filename(self, filename):
modname = os.path.basename(filename)
@@ -301,20 +304,94 @@ class BoostDependency(ExternalDependency):
modname = modname[3:]
return modname
- def detect_lib_modules_win(self):
- arch = detect_cpu_family(self.env.coredata.compilers)
+ def compiler_tag(self):
+ tag = None
+ compiler = self.env.detect_cpp_compiler(self.want_cross)
+ if mesonlib.for_windows(self.want_cross, self.env):
+ if compiler.get_id() == 'msvc':
+ comp_ts_version = compiler.get_toolset_version()
+ compiler_ts = comp_ts_version.split('.')
+ # FIXME - what about other compilers?
+ tag = '-vc{}{}'.format(compiler_ts[0], compiler_ts[1])
+ else:
+ tag = ''
+ return tag
+
+ def threading_tag(self):
+ if not self.is_multithreading:
+ return ''
+
+ if mesonlib.for_darwin(self.want_cross, self.env):
+ # - Mac: requires -mt for multithreading, so should not fall back to non-mt libraries.
+ return '-mt'
+ elif mesonlib.for_windows(self.want_cross, self.env):
+ # - Windows: requires -mt for multithreading, so should not fall back to non-mt libraries.
+ return '-mt'
+ else:
+ # - Linux: leaves off -mt but libraries are multithreading-aware.
+ # - Cygwin: leaves off -mt but libraries are multithreading-aware.
+ return ''
+
+ def version_tag(self):
+ return '-' + self.version.replace('.', '_')
+
+ def debug_tag(self):
+ return '-gd' if self.is_debug else ''
+
+ def versioned_abi_tag(self):
+ return self.compiler_tag() + self.threading_tag() + self.debug_tag() + self.version_tag()
+
+ # FIXME - how to handle different distributions, e.g. for Mac? Currently we handle homebrew and macports, but not fink.
+ def abi_tags(self):
+ if mesonlib.for_windows(self.want_cross, self.env):
+ return [self.versioned_abi_tag(), self.threading_tag()]
+ else:
+ return [self.threading_tag()]
+
+ def sourceforge_dir(self):
+ if self.env.detect_cpp_compiler(self.want_cross).get_id() != 'msvc':
+ return None
comp_ts_version = self.env.detect_cpp_compiler(self.want_cross).get_toolset_version()
- compiler_ts = comp_ts_version.split('.')
- compiler = 'vc{}{}'.format(compiler_ts[0], compiler_ts[1])
+ arch = detect_cpu_family(self.env.coredata.compilers)
+ if arch == 'x86':
+ return 'lib32-msvc-{}'.format(comp_ts_version)
+ elif arch == 'x86_64':
+ return 'lib64-msvc-{}'.format(comp_ts_version)
+ else:
+ # Does anyone do Boost cross-compiling to other archs on Windows?
+ return None
+
+ def find_libraries_with_abi_tag(self, tag):
+
+ # All modules should have the same tag
+ self.lib_modules = {}
+
+ all_found = True
+
+ for module in self.requested_modules:
+ libname = 'boost_' + module + 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 '{}' (ABI tag = '{}')".format(libname, module, tag))
+ all_found = False
+ else:
+ mlog.debug('Link args for boost module "{}" are {}'.format(module, args))
+ self.lib_modules['boost_' + module] = args
+
+ return all_found
+
+ def find_libraries_with_abi_tags(self, tags):
+ for tag in tags:
+ if self.find_libraries_with_abi_tag(tag):
+ return True
+ return False
+
+ def detect_lib_modules_win(self):
if not self.libdir:
# The libdirs in the distributed binaries (from sf)
- if arch == 'x86':
- lib_sf = 'lib32-msvc-{}'.format(comp_ts_version)
- elif arch == 'x86_64':
- lib_sf = 'lib64-msvc-{}'.format(comp_ts_version)
- else:
- # Does anyone do Boost cross-compiling to other archs on Windows?
- lib_sf = None
+ lib_sf = self.sourceforge_dir()
+
if self.boost_root:
roots = [self.boost_root]
else:
@@ -335,12 +412,8 @@ class BoostDependency(ExternalDependency):
return
for name in self.need_static_link:
- libname = "lib{}".format(name) + '-' + compiler
- if self.is_multithreading:
- libname = libname + '-mt'
- if self.is_debug:
- libname = libname + '-gd'
- libname = libname + "-{}.lib".format(self.version.replace('.', '_'))
+ # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a
+ libname = 'lib' + name + self.versioned_abi_tag() + '.lib'
if os.path.isfile(os.path.join(self.libdir, libname)):
self.lib_modules[self.modname_from_filename(libname)] = [libname]
else:
@@ -351,52 +424,23 @@ class BoostDependency(ExternalDependency):
# globber1 applies to a layout=system installation
# globber2 applies to a layout=versioned installation
globber1 = 'libboost_*' if self.static else 'boost_*'
- globber2 = globber1 + '-' + compiler
- if self.is_multithreading:
- globber2 = globber2 + '-mt'
- if self.is_debug:
- globber2 = globber2 + '-gd'
- globber2 = globber2 + '-{}'.format(self.version.replace('.', '_'))
+ globber2 = globber1 + self.versioned_abi_tag()
+ # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a
globber2_matches = glob.glob(os.path.join(self.libdir, globber2 + '.lib'))
for entry in globber2_matches:
fname = os.path.basename(entry)
self.lib_modules[self.modname_from_filename(fname)] = [fname]
if len(globber2_matches) == 0:
+ # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a
for entry in glob.glob(os.path.join(self.libdir, globber1 + '.lib')):
if self.static:
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:
- 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))
- all_found = False
- else:
- mlog.debug('Link args for boost module "{}" are {}'.format(module, args))
- self.lib_modules['boost_' + module] = args
- if all_found:
- return
-
if self.static:
libsuffix = 'a'
- elif mesonlib.is_osx() and not self.want_cross:
+ elif mesonlib.for_darwin(self.want_cross, self.env):
libsuffix = 'dylib'
else:
libsuffix = 'so'
@@ -442,7 +486,7 @@ class BoostDependency(ExternalDependency):
def get_link_args(self):
args = []
for dir in self.extra_lib_dirs():
- args += self.compiler.get_linker_search_args(self.libdir)
+ args += self.compiler.get_linker_search_args(dir)
for lib in self.requested_modules:
args += self.lib_modules['boost_' + lib]
return args
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 524df73..4bd7d7f 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -684,6 +684,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):
@@ -1580,6 +1582,8 @@ class Interpreter(InterpreterBase):
self.build.cross_stdlibs[l] = subproj.get_variable_method([depname], {})
except KeyError:
pass
+ except InvalidArguments:
+ pass
@stringArgs
@noKwargs
@@ -1685,7 +1689,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 = []
@@ -1701,7 +1712,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:
@@ -1725,8 +1736,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)
@@ -2192,10 +2211,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/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 d4ea06a..16eaf78 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -154,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:
@@ -173,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/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/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' ])