aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Build-options.md7
-rw-r--r--docs/markdown/Dependencies.md12
-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/Using-wraptool.md22
-rw-r--r--mesonbuild/backend/backends.py23
-rw-r--r--mesonbuild/dependencies/misc.py206
-rw-r--r--mesonbuild/interpreter.py22
-rw-r--r--mesonbuild/optinterpreter.py33
-rw-r--r--test cases/common/15 mixed pch/meson.build19
-rw-r--r--test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/a.c15
-rw-r--r--test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build4
-rw-r--r--test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here1
-rw-r--r--test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/b.c14
-rw-r--r--test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/meson.build3
-rw-r--r--test cases/common/177 subproject nested subproject dirs/meson.build7
-rw-r--r--test cases/common/177 subproject nested subproject dirs/prog.c5
-rw-r--r--test cases/unit/19 bad command line options/subprojects/one/meson.build2
19 files changed, 311 insertions, 142 deletions
diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md
index f70dda5..9ccdf83 100644
--- a/docs/markdown/Build-options.md
+++ b/docs/markdown/Build-options.md
@@ -107,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/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/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 a542ff6..8041526 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -33,6 +33,7 @@ from .modules import ModuleReturnValue
import os, sys, shutil, uuid
import re, shlex
from collections import namedtuple
+from pathlib import PurePath
import importlib
@@ -1983,7 +1984,7 @@ to directly access options of other subprojects.''')
@noKwargs
def func_error(self, node, args, kwargs):
self.validate_arguments(args, 1, [str])
- raise InterpreterException('Error encountered: ' + args[0])
+ raise InterpreterException('Problem encountered: ' + args[0])
@noKwargs
def func_exception(self, node, args, kwargs):
@@ -2365,10 +2366,10 @@ root and issuing %s.
raise
# If the subproject execution failed in a non-fatal way, don't raise an
# exception; let the caller handle things.
- except:
+ except Exception as e:
mlog.log('Also couldn\'t find a fallback subproject in',
mlog.bold(os.path.join(self.subproject_dir, dirname)),
- 'for the dependency', mlog.bold(name))
+ 'for the dependency', mlog.bold(name), '\nReason:', str(e))
return None
dep = self.get_subproject_dep(name, dirname, varname, kwargs.get('required', True))
if not dep:
@@ -2989,11 +2990,16 @@ different subdirectory.
def evaluate_subproject_info(self, path_from_source_root, subproject_dirname):
depth = 0
subproj_name = ''
- segs = path_from_source_root.split(os.path.sep)
- while segs and segs[0] == subproject_dirname:
- depth += 1
- subproj_name = segs[1]
- segs = segs[2:]
+ segs = PurePath(path_from_source_root).parts
+ segs_spd = PurePath(subproject_dirname).parts
+ while segs and segs[0] == segs_spd[0]:
+ if len(segs_spd) == 1:
+ subproj_name = segs[1]
+ segs = segs[2:]
+ depth += 1
+ else:
+ segs_spd = segs_spd[1:]
+ segs = segs[1:]
return (depth, subproj_name)
# Check that the indicated file is within the same subproject
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/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/a.c b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/a.c
new file mode 100644
index 0000000..7ac3e5e
--- /dev/null
+++ b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/a.c
@@ -0,0 +1,15 @@
+int func2();
+
+#if defined _WIN32 || defined __CYGWIN__
+ #define DLL_PUBLIC __declspec(dllexport)
+#else
+ #if defined __GNUC__
+ #define DLL_PUBLIC __attribute__ ((visibility("default")))
+ #else
+ #pragma message ("Compiler does not support symbol visibility.")
+ #define DLL_PUBLIC
+ #endif
+#endif
+
+int DLL_PUBLIC func() { return func2(); }
+
diff --git a/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build
new file mode 100644
index 0000000..12f6564
--- /dev/null
+++ b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build
@@ -0,0 +1,4 @@
+project('alpha project', 'c', subproject_dir: 'var/subprojects')
+
+b = subproject('beta')
+l = shared_library('a', 'a.c', link_with : b.get_variable('lb'))
diff --git a/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here
new file mode 100644
index 0000000..8d1c8b6
--- /dev/null
+++ b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here
@@ -0,0 +1 @@
+
diff --git a/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/b.c b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/b.c
new file mode 100644
index 0000000..a95651b
--- /dev/null
+++ b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/b.c
@@ -0,0 +1,14 @@
+#if defined _WIN32 || defined __CYGWIN__
+ #define DLL_PUBLIC __declspec(dllexport)
+#else
+ #if defined __GNUC__
+ #define DLL_PUBLIC __attribute__ ((visibility("default")))
+ #else
+ #pragma message ("Compiler does not support symbol visibility.")
+ #define DLL_PUBLIC
+ #endif
+#endif
+
+int DLL_PUBLIC func2() {
+ return 42;
+}
diff --git a/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/meson.build b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/meson.build
new file mode 100644
index 0000000..ea4cc9b
--- /dev/null
+++ b/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/meson.build
@@ -0,0 +1,3 @@
+project('beta project', 'c')
+
+lb = shared_library('b', 'b.c')
diff --git a/test cases/common/177 subproject nested subproject dirs/meson.build b/test cases/common/177 subproject nested subproject dirs/meson.build
new file mode 100644
index 0000000..a4d0a97
--- /dev/null
+++ b/test cases/common/177 subproject nested subproject dirs/meson.build
@@ -0,0 +1,7 @@
+project('gamma project', 'c', subproject_dir: 'contrib/subprojects')
+
+a = subproject('alpha')
+lib = a.get_variable('l')
+
+exe = executable('prog', 'prog.c', link_with : lib)
+test('basic', exe)
diff --git a/test cases/common/177 subproject nested subproject dirs/prog.c b/test cases/common/177 subproject nested subproject dirs/prog.c
new file mode 100644
index 0000000..394f139
--- /dev/null
+++ b/test cases/common/177 subproject nested subproject dirs/prog.c
@@ -0,0 +1,5 @@
+int func();
+
+int main(int argc, char **argv) {
+ return func() == 42 ? 0 : 1;
+}
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' ])