aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contributing.txt70
-rw-r--r--docs/markdown/Contributing.md144
-rw-r--r--docs/markdown/Disabler.md2
-rw-r--r--docs/markdown/index.md20
-rw-r--r--docs/markdown/snippets/if-release.md7
-rw-r--r--docs/sitemap.txt1
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/compilers/c.py18
-rw-r--r--mesonbuild/compilers/compilers.py20
-rw-r--r--mesonbuild/compilers/cpp.py16
-rw-r--r--mesonbuild/compilers/cs.py4
-rw-r--r--mesonbuild/compilers/d.py16
-rw-r--r--mesonbuild/compilers/fortran.py38
-rw-r--r--mesonbuild/coredata.py4
-rw-r--r--mesonbuild/dependencies/misc.py25
-rw-r--r--mesonbuild/environment.py34
-rw-r--r--mesonbuild/interpreter.py44
-rw-r--r--mesonbuild/mesonmain.py2
-rw-r--r--mesonbuild/modules/gnome.py31
-rw-r--r--mesonbuild/optinterpreter.py9
-rwxr-xr-xrun_project_tests.py11
-rwxr-xr-xrun_unittests.py65
-rw-r--r--test cases/common/173 default options prefix dependent defaults/meson.build1
-rw-r--r--test cases/failing/68 subproj different versions/main.c9
-rw-r--r--test cases/failing/68 subproj different versions/meson.build9
-rw-r--r--test cases/failing/68 subproj different versions/subprojects/a/a.c5
-rw-r--r--test cases/failing/68 subproj different versions/subprojects/a/a.h1
-rw-r--r--test cases/failing/68 subproj different versions/subprojects/a/meson.build11
-rw-r--r--test cases/failing/68 subproj different versions/subprojects/b/b.c5
-rw-r--r--test cases/failing/68 subproj different versions/subprojects/b/b.h1
-rw-r--r--test cases/failing/68 subproj different versions/subprojects/b/meson.build11
-rw-r--r--test cases/failing/68 subproj different versions/subprojects/c/c.h3
-rw-r--r--test cases/failing/68 subproj different versions/subprojects/c/meson.build5
-rw-r--r--test cases/failing/69 wrong boost module/meson.build5
-rw-r--r--test cases/frameworks/1 boost/meson.build2
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml1
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/meson.build6
-rw-r--r--test cases/frameworks/10 gtk-doc/include/generate-enums-docbook.py63
-rw-r--r--test cases/frameworks/10 gtk-doc/include/meson.build6
-rw-r--r--test cases/frameworks/21 libwmf/meson.build5
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/main.c9
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/meson.build9
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.c5
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.h1
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/subprojects/a/meson.build11
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.c11
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.h1
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/subprojects/b/meson.build17
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/subprojects/c/c.h3
-rw-r--r--test cases/linuxlike/12 subprojects in subprojects/subprojects/c/meson.build5
-rw-r--r--test cases/linuxlike/5 dependency versions/meson.build5
-rw-r--r--test cases/unit/11 build_rpath/meson.build9
-rw-r--r--test cases/unit/11 build_rpath/prog.cc8
-rw-r--r--test cases/unit/19 bad command line options/meson.build17
-rw-r--r--test cases/unit/19 bad command line options/meson_options.txt16
-rw-r--r--test cases/unit/19 bad command line options/subprojects/one/meson.build15
-rw-r--r--test cases/unit/19 bad command line options/subprojects/one/meson_options.txt15
57 files changed, 726 insertions, 163 deletions
diff --git a/contributing.txt b/contributing.txt
index 094c5e6..b1c015c 100644
--- a/contributing.txt
+++ b/contributing.txt
@@ -1,70 +1,4 @@
Contributing to the Meson build system
-There are two simple ways to submit your patches. The preferred way is
-to send a github pull request. Small changes can also be sent as
-patches as emails to the Meson mailing list.
-
-
-Python Coding style
-
-Meson follows the basic Python coding style. Additional rules are the
-following:
-
-- indent 4 spaces, no tabs ever
-- indent meson.build files with two spaces
-- try to keep the code as simple as possible
-- contact the mailing list before embarking on large scale projects
- to avoid wasted effort
-- all new features must come with a test (or several if it is
- a big feature)
-
-Meson uses Flake8 for style guide enforcement. The Flake8 options for
-the project are contained in setup.cfg.
-
-To run Flake8 on your local clone of Meson:
-
- $ python3 -m pip install flake8
- $ cd meson
- $ flake8
-
-C/C++ coding style
-
-Meson has a bunch of test code in several languages. The rules for
-those are simple.
-
-- indent 4 spaces, no tabs ever
-- brace always on the same line as if/for/else/function definition
-
-
-External dependencies
-
-The goal of Meson is to be as easily usable as possible. The user
-experience should be "get Python3 and Ninja, run", even on
-Windows. Unfortunately this means that we can't have dependencies on
-projects outside of Python's standard library. This applies only to
-core functionality, though. For additional helper programs etc the use
-of external dependencies may be ok. If you feel that you are dealing
-with this kind of case, please raise the issue on the mailing list
-first.
-
-
-What not to contribute?
-
-There are a few things that people seem to want to add to Meson but which
-are not there by design and will not be added either.
-
-The first one is defining your own functions or a generalized for loop.
-These are bad because they would make Meson's DSL Turing complete. The
-second feature is a Make backend.
-
-The FAQ has specific information why these two features will not be
-added to Meson: http://mesonbuild.com/FAQ.html
-
-Merge requests adding either of these two features will be automatically
-rejected. Please save everyone's time (especially your own) and don't start
-working on these features.
-
-
-Do I need to sign a CLA?
-
-No. All contributions are welcome.
+Contribution instructions can be found [on the
+website](http://mesonbuild.com/Contributing.html).
diff --git a/docs/markdown/Contributing.md b/docs/markdown/Contributing.md
new file mode 100644
index 0000000..354bf62
--- /dev/null
+++ b/docs/markdown/Contributing.md
@@ -0,0 +1,144 @@
+---
+short-description: Contributing to Meson
+...
+
+# Contributing to Meson
+
+A large fraction of Meson is contributed by people outside the core
+team. This documentation explains some of the design rationales of
+Meson as well as how to create and submit your patches for inclusion
+to Meson.
+
+Thank you for your interest in participating to the development.
+
+## Submitting patches
+
+All changes must be submitted as [pull requests to
+Github](https://github.com/mesonbuild/meson/pulls). This causes them
+to be run through the CI system. All submissions must pass a full CI
+test run before they are even considered for submission.
+
+## Tests
+
+All new features must come with automatic tests that throughly prove
+that the feature is working as expected. Similarly bug fixes must come
+with a unit test that demonstrates the bug, proves that it has been
+fixed and prevents the feature from breaking in the future.
+
+Sometimes it is difficult to create a unit test for a given bug. If
+this is the case, note this in your pull request. We may permit bug
+fix merge requests in these cases. This is done on a case by case
+basis. Sometimes it may be easier to write the test than convince the
+maintainers that one is not needed. Exercise judgment and ask for help
+in problematic cases.
+
+## Documentation
+
+The `docs` directory contains the full documentation that will be used
+to generate [the Meson web site](http://mesonbuild.com). Every change
+in functionality must change the documentation pages. In most cases
+this means updating the reference documentation page but bigger
+changes might need changes in other documentation, too.
+
+All new functionality needs to have a mention in the release
+notes. These features should be written in standalone files in the
+`docs/markdown/snippets` directory. The release manager will combine
+them into one page when doing the release.
+
+## Python Coding style
+
+Meson follows the basic Python coding style. Additional rules are the
+following:
+
+- indent 4 spaces, no tabs ever
+- indent meson.build files with two spaces
+- try to keep the code as simple as possible
+- contact the mailing list before embarking on large scale projects
+ to avoid wasted effort
+
+Meson uses Flake8 for style guide enforcement. The Flake8 options for
+the project are contained in setup.cfg.
+
+To run Flake8 on your local clone of Meson:
+
+```console
+$ python3 -m pip install flake8
+$ cd meson
+$ flake8
+```
+
+## C/C++ coding style
+
+Meson has a bunch of test code in several languages. The rules for
+those are simple.
+
+- indent 4 spaces, no tabs ever
+- brace always on the same line as if/for/else/function definition
+
+
+
+## External dependencies
+
+The goal of Meson is to be as easily usable as possible. The user
+experience should be "get Python3 and Ninja, run", even on
+Windows. Unfortunately this means that we can't have dependencies on
+projects outside of Python's standard library. This applies only to
+core functionality, though. For additional helper programs etc the use
+of external dependencies may be ok. If you feel that you are dealing
+with this kind of case, please contact the developers first with your
+use case.
+
+## Turing completeness
+
+The main design principle of Meson is that the definition language is
+not Turing complete. Any change that would make Meson Turing complete
+is automatically rejected. In practice this means that defining your
+own functions inside `meson.build` files and generalised loops will
+not be added to the language.
+
+## Do I need to sign a CLA in order to contribute?
+
+No you don't. All contributions are welcome.
+
+## No lingering state
+
+Meson operates in much the same way as functional programming
+languages. It has inputs, which include `meson.build` files, values of
+options, compilers and so on. These are passed to a function, which
+generates output build definition. This function is pure, which means that:
+
+ - for any given input the output is always the same
+ - running Meson twice in a row _always_ produce the same output in both runs
+
+The latter one is important, because it enforces that there is no way
+for "secret state" to pass between consecutive invocations of
+Meson. This is the reason why, for example, there is no `set_option`
+function even though there is a `get_option` one.
+
+If this were not the case, we could never know if the build output is
+"stable". For example suppose there were a `set_option` function and a
+boolean variable `flipflop`. Then you could do this:
+
+```meson
+set_option('flipflop', not get_option('flipflop'))
+```
+
+This piece of code would never converge. Every Meson run would change
+the value of the option and thus the output you get out of this build
+definition would be random.
+
+Meson does not permit this by forbidding these sorts of covert channels.
+
+There is one exception to this rule. Users can call into external
+commands with `run_command`. If the output of that command does not
+behave like a pure function, this problem arises. Meson does not try
+to guard against this case, it is the responsibility of the user to
+make sure the commands they run behave like pure functions.
+
+## Environment variables
+
+Environment variables are like global variables, except that they are
+also hidden by default. Envvars should be avoided whenever possible,
+all functionality should be exposed in better ways such as command
+line switches.
+
diff --git a/docs/markdown/Disabler.md b/docs/markdown/Disabler.md
index bd2b322..81417f6 100644
--- a/docs/markdown/Disabler.md
+++ b/docs/markdown/Disabler.md
@@ -63,4 +63,4 @@ endif
This concentrates the handling of this option in one place and other
build definition files do not need to be sprinkled with `if`
-statements. \ No newline at end of file
+statements.
diff --git a/docs/markdown/index.md b/docs/markdown/index.md
index 81c17ff..5f42cc7 100644
--- a/docs/markdown/index.md
+++ b/docs/markdown/index.md
@@ -6,9 +6,13 @@ render-subpages: false
## Overview
-Meson is an open source build system meant to be both extremely fast, and, even more importantly, as user friendly as possible.
+Meson is an open source build system meant to be both extremely fast,
+and, even more importantly, as user friendly as possible.
-The main design point of Meson is that every moment a developer spends writing or debugging build definitions is a second wasted. So is every second spent waiting for the build system to actually start compiling code.
+The main design point of Meson is that every moment a developer spends
+writing or debugging build definitions is a second wasted. So is every
+second spent waiting for the build system to actually start compiling
+code.
## Features
@@ -22,12 +26,18 @@ The main design point of Meson is that every moment a developer spends writing o
## Community
-There are two main methods of connecting with other Meson developers. The first one is the mailing list, which is hosted at [Google Groups](https://groups.google.com/forum/#!forum/mesonbuild).
+There are two main methods of connecting with other Meson
+developers. The first one is the mailing list, which is hosted at
+[Google Groups](https://groups.google.com/forum/#!forum/mesonbuild).
-The second way is via IRC. The channel to use is `#mesonbuild` at [Freenode](https://freenode.net/).
+The second way is via IRC. The channel to use is `#mesonbuild` at
+[Freenode](https://freenode.net/).
## Development
-All development on Meson is done on [GitHub project](https://github.com/mesonbuild/meson). For further info look into the `contributing.txt` file that comes with Meson's source checkout.
+All development on Meson is done on [GitHub
+project](https://github.com/mesonbuild/meson). Instruction on
+contributing can be found on the [contribution page](Contributing.md).
+
You do not need to sign a CLA to contribute to Meson.
diff --git a/docs/markdown/snippets/if-release.md b/docs/markdown/snippets/if-release.md
new file mode 100644
index 0000000..96e12ef
--- /dev/null
+++ b/docs/markdown/snippets/if-release.md
@@ -0,0 +1,7 @@
+## b_ndebug : if-release
+
+The value `if-release` can be given for the `b_ndebug` project option.
+
+This will make the `NDEBUG` pre-compiler macro to be defined for release
+type builds as if the `b_ndebug` project option had had the value `true`
+defined for it.
diff --git a/docs/sitemap.txt b/docs/sitemap.txt
index 77a4e6f..b7ee136 100644
--- a/docs/sitemap.txt
+++ b/docs/sitemap.txt
@@ -90,5 +90,6 @@ index.md
Use-of-Python.md
Users.md
Using-multiple-build-directories.md
+ Contributing.md
legal.md
Videos.md
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 7757300..4a35bec 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1776,7 +1776,7 @@ class CustomTargetIndex:
def __repr__(self):
return '<CustomTargetIndex: {!r}[{}]>'.format(
- self.target, self.target.output.index(self.output))
+ self.target, self.target.get_outputs().index(self.output))
def get_outputs(self):
return [self.output]
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 8753c56..233fc84 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -42,11 +42,11 @@ from .compilers import (
class CCompiler(Compiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
# If a child ObjC or CPP class has already set it, don't set it ourselves
if not hasattr(self, 'language'):
self.language = 'c'
- super().__init__(exelist, version)
+ super().__init__(exelist, version, **kwargs)
self.id = 'unknown'
self.is_cross = is_cross
self.can_compile_suffixes.add('h')
@@ -97,7 +97,7 @@ class CCompiler(Compiler):
return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
def get_dependency_gen_args(self, outtarget, outfile):
- return ['-MMD', '-MQ', outtarget, '-MF', outfile]
+ return ['-MD', '-MQ', outtarget, '-MF', outfile]
def depfile_for_object(self, objfile):
return objfile + '.' + self.get_depfile_suffix()
@@ -800,8 +800,8 @@ class CCompiler(Compiler):
class ClangCCompiler(ClangCompiler, CCompiler):
- def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None):
- CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
+ def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None, **kwargs):
+ CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs)
ClangCompiler.__init__(self, clang_type)
default_warn_args = ['-Wall', '-Winvalid-pch']
self.warn_args = {'1': default_warn_args,
@@ -832,8 +832,8 @@ class ClangCCompiler(ClangCompiler, CCompiler):
class GnuCCompiler(GnuCompiler, CCompiler):
- def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None):
- CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
+ def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
+ CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs)
GnuCompiler.__init__(self, gcc_type, defines)
default_warn_args = ['-Wall', '-Winvalid-pch']
self.warn_args = {'1': default_warn_args,
@@ -871,8 +871,8 @@ class GnuCCompiler(GnuCompiler, CCompiler):
class IntelCCompiler(IntelCompiler, CCompiler):
- def __init__(self, exelist, version, icc_type, is_cross, exe_wrapper=None):
- CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
+ def __init__(self, exelist, version, icc_type, is_cross, exe_wrapper=None, **kwargs):
+ CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs)
IntelCompiler.__init__(self, icc_type)
self.lang_header = 'c-header'
default_warn_args = ['-Wall', '-w3', '-diag-disable:remark', '-Wpch-messages']
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 011c222..24ae3c9 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -224,9 +224,8 @@ base_options = {'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled he
'b_colorout': coredata.UserComboOption('b_colorout', 'Use colored output',
['auto', 'always', 'never'],
'always'),
- 'b_ndebug': coredata.UserBooleanOption('b_ndebug',
- 'Disable asserts',
- False),
+ 'b_ndebug': coredata.UserComboOption('b_ndebug', 'Disable asserts',
+ ['true', 'false', 'if-release'], 'false'),
'b_staticpic': coredata.UserBooleanOption('b_staticpic',
'Build static libraries as position independent',
True),
@@ -313,7 +312,7 @@ def get_base_compile_args(options, compiler):
except KeyError:
pass
try:
- if options['b_ndebug'].value:
+ if options['b_ndebug'].value == 'true' or (options['b_ndebug'].value == 'if-release' and options['buildtype'] == 'release'):
args += ['-DNDEBUG']
except KeyError:
pass
@@ -598,7 +597,7 @@ class Compiler:
# compiler or the C library. Currently only used for MSVC.
ignore_libs = ()
- def __init__(self, exelist, version):
+ def __init__(self, exelist, version, **kwargs):
if isinstance(exelist, str):
self.exelist = [exelist]
elif isinstance(exelist, list):
@@ -612,6 +611,10 @@ class Compiler:
self.can_compile_suffixes = set(self.file_suffixes)
self.default_suffix = self.file_suffixes[0]
self.version = version
+ if 'full_version' in kwargs:
+ self.full_version = kwargs['full_version']
+ else:
+ self.full_version = None
self.base_options = []
def __repr__(self):
@@ -860,7 +863,12 @@ class Compiler:
# Not needed on Windows or other platforms that don't use RPATH
# https://github.com/mesonbuild/meson/issues/1897
lpaths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
- args += ['-Wl,-rpath-link,' + lpaths]
+
+ # clang expands '-Wl,rpath-link,' to ['-rpath-link'] instead of ['-rpath-link','']
+ # This eats the next argument, which happens to be 'ldstdc++', causing link failures.
+ # We can dodge this problem by not adding any rpath_paths if the argument is empty.
+ if lpaths.strip() != '':
+ args += ['-Wl,-rpath-link,' + lpaths]
return args
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index cb4b055..5e32ace 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -28,11 +28,11 @@ from .compilers import (
)
class CPPCompiler(CCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrap):
+ def __init__(self, exelist, version, is_cross, exe_wrap, **kwargs):
# If a child ObjCPP class has already set it, don't set it ourselves
if not hasattr(self, 'language'):
self.language = 'cpp'
- CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
+ CCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs)
def get_display_language(self):
return 'C++'
@@ -66,8 +66,8 @@ class CPPCompiler(CCompiler):
class ClangCPPCompiler(ClangCompiler, CPPCompiler):
- def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
- CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
+ def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None, **kwargs):
+ CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs)
ClangCompiler.__init__(self, cltype)
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'1': default_warn_args,
@@ -92,8 +92,8 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
class GnuCPPCompiler(GnuCompiler, CPPCompiler):
- def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines):
- CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
+ def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines, **kwargs):
+ CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs)
GnuCompiler.__init__(self, gcc_type, defines)
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'1': default_warn_args,
@@ -133,8 +133,8 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
class IntelCPPCompiler(IntelCompiler, CPPCompiler):
- def __init__(self, exelist, version, icc_type, is_cross, exe_wrap):
- CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
+ def __init__(self, exelist, version, icc_type, is_cross, exe_wrap, **kwargs):
+ CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs)
IntelCompiler.__init__(self, icc_type)
self.lang_header = 'c++-header'
default_warn_args = ['-Wall', '-w3', '-diag-disable:remark',
diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py
index b8a4d13..dd7a433 100644
--- a/mesonbuild/compilers/cs.py
+++ b/mesonbuild/compilers/cs.py
@@ -19,9 +19,9 @@ from ..mesonlib import EnvironmentException
from .compilers import Compiler, mono_buildtype_args
class MonoCompiler(Compiler):
- def __init__(self, exelist, version):
+ def __init__(self, exelist, version, **kwargs):
self.language = 'cs'
- super().__init__(exelist, version)
+ super().__init__(exelist, version, **kwargs)
self.id = 'mono'
self.monorunner = 'mono'
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index 9739f28..9681a9f 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -42,9 +42,9 @@ d_feature_args = {'gcc': {'unittest': '-funittest',
}
class DCompiler(Compiler):
- def __init__(self, exelist, version, is_cross):
+ def __init__(self, exelist, version, is_cross, **kwargs):
self.language = 'd'
- super().__init__(exelist, version)
+ super().__init__(exelist, version, **kwargs)
self.id = 'unknown'
self.is_cross = is_cross
@@ -224,8 +224,8 @@ class DCompiler(Compiler):
class GnuDCompiler(DCompiler):
- def __init__(self, exelist, version, is_cross):
- DCompiler.__init__(self, exelist, version, is_cross)
+ def __init__(self, exelist, version, is_cross, **kwargs):
+ DCompiler.__init__(self, exelist, version, is_cross, **kwargs)
self.id = 'gcc'
default_warn_args = ['-Wall', '-Wdeprecated']
self.warn_args = {'1': default_warn_args,
@@ -267,8 +267,8 @@ class GnuDCompiler(DCompiler):
class LLVMDCompiler(DCompiler):
- def __init__(self, exelist, version, is_cross):
- DCompiler.__init__(self, exelist, version, is_cross)
+ def __init__(self, exelist, version, is_cross, **kwargs):
+ DCompiler.__init__(self, exelist, version, is_cross, **kwargs)
self.id = 'llvm'
self.base_options = ['b_coverage', 'b_colorout']
@@ -321,8 +321,8 @@ class LLVMDCompiler(DCompiler):
class DmdDCompiler(DCompiler):
- def __init__(self, exelist, version, is_cross):
- DCompiler.__init__(self, exelist, version, is_cross)
+ def __init__(self, exelist, version, is_cross, **kwargs):
+ DCompiler.__init__(self, exelist, version, is_cross, **kwargs)
self.id = 'dmd'
self.base_options = ['b_coverage', 'b_colorout']
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 2957a7c..1b42bfa 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -31,9 +31,9 @@ from .compilers import (
)
class FortranCompiler(Compiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
self.language = 'fortran'
- super().__init__(exelist, version)
+ super().__init__(exelist, version, **kwargs)
self.is_cross = is_cross
self.exe_wrapper = exe_wrapper
# Not really correct but I don't have Fortran compilers to test with. Sorry.
@@ -99,7 +99,7 @@ end program prog
def get_dependency_gen_args(self, outtarget, outfile):
# Disabled until this is fixed:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162
- # return ['-cpp', '-MMD', '-MQ', outtarget]
+ # return ['-cpp', '-MD', '-MQ', outtarget]
return []
def get_output_args(self, target):
@@ -149,8 +149,8 @@ end program prog
class GnuFortranCompiler(FortranCompiler):
- def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
+ def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
+ super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwargs)
self.gcc_type = gcc_type
self.defines = defines or {}
self.id = 'gcc'
@@ -181,8 +181,8 @@ class GnuFortranCompiler(FortranCompiler):
class G95FortranCompiler(FortranCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
+ super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
self.id = 'g95'
def get_module_outdir_args(self, path):
@@ -205,8 +205,8 @@ class G95FortranCompiler(FortranCompiler):
class SunFortranCompiler(FortranCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
+ super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
self.id = 'sun'
def get_dependency_gen_args(self, outtarget, outfile):
@@ -228,9 +228,9 @@ class SunFortranCompiler(FortranCompiler):
class IntelFortranCompiler(IntelCompiler, FortranCompiler):
std_warn_args = ['-warn', 'all']
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp')
- FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
+ FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
# FIXME: Add support for OS X and Windows in detect_fortran_compiler so
# we are sent the type of compiler
IntelCompiler.__init__(self, ICC_STANDARD)
@@ -246,8 +246,8 @@ class IntelFortranCompiler(IntelCompiler, FortranCompiler):
class PathScaleFortranCompiler(FortranCompiler):
std_warn_args = ['-fullwarn']
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
+ super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
self.id = 'pathscale'
def get_module_outdir_args(self, path):
@@ -259,8 +259,8 @@ class PathScaleFortranCompiler(FortranCompiler):
class PGIFortranCompiler(FortranCompiler):
std_warn_args = ['-Minform=inform']
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
+ super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
self.id = 'pgi'
def get_module_incdir_args(self):
@@ -279,8 +279,8 @@ class PGIFortranCompiler(FortranCompiler):
class Open64FortranCompiler(FortranCompiler):
std_warn_args = ['-fullwarn']
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
+ super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
self.id = 'open64'
def get_module_outdir_args(self, path):
@@ -293,8 +293,8 @@ class Open64FortranCompiler(FortranCompiler):
class NAGFortranCompiler(FortranCompiler):
std_warn_args = []
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
+ super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
self.id = 'nagfor'
def get_module_outdir_args(self, path):
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index cf7df5e..d4a91a7 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from . import mlog
import pickle, os, uuid
import sys
from pathlib import PurePath
@@ -148,6 +149,9 @@ class UserArrayOption(UserOption):
newvalue = ast.literal_eval(value)
else:
newvalue = [v.strip() for v in value.split(',')]
+ if len(set(newvalue)) != len(newvalue):
+ mlog.log(mlog.red('DEPRECATION:'), '''Duplicated values in an array type is deprecated.
+This will become a hard error in the future.''')
if not isinstance(newvalue, list):
raise MesonException('"{0}" should be a string array, but it is not'.format(str(newvalue)))
for i in newvalue:
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index ce9313e..7ceda3e 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -71,11 +71,6 @@ class BoostDependency(ExternalDependency):
self.is_multithreading = threading == "multi"
self.requested_modules = self.get_requested(kwargs)
- invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS]
- if invalid_modules:
- mlog.warning('Invalid Boost modules: ' + ', '.join(invalid_modules))
- self.log_fail()
- return
self.boost_root = None
self.boost_roots = []
@@ -112,6 +107,24 @@ class BoostDependency(ExternalDependency):
self.log_fail()
return
+ invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS]
+
+ # previous versions of meson allowed include dirs as modules
+ remove = []
+ for m in invalid_modules:
+ if m in os.listdir(os.path.join(self.incdir, 'boost')):
+ mlog.warning('Requested boost library', mlog.bold(m), 'that doesn\'t exist. '
+ 'This will be an error in the future')
+ remove.append(m)
+
+ self.requested_modules = [x for x in self.requested_modules if x not in remove]
+ invalid_modules = [x for x in invalid_modules if x not in remove]
+
+ if invalid_modules:
+ mlog.warning('Invalid Boost modules: ' + ', '.join(invalid_modules))
+ self.log_fail()
+ return
+
mlog.debug('Boost library root dir is', mlog.bold(self.boost_root))
mlog.debug('Boost include directory is', mlog.bold(self.incdir))
@@ -804,7 +817,7 @@ class CupsDependency(ExternalDependency):
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(['--libs'], 'link_args')
+ self.link_args = ctdep.get_config_value(['--ldflags', '--libs'], 'link_args')
self.is_found = True
return
except Exception as e:
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 0cb1450..858d31d 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -496,6 +496,7 @@ class Environment:
popen_exceptions[' '.join(compiler + [arg])] = e
continue
version = search_version(out)
+ full_version = out.split('\n', 1)[0]
if 'Free Software Foundation' in out:
defines = self.get_gnu_compiler_defines(compiler)
if not defines:
@@ -504,7 +505,7 @@ class Environment:
gtype = self.get_gnu_compiler_type(defines)
version = self.get_gnu_version_from_defines(defines)
cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
- return cls(ccache + compiler, version, gtype, is_cross, exe_wrap, defines)
+ return cls(ccache + compiler, version, gtype, is_cross, exe_wrap, defines, full_version=full_version)
if 'clang' in out:
if 'Apple' in out or mesonlib.for_darwin(want_cross, self):
cltype = CLANG_OSX
@@ -513,7 +514,7 @@ class Environment:
else:
cltype = CLANG_STANDARD
cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler
- return cls(ccache + compiler, version, cltype, is_cross, exe_wrap)
+ return cls(ccache + compiler, version, cltype, is_cross, exe_wrap, full_version=full_version)
if 'Microsoft' in out or 'Microsoft' in err:
# Latest versions of Visual Studio print version
# number to stderr but earlier ones print version
@@ -532,7 +533,7 @@ class Environment:
# TODO: add microsoft add check OSX
inteltype = ICC_STANDARD
cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler
- return cls(ccache + compiler, version, inteltype, is_cross, exe_wrap)
+ return cls(ccache + compiler, version, inteltype, is_cross, exe_wrap, full_version=full_version)
self._handle_exceptions(popen_exceptions, compilers)
def detect_c_compiler(self, want_cross):
@@ -555,6 +556,7 @@ class Environment:
continue
version = search_version(out)
+ full_version = out.split('\n', 1)[0]
if 'GNU Fortran' in out:
defines = self.get_gnu_compiler_defines(compiler)
@@ -563,29 +565,29 @@ class Environment:
continue
gtype = self.get_gnu_compiler_type(defines)
version = self.get_gnu_version_from_defines(defines)
- return GnuFortranCompiler(compiler, version, gtype, is_cross, exe_wrap, defines)
+ return GnuFortranCompiler(compiler, version, gtype, is_cross, exe_wrap, defines, full_version=full_version)
if 'G95' in out:
- return G95FortranCompiler(compiler, version, is_cross, exe_wrap)
+ return G95FortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version)
if 'Sun Fortran' in err:
version = search_version(err)
- return SunFortranCompiler(compiler, version, is_cross, exe_wrap)
+ return SunFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version)
if 'ifort (IFORT)' in out:
- return IntelFortranCompiler(compiler, version, is_cross, exe_wrap)
+ return IntelFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version)
if 'PathScale EKOPath(tm)' in err:
- return PathScaleFortranCompiler(compiler, version, is_cross, exe_wrap)
+ return PathScaleFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version)
if 'PGI Compilers' in out:
- return PGIFortranCompiler(compiler, version, is_cross, exe_wrap)
+ return PGIFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version)
if 'Open64 Compiler Suite' in err:
- return Open64FortranCompiler(compiler, version, is_cross, exe_wrap)
+ return Open64FortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version)
if 'NAG Fortran' in err:
- return NAGFortranCompiler(compiler, version, is_cross, exe_wrap)
+ return NAGFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version)
self._handle_exceptions(popen_exceptions, compilers)
def get_scratch_dir(self):
@@ -665,8 +667,9 @@ class Environment:
except OSError:
raise EnvironmentException('Could not execute C# compiler "%s"' % ' '.join(exelist))
version = search_version(out)
+ full_version = out.split('\n', 1)[0]
if 'Mono' in out:
- return MonoCompiler(exelist, version)
+ return MonoCompiler(exelist, version, full_version=full_version)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
def detect_vala_compiler(self):
@@ -721,12 +724,13 @@ class Environment:
except OSError:
raise EnvironmentException('Could not execute D compiler "%s"' % ' '.join(exelist))
version = search_version(out)
+ full_version = out.split('\n', 1)[0]
if 'LLVM D compiler' in out:
- return compilers.LLVMDCompiler(exelist, version, is_cross)
+ return compilers.LLVMDCompiler(exelist, version, is_cross, full_version=full_version)
elif 'gdc' in out:
- return compilers.GnuDCompiler(exelist, version, is_cross)
+ return compilers.GnuDCompiler(exelist, version, is_cross, full_version=full_version)
elif 'Digital Mars' in out:
- return compilers.DmdDCompiler(exelist, version, is_cross)
+ return compilers.DmdDCompiler(exelist, version, is_cross, full_version=full_version)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
def detect_swift_compiler(self):
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 58bcf1d..444a6ee 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1813,9 +1813,18 @@ to directly access options of other subprojects.''')
if coredata.is_builtin_option(key):
if self.subproject != '':
continue # Only the master project is allowed to set global options.
+ # If this was set on the command line, do not override.
if not self.environment.had_argument_for(key):
self.coredata.set_builtin_option(key, value)
- # If this was set on the command line, do not override.
+ # If we are setting the prefix, then other options which
+ # have prefix-dependent defaults need their value updating,
+ # if they haven't been explicitly set (i.e. have their
+ # default value)
+ if key == 'prefix':
+ for option in coredata.builtin_dir_noprefix_options:
+ if not (self.environment.had_argument_for(option) or
+ any([k.startswith(option + '=') for k in default_options])):
+ self.coredata.set_builtin_option(option, coredata.get_builtin_option_default(option, value))
else:
# Option values set with subproject() default_options override those
# set in project() default_options.
@@ -2021,7 +2030,11 @@ to directly access options of other subprojects.''')
continue
else:
raise
- mlog.log('Native %s compiler: ' % comp.get_display_language(), mlog.bold(' '.join(comp.get_exelist())), ' (%s %s)' % (comp.id, comp.version), sep='')
+ if comp.full_version is not None:
+ version_string = ' (%s %s "%s")' % (comp.id, comp.version, comp.full_version)
+ else:
+ version_string = ' (%s %s)' % (comp.id, comp.version)
+ mlog.log('Native %s compiler: ' % comp.get_display_language(), mlog.bold(' '.join(comp.get_exelist())), version_string, sep='')
if not comp.get_language() in self.coredata.external_args:
(preproc_args, compile_args, link_args) = environment.get_args_from_envvars(comp)
self.coredata.external_preprocess_args[comp.get_language()] = preproc_args
@@ -2127,6 +2140,8 @@ to directly access options of other subprojects.''')
# Check if we've already searched for and found this dep
if identifier in self.coredata.deps:
cached_dep = self.coredata.deps[identifier]
+ mlog.log('Cached dependency', mlog.bold(name),
+ 'found:', mlog.green('YES'))
else:
# Check if exactly the same dep with different version requirements
# was found already.
@@ -2168,13 +2183,26 @@ to directly access options of other subprojects.''')
# a higher level project, try to use it first.
if 'fallback' in kwargs:
dirname, varname = self.get_subproject_infos(kwargs)
+ required = kwargs.get('required', True)
+ wanted = kwargs.get('version', 'undefined')
+ if not isinstance(required, bool):
+ raise DependencyException('Keyword "required" must be a boolean.')
if dirname in self.subprojects:
- subproject = self.subprojects[dirname]
- try:
- # Never add fallback deps to self.coredata.deps
- return subproject.get_variable_method([varname], {})
- except KeyError:
- pass
+ found = self.subprojects[dirname].held_object.project_version
+ valid_version = wanted == 'undefined' or mesonlib.version_compare(found, wanted)
+ if required and not valid_version:
+ m = 'Version {} of {} already loaded, requested incompatible version {}'
+ raise DependencyException(m.format(found, dirname, wanted))
+ elif valid_version:
+ mlog.log('Found a', mlog.green('(cached)'), 'subproject',
+ mlog.bold(os.path.join(self.subproject_dir, dirname)), 'for',
+ mlog.bold(name))
+ subproject = self.subprojects[dirname]
+ try:
+ # Never add fallback deps to self.coredata.deps
+ return subproject.get_variable_method([varname], {})
+ except KeyError:
+ pass
# We need to actually search for this dep
exception = None
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index f261935..f811def 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -28,7 +28,7 @@ default_warning = '1'
def add_builtin_argument(p, name, **kwargs):
k = kwargs.get('dest', name.replace('-', '_'))
c = coredata.get_builtin_option_choices(k)
- b = True if kwargs.get('action', None) in ['store_true', 'store_false'] else False
+ b = kwargs.get('action', None) in ['store_true', 'store_false']
h = coredata.get_builtin_option_description(k)
if not b:
h = h.rstrip('.') + ' (default: %s).' % coredata.get_builtin_option_default(k)
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 7a01abc..ad99c14 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -776,12 +776,39 @@ This will become a hard error in the future.''')
args += self._unpack_args('--fixxrefargs=', 'fixxref_args', kwargs)
args += self._unpack_args('--mkdbargs=', 'mkdb_args', kwargs)
args += self._unpack_args('--html-assets=', 'html_assets', kwargs, state)
- args += self._unpack_args('--content-files=', 'content_files', kwargs, state)
+
+ depends = []
+ content_files = []
+ for s in mesonlib.extract_as_list(kwargs, 'content_files'):
+ if hasattr(s, 'held_object'):
+ s = s.held_object
+ if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)):
+ depends.append(s)
+ content_files.append(os.path.join(state.environment.get_build_dir(),
+ state.backend.get_target_dir(s),
+ s.get_outputs()[0]))
+ elif isinstance(s, mesonlib.File):
+ content_files.append(s.rel_to_builddir(state.build_to_src))
+ elif isinstance(s, build.GeneratedList):
+ depends.append(s)
+ for gen_src in s.get_outputs():
+ content_files.append(os.path.join(state.environment.get_source_dir(),
+ state.subdir,
+ gen_src))
+ elif isinstance(s, str):
+ content_files.append(os.path.join(state.environment.get_source_dir(),
+ state.subdir,
+ s))
+ else:
+ raise MesonException(
+ 'Invalid object type: {!r}'.format(s.__class__.__name__))
+ args += ['--content-files=' + '@@'.join(content_files)]
+
args += self._unpack_args('--expand-content-files=', 'expand_content_files', kwargs, state)
args += self._unpack_args('--ignore-headers=', 'ignore_headers', kwargs)
args += self._unpack_args('--installdir=', 'install_dir', kwargs, state)
args += self._get_build_args(kwargs, state)
- res = [build.RunTarget(targetname, command[0], command[1:] + args, [], state.subdir, state.subproject)]
+ res = [build.RunTarget(targetname, command[0], command[1:] + args, depends, state.subdir, state.subproject)]
if kwargs.get('install', True):
res.append(build.RunScript(command, args))
return ModuleReturnValue(None, res)
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index f8ccbe6..df945ab 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -15,6 +15,7 @@
import os, re
import functools
+from . import mlog
from . import mparser
from . import coredata
from . import mesonlib
@@ -146,6 +147,14 @@ 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)))
def reduce_single(self, arg):
if isinstance(arg, str):
diff --git a/run_project_tests.py b/run_project_tests.py
index b94a976..323f9a3 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -312,10 +312,19 @@ def parse_test_args(testdir):
pass
return args
+# Build directory name must be the same so CCache works over
+# consecutive invocations.
+def create_deterministic_builddir(src_dir):
+ import hashlib
+ rel_dirname = 'b ' + hashlib.sha256(src_dir.encode(errors='ignore')).hexdigest()[0:10]
+ os.mkdir(rel_dirname)
+ abs_pathname = os.path.join(os.getcwd(), rel_dirname)
+ return abs_pathname
+
def run_test(skipped, testdir, extra_args, compiler, backend, flags, commands, should_fail):
if skipped:
return None
- with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir:
+ with AutoDeletedDir(create_deterministic_builddir(testdir)) as build_dir:
with AutoDeletedDir(tempfile.mkdtemp(prefix='i ', dir=os.getcwd())) as install_dir:
try:
return _run_test(testdir, build_dir, install_dir, extra_args, compiler, backend, flags, commands, should_fail)
diff --git a/run_unittests.py b/run_unittests.py
index d5dc36e..cf229da 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -790,6 +790,45 @@ class AllPlatformTests(BasePlatformTests):
self.assertEqual(value, expected[prefix][name])
self.wipe()
+ def test_default_options_prefix_dependent_defaults(self):
+ '''
+ Tests that setting a prefix in default_options in project() sets prefix
+ dependent defaults for other options, and that those defaults can
+ be overridden in default_options or by the command line.
+ '''
+ testdir = os.path.join(self.common_test_dir, '173 default options prefix dependent defaults')
+ expected = {
+ '':
+ {'prefix': '/usr',
+ 'sysconfdir': '/etc',
+ 'localstatedir': '/var',
+ 'sharedstatedir': '/sharedstate'},
+ '--prefix=/usr':
+ {'prefix': '/usr',
+ 'sysconfdir': '/etc',
+ 'localstatedir': '/var',
+ 'sharedstatedir': '/sharedstate'},
+ '--sharedstatedir=/var/state':
+ {'prefix': '/usr',
+ 'sysconfdir': '/etc',
+ 'localstatedir': '/var',
+ 'sharedstatedir': '/var/state'},
+ '--sharedstatedir=/var/state --prefix=/usr --sysconfdir=sysconf':
+ {'prefix': '/usr',
+ 'sysconfdir': 'sysconf',
+ 'localstatedir': '/var',
+ 'sharedstatedir': '/var/state'},
+ }
+ for args in expected:
+ self.init(testdir, args.split(), default_args=False)
+ opts = self.introspect('--buildoptions')
+ for opt in opts:
+ name = opt['name']
+ value = opt['value']
+ if name in expected[args]:
+ self.assertEqual(value, expected[args][name])
+ self.wipe()
+
def test_static_library_overwrite(self):
'''
Tests that static libraries are never appended to, always overwritten.
@@ -1807,6 +1846,25 @@ class FailureTests(BasePlatformTests):
'''
self.assertMesonRaises(code, "Method.*configtool.*is invalid.*internal")
+ def test_bad_option(self):
+ tdir = os.path.join(self.unit_test_dir, '19 bad command line options')
+ os.environ['MESON_FORCE_BACKTRACE'] = '1'
+ self.init(tdir, extra_args=['-Dopt=bar', '-Dc_args=-Wall'], inprocess=True)
+ self.wipe()
+ out = self.init(tdir, extra_args=['-Dfoo=bar', '-Dbad=true'], inprocess=True)
+ self.assertRegex(
+ out, r'Unknown command line options: "bad, foo"')
+
+ def test_bad_option_subproject(self):
+ tdir = os.path.join(self.unit_test_dir, '19 bad command line options')
+ os.environ['MESON_FORCE_BACKTRACE'] = '1'
+ self.init(tdir, extra_args=['-Done:one=bar'], inprocess=True)
+ self.wipe()
+ out = self.init(tdir, extra_args=['-Done:two=bar'], inprocess=True)
+ self.assertRegex(
+ out,
+ r'In subproject one: Unknown command line options: "one:two"')
+
class WindowsTests(BasePlatformTests):
'''
@@ -2294,11 +2352,18 @@ class LinuxlikeTests(BasePlatformTests):
testdir = os.path.join(self.unit_test_dir, '11 build_rpath')
self.init(testdir)
self.build()
+ # C program RPATH
build_rpath = get_rpath(os.path.join(self.builddir, 'prog'))
self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar')
self.install()
install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog'))
self.assertEqual(install_rpath, '/baz')
+ # C++ program RPATH
+ build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx'))
+ self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar')
+ self.install()
+ install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx'))
+ self.assertEqual(install_rpath, 'baz')
def test_pch_with_address_sanitizer(self):
testdir = os.path.join(self.common_test_dir, '13 pch')
diff --git a/test cases/common/173 default options prefix dependent defaults/meson.build b/test cases/common/173 default options prefix dependent defaults/meson.build
new file mode 100644
index 0000000..9ca4ec5
--- /dev/null
+++ b/test cases/common/173 default options prefix dependent defaults/meson.build
@@ -0,0 +1 @@
+project('default options prefix dependent defaults ', 'c', default_options : ['sharedstatedir=/sharedstate', 'prefix=/usr'])
diff --git a/test cases/failing/68 subproj different versions/main.c b/test cases/failing/68 subproj different versions/main.c
new file mode 100644
index 0000000..8793c62
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/main.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include "a.h"
+#include "b.h"
+
+int main(int argc, char **argv) {
+ int life = a_fun() + b_fun();
+ printf("%d\n", life);
+ return 0;
+}
diff --git a/test cases/failing/68 subproj different versions/meson.build b/test cases/failing/68 subproj different versions/meson.build
new file mode 100644
index 0000000..7690277
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/meson.build
@@ -0,0 +1,9 @@
+project('super', 'c')
+
+# A will use version 1 of C
+a_dep = dependency('a', fallback: ['a', 'a_dep'])
+
+# B will fail becuase it requests version 2 of C
+b_dep = dependency('b', fallback: ['b', 'b_dep'])
+
+main = executable('main', files('main.c'), dependencies: [a_dep, b_dep])
diff --git a/test cases/failing/68 subproj different versions/subprojects/a/a.c b/test cases/failing/68 subproj different versions/subprojects/a/a.c
new file mode 100644
index 0000000..cd41a65
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/subprojects/a/a.c
@@ -0,0 +1,5 @@
+#include "c.h"
+
+int a_fun() {
+ return c_fun();
+}
diff --git a/test cases/failing/68 subproj different versions/subprojects/a/a.h b/test cases/failing/68 subproj different versions/subprojects/a/a.h
new file mode 100644
index 0000000..8f1d49e
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/subprojects/a/a.h
@@ -0,0 +1 @@
+int a_fun();
diff --git a/test cases/failing/68 subproj different versions/subprojects/a/meson.build b/test cases/failing/68 subproj different versions/subprojects/a/meson.build
new file mode 100644
index 0000000..e84182a
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/subprojects/a/meson.build
@@ -0,0 +1,11 @@
+project('a', 'c')
+
+c_dep = dependency('c', version:'1', fallback: ['c', 'c_dep'])
+
+alib = library('a', 'a.c',
+ dependencies: c_dep)
+
+a_dep = declare_dependency(
+ link_with: alib,
+ include_directories: include_directories('.'),
+)
diff --git a/test cases/failing/68 subproj different versions/subprojects/b/b.c b/test cases/failing/68 subproj different versions/subprojects/b/b.c
new file mode 100644
index 0000000..f85f8c3
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/subprojects/b/b.c
@@ -0,0 +1,5 @@
+#include "c.h"
+
+int b_fun(){
+return c_fun();
+}
diff --git a/test cases/failing/68 subproj different versions/subprojects/b/b.h b/test cases/failing/68 subproj different versions/subprojects/b/b.h
new file mode 100644
index 0000000..eced786
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/subprojects/b/b.h
@@ -0,0 +1 @@
+int b_fun();
diff --git a/test cases/failing/68 subproj different versions/subprojects/b/meson.build b/test cases/failing/68 subproj different versions/subprojects/b/meson.build
new file mode 100644
index 0000000..0398340
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/subprojects/b/meson.build
@@ -0,0 +1,11 @@
+project('b', 'c')
+
+c_dep = dependency('c', version:'2', fallback: ['c', 'c_dep'])
+
+blib = library('b', 'b.c',
+ dependencies: c_dep)
+
+b_dep = declare_dependency(
+ link_with: blib,
+ include_directories: include_directories('.'),
+)
diff --git a/test cases/failing/68 subproj different versions/subprojects/c/c.h b/test cases/failing/68 subproj different versions/subprojects/c/c.h
new file mode 100644
index 0000000..2b15f60
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/subprojects/c/c.h
@@ -0,0 +1,3 @@
+static int c_fun(){
+ return 3;
+}
diff --git a/test cases/failing/68 subproj different versions/subprojects/c/meson.build b/test cases/failing/68 subproj different versions/subprojects/c/meson.build
new file mode 100644
index 0000000..7184933
--- /dev/null
+++ b/test cases/failing/68 subproj different versions/subprojects/c/meson.build
@@ -0,0 +1,5 @@
+project('c', 'c', version:'1')
+
+c_dep = declare_dependency(
+ include_directories: include_directories('.')
+)
diff --git a/test cases/failing/69 wrong boost module/meson.build b/test cases/failing/69 wrong boost module/meson.build
new file mode 100644
index 0000000..7fb3a40
--- /dev/null
+++ b/test cases/failing/69 wrong boost module/meson.build
@@ -0,0 +1,5 @@
+project('boosttest', 'cpp',
+ default_options : ['cpp_std=c++11'])
+
+# abc doesn't exist
+linkdep = dependency('boost', modules : ['thread', 'system', 'test', 'abc'])
diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build
index b73f93a..771ecbc 100644
--- a/test cases/frameworks/1 boost/meson.build
+++ b/test cases/frameworks/1 boost/meson.build
@@ -9,7 +9,7 @@ add_project_arguments(['-DBOOST_LOG_DYN_LINK'],
# within one project. The need to be independent of each other.
# Use one without a library dependency and one with it.
-linkdep = dependency('boost', modules : ['thread', 'system'])
+linkdep = dependency('boost', modules : ['thread', 'system', 'test'])
staticdep = dependency('boost', modules : ['thread', 'system'], static : true)
testdep = dependency('boost', modules : ['unit_test_framework'])
nomoddep = dependency('boost')
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml b/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml
index 028b808..3894317 100644
--- a/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml
@@ -34,6 +34,7 @@
</para>
</partintro>
<xi:include href="xml/foo.xml"/>
+ <xi:include href="../include/bar.xml"/>
<xi:include href="xml/foo-version.xml"/>
</reference>
diff --git a/test cases/frameworks/10 gtk-doc/doc/meson.build b/test cases/frameworks/10 gtk-doc/doc/meson.build
index 5f08e89..7aeb98d 100644
--- a/test cases/frameworks/10 gtk-doc/doc/meson.build
+++ b/test cases/frameworks/10 gtk-doc/doc/meson.build
@@ -4,4 +4,8 @@ configure_file(input : 'version.xml.in',
output : 'version.xml',
configuration : cdata)
-gnome.gtkdoc('foobar', src_dir : inc, main_sgml : 'foobar-docs.sgml', install : true)
+gnome.gtkdoc('foobar',
+ src_dir : inc,
+ main_sgml : 'foobar-docs.sgml',
+ content_files : docbook,
+ install : true)
diff --git a/test cases/frameworks/10 gtk-doc/include/generate-enums-docbook.py b/test cases/frameworks/10 gtk-doc/include/generate-enums-docbook.py
new file mode 100644
index 0000000..41c6121
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/include/generate-enums-docbook.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+
+import sys
+
+DOC_HEADER = '''<?xml version='1.0'?>
+<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="{0}">
+ <refmeta>
+ <refentrytitle role="top_of_page" id="{0}.top_of_page">{0}</refentrytitle>
+ <refmiscinfo>{0}</refmiscinfo>
+ </refmeta>
+ <refnamediv>
+ <refname>{0}</refname>
+ <refpurpose></refpurpose>
+ </refnamediv>
+
+ <refsect2 id="{1}" role="enum">
+ <title>enum {1}</title>
+ <indexterm zone="{1}">
+ <primary>{1}</primary>
+ </indexterm>
+ <para><link linkend="{1}">{1}</link></para>
+ <refsect3 role="enum_members">
+ <title>Values</title>
+ <informaltable role="enum_members_table" pgwide="1" frame="none">
+ <tgroup cols="4">
+ <colspec colname="enum_members_name" colwidth="300px" />
+ <colspec colname="enum_members_value" colwidth="100px"/>
+ <colspec colname="enum_members_description" />
+ <tbody>
+'''
+
+DOC_ENUM = ''' <row role="constant">
+ <entry role="enum_member_name"><para>{0}</para><para></para></entry>
+ <entry role="enum_member_value"><para>= <literal>{1}</literal></para><para></para></entry>
+ <entry role="enum_member_description"></entry>
+ </row>'''
+
+DOC_FOOTER = '''
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </refsect3>
+ </refsect2>
+</refentry>
+'''
+
+if __name__ == '__main__':
+ if len(sys.argv) >= 4:
+ with open(sys.argv[1], 'w') as doc_out:
+ enum_name = sys.argv[2]
+ enum_type = sys.argv[3]
+
+ doc_out.write(DOC_HEADER.format(enum_name, enum_type))
+ for i, enum in enumerate(sys.argv[4:]):
+ doc_out.write(DOC_ENUM.format(enum, i))
+ doc_out.write(DOC_FOOTER)
+ else:
+ print('Use: ' + sys.argv[0] + ' out name type [enums]')
+
+ sys.exit(0)
diff --git a/test cases/frameworks/10 gtk-doc/include/meson.build b/test cases/frameworks/10 gtk-doc/include/meson.build
index 4c85b80..f6dd99f 100644
--- a/test cases/frameworks/10 gtk-doc/include/meson.build
+++ b/test cases/frameworks/10 gtk-doc/include/meson.build
@@ -8,3 +8,9 @@ configure_file(input : 'foo-version.h.in',
configuration : cdata,
install : true,
install_dir : get_option('includedir'))
+
+generate_enums_docbook = find_program('generate-enums-docbook.py')
+
+docbook = custom_target('enum-docbook',
+ output : 'bar.xml',
+ command : [generate_enums_docbook, '@OUTPUT@', 'BAR', 'BAR_TYPE', 'BAR_FOO'])
diff --git a/test cases/frameworks/21 libwmf/meson.build b/test cases/frameworks/21 libwmf/meson.build
index b39d8f4..1fdce2e 100644
--- a/test cases/frameworks/21 libwmf/meson.build
+++ b/test cases/frameworks/21 libwmf/meson.build
@@ -1,5 +1,10 @@
project('libwmf test', 'c')
+wm = find_program('libwmf-config', required : false)
+if not wm.found()
+ error('MESON_SKIP_TEST: libwmf-config not installed')
+endif
+
libwmf_dep = dependency('libwmf', version : '>= 0.2.8')
libwmf_ver = libwmf_dep.version()
assert(libwmf_ver.split('.').length() > 1, 'libwmf version is "@0@"'.format(libwmf_ver))
diff --git a/test cases/linuxlike/12 subprojects in subprojects/main.c b/test cases/linuxlike/12 subprojects in subprojects/main.c
new file mode 100644
index 0000000..8793c62
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/main.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include "a.h"
+#include "b.h"
+
+int main(int argc, char **argv) {
+ int life = a_fun() + b_fun();
+ printf("%d\n", life);
+ return 0;
+}
diff --git a/test cases/linuxlike/12 subprojects in subprojects/meson.build b/test cases/linuxlike/12 subprojects in subprojects/meson.build
new file mode 100644
index 0000000..4014149
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/meson.build
@@ -0,0 +1,9 @@
+project('super', 'c')
+
+# A will use version 1 of C
+a_dep = dependency('a', fallback: ['a', 'a_dep'])
+
+# B has an optional dependency on C version 2 and will therefore work
+b_dep = dependency('b', fallback: ['b', 'b_dep'])
+
+main = executable('main', files('main.c'), dependencies: [a_dep, b_dep])
diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.c b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.c
new file mode 100644
index 0000000..cd41a65
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.c
@@ -0,0 +1,5 @@
+#include "c.h"
+
+int a_fun() {
+ return c_fun();
+}
diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.h b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.h
new file mode 100644
index 0000000..8f1d49e
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.h
@@ -0,0 +1 @@
+int a_fun();
diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/meson.build b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/meson.build
new file mode 100644
index 0000000..5f579a3
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/a/meson.build
@@ -0,0 +1,11 @@
+project('a', 'c', version:'1.0')
+
+c_dep = dependency('c', version:'1', fallback: ['c', 'c_dep'])
+
+alib = library('a', 'a.c',
+ dependencies: c_dep)
+
+a_dep = declare_dependency(
+ link_with: alib,
+ include_directories: include_directories('.'),
+)
diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.c b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.c
new file mode 100644
index 0000000..4824285
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.c
@@ -0,0 +1,11 @@
+#if defined(WITH_C)
+#include "c.h"
+#endif
+
+int b_fun(){
+#if defined(WITH_C)
+return c_fun();
+#else
+return 0;
+#endif
+}
diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.h b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.h
new file mode 100644
index 0000000..eced786
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.h
@@ -0,0 +1 @@
+int b_fun();
diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/meson.build b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/meson.build
new file mode 100644
index 0000000..80903f3
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/b/meson.build
@@ -0,0 +1,17 @@
+project('b', 'c')
+
+c_dep = dependency('c', version:'2', fallback: ['c', 'c_dep'], required: false)
+
+assert(c_dep.found() == false, 'C project has the wrong version and should not be found')
+
+if c_dep.found()
+ add_global_arguments('-DWITH_C', language: 'c')
+endif
+
+blib = library('b', 'b.c',
+ dependencies: c_dep)
+
+b_dep = declare_dependency(
+ link_with: blib,
+ include_directories: include_directories('.'),
+)
diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/c.h b/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/c.h
new file mode 100644
index 0000000..2b15f60
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/c.h
@@ -0,0 +1,3 @@
+static int c_fun(){
+ return 3;
+}
diff --git a/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/meson.build b/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/meson.build
new file mode 100644
index 0000000..7184933
--- /dev/null
+++ b/test cases/linuxlike/12 subprojects in subprojects/subprojects/c/meson.build
@@ -0,0 +1,5 @@
+project('c', 'c', version:'1')
+
+c_dep = declare_dependency(
+ include_directories: include_directories('.')
+)
diff --git a/test cases/linuxlike/5 dependency versions/meson.build b/test cases/linuxlike/5 dependency versions/meson.build
index d4140b7..5d9eb32 100644
--- a/test cases/linuxlike/5 dependency versions/meson.build
+++ b/test cases/linuxlike/5 dependency versions/meson.build
@@ -41,6 +41,11 @@ assert(somelibver.type_name() == 'internal', 'somelibver should be of type "inte
somelib = dependency('somelib',
version : '== 0.1',
fallback : ['somelib', 'some_dep'])
+# Find an internal dependency again even if required = false
+somelib_reqfalse = dependency('somelib',
+ required: false,
+ fallback : ['somelib', 'some_dep'])
+assert(somelib_reqfalse.found(), 'somelib should have been found')
# Find an internal dependency again with the same name and incompatible version
somelibver = dependency('somelib',
version : '>= 0.3',
diff --git a/test cases/unit/11 build_rpath/meson.build b/test cases/unit/11 build_rpath/meson.build
index b84c259..c0bc3bd 100644
--- a/test cases/unit/11 build_rpath/meson.build
+++ b/test cases/unit/11 build_rpath/meson.build
@@ -1,4 +1,4 @@
-project('build rpath', 'c')
+project('build rpath', 'c', 'cpp')
subdir('sub')
executable('prog', 'prog.c',
@@ -7,3 +7,10 @@ executable('prog', 'prog.c',
install_rpath : '/baz',
install : true,
)
+
+executable('progcxx', 'prog.cc',
+ link_with : l,
+ build_rpath : '/foo/bar',
+ install_rpath : 'baz',
+ install : true,
+ )
diff --git a/test cases/unit/11 build_rpath/prog.cc b/test cases/unit/11 build_rpath/prog.cc
new file mode 100644
index 0000000..c7c2123
--- /dev/null
+++ b/test cases/unit/11 build_rpath/prog.cc
@@ -0,0 +1,8 @@
+#include <string>
+#include <iostream>
+
+int main(int argc, char **argv) {
+ std::string* s = new std::string("Hello");
+ delete s;
+ return 0;
+}
diff --git a/test cases/unit/19 bad command line options/meson.build b/test cases/unit/19 bad command line options/meson.build
new file mode 100644
index 0000000..b1670c0
--- /dev/null
+++ b/test cases/unit/19 bad command line options/meson.build
@@ -0,0 +1,17 @@
+# Copyright © 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+project('Bad command line options')
+
+one = subproject('one')
diff --git a/test cases/unit/19 bad command line options/meson_options.txt b/test cases/unit/19 bad command line options/meson_options.txt
new file mode 100644
index 0000000..fc09712
--- /dev/null
+++ b/test cases/unit/19 bad command line options/meson_options.txt
@@ -0,0 +1,16 @@
+# Copyright © 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+option('opt', type : 'string', description : 'An argument')
+option('good', type : 'boolean', value : true, description : 'another argument')
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
new file mode 100644
index 0000000..39ae07e
--- /dev/null
+++ b/test cases/unit/19 bad command line options/subprojects/one/meson.build
@@ -0,0 +1,15 @@
+# Copyright © 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+project('one subproject')
diff --git a/test cases/unit/19 bad command line options/subprojects/one/meson_options.txt b/test cases/unit/19 bad command line options/subprojects/one/meson_options.txt
new file mode 100644
index 0000000..7d90fae
--- /dev/null
+++ b/test cases/unit/19 bad command line options/subprojects/one/meson_options.txt
@@ -0,0 +1,15 @@
+# Copyright © 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+option('one', type : 'string', description : 'an option')