aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cross/ubuntu-armhf.txt1
-rw-r--r--data/syntax-highlighting/emacs/meson.el11
-rw-r--r--data/syntax-highlighting/vim/syntax/meson.vim4
-rw-r--r--docs/markdown/Build-options.md25
-rw-r--r--docs/markdown/Compiler-properties.md2
-rw-r--r--docs/markdown/Contributing.md2
-rw-r--r--docs/markdown/Creating-Linux-binaries.md2
-rw-r--r--docs/markdown/Dependencies.md7
-rw-r--r--docs/markdown/Disabler.md4
-rw-r--r--docs/markdown/Generating-sources.md4
-rw-r--r--docs/markdown/Icestorm-module.md27
-rw-r--r--docs/markdown/Installing.md2
-rw-r--r--docs/markdown/Reference-manual.md60
-rw-r--r--docs/markdown/Reference-tables.md2
-rw-r--r--docs/markdown/Release-notes-for-0.38.0.md2
-rw-r--r--docs/markdown/Style-guide.md36
-rw-r--r--docs/markdown/Syntax.md6
-rw-r--r--docs/markdown/Users.md15
-rw-r--r--docs/markdown/Videos.md44
-rw-r--r--docs/markdown/_Sidebar.md2
-rw-r--r--docs/markdown/i18n-module.md2
-rw-r--r--docs/markdown/snippets/config-tool-cross.md13
-rw-r--r--docs/markdown/snippets/deprecations.md14
-rw-r--r--docs/markdown/snippets/fpga.md12
-rw-r--r--docs/markdown/snippets/hexnumbers.md5
-rw-r--r--docs/markdown/snippets/install_subdir-strip_directory.md4
-rw-r--r--docs/markdown/snippets/intopt.md6
-rw-r--r--docs/markdown/snippets/project-license.md4
-rw-r--r--docs/markdown/snippets/rust-cross.md16
-rw-r--r--docs/markdown/snippets/yield.md8
-rw-r--r--docs/sitemap.txt2
-rw-r--r--mesonbuild/backend/backends.py2
-rw-r--r--mesonbuild/backend/ninjabackend.py68
-rw-r--r--mesonbuild/backend/vs2010backend.py2
-rw-r--r--mesonbuild/backend/xcodebackend.py2
-rw-r--r--mesonbuild/build.py68
-rw-r--r--mesonbuild/compilers/c.py21
-rw-r--r--mesonbuild/compilers/compilers.py13
-rw-r--r--mesonbuild/compilers/cpp.py10
-rw-r--r--mesonbuild/compilers/fortran.py2
-rw-r--r--mesonbuild/compilers/rust.py15
-rw-r--r--mesonbuild/coredata.py36
-rw-r--r--mesonbuild/dependencies/base.py44
-rw-r--r--mesonbuild/dependencies/dev.py10
-rw-r--r--mesonbuild/dependencies/misc.py97
-rw-r--r--mesonbuild/environment.py33
-rw-r--r--mesonbuild/interpreter.py62
-rw-r--r--mesonbuild/interpreterbase.py14
-rw-r--r--mesonbuild/mesonlib.py25
-rw-r--r--mesonbuild/mesonmain.py7
-rw-r--r--mesonbuild/mintro.py6
-rw-r--r--mesonbuild/mlog.py7
-rw-r--r--mesonbuild/modules/gnome.py4
-rw-r--r--mesonbuild/modules/pkgconfig.py8
-rw-r--r--mesonbuild/modules/qt.py6
-rw-r--r--mesonbuild/modules/unstable_icestorm.py85
-rw-r--r--mesonbuild/mparser.py6
-rw-r--r--mesonbuild/mtest.py12
-rw-r--r--mesonbuild/optinterpreter.py46
-rw-r--r--mesonbuild/scripts/coverage.py28
-rw-r--r--mesonbuild/scripts/gettext.py2
-rw-r--r--mesonbuild/scripts/meson_install.py74
-rw-r--r--mesonbuild/wrap/wrap.py13
-rw-r--r--mesonbuild/wrap/wraptool.py4
-rwxr-xr-xrun_project_tests.py52
-rwxr-xr-xrun_unittests.py62
-rw-r--r--test cases/common/140 get define/meson.build4
-rw-r--r--test cases/common/174 preserve gendir/base.inp (renamed from test cases/common/173 preserve gendir/base.inp)0
-rw-r--r--test cases/common/174 preserve gendir/com/mesonbuild/subbie.inp (renamed from test cases/common/173 preserve gendir/com/mesonbuild/subbie.inp)0
-rwxr-xr-xtest cases/common/174 preserve gendir/genprog.py (renamed from test cases/common/173 preserve gendir/genprog.py)1
-rw-r--r--test cases/common/174 preserve gendir/meson.build (renamed from test cases/common/173 preserve gendir/meson.build)0
-rw-r--r--test cases/common/174 preserve gendir/testprog.c (renamed from test cases/common/173 preserve gendir/testprog.c)0
-rw-r--r--test cases/common/175 get project license/bar.c6
-rw-r--r--test cases/common/175 get project license/meson.build8
-rw-r--r--test cases/common/176 yield/meson.build6
-rw-r--r--test cases/common/176 yield/meson_options.txt2
-rw-r--r--test cases/common/176 yield/subprojects/sub/meson.build4
-rw-r--r--test cases/common/176 yield/subprojects/sub/meson_options.txt2
-rw-r--r--test cases/common/47 options/meson.build4
-rw-r--r--test cases/common/47 options/meson_options.txt1
-rw-r--r--test cases/common/51 pkgconfig-gen/dependencies/exposed.c3
-rw-r--r--test cases/common/51 pkgconfig-gen/dependencies/internal.c3
-rw-r--r--test cases/common/51 pkgconfig-gen/dependencies/meson.build38
-rw-r--r--test cases/common/51 pkgconfig-gen/meson.build33
-rw-r--r--test cases/common/58 run target/meson.build3
-rw-r--r--test cases/common/66 install subdir/installed_files.txt6
-rw-r--r--test cases/common/66 install subdir/meson.build4
-rw-r--r--test cases/common/66 install subdir/nested_elided/sub/dircheck/nineth.dat1
-rw-r--r--test cases/common/66 install subdir/nested_elided/sub/eighth.dat1
-rw-r--r--test cases/common/66 install subdir/sub_elided/dircheck/fifth.dat1
-rw-r--r--test cases/common/66 install subdir/sub_elided/fourth.dat1
-rw-r--r--test cases/common/66 install subdir/subdir/meson.build2
-rw-r--r--test cases/common/66 install subdir/subdir/sub_elided/dircheck/seventh.dat1
-rw-r--r--test cases/common/66 install subdir/subdir/sub_elided/sixth.dat1
-rw-r--r--test cases/common/68 number arithmetic/meson.build6
-rw-r--r--test cases/common/90 identical target name in subproject/meson.build2
-rw-r--r--test cases/common/90 identical target name in subproject/subprojects/foo/meson.build2
-rw-r--r--test cases/failing/68 subproj different versions/meson.build2
-rw-r--r--test cases/fpga/1 simple/meson.build9
-rw-r--r--test cases/fpga/1 simple/spin.pcf6
-rw-r--r--test cases/fpga/1 simple/spin.v32
-rw-r--r--test cases/frameworks/1 boost/linkexe.cc2
-rw-r--r--test cases/frameworks/4 qt/meson.build3
-rw-r--r--test cases/frameworks/4 qt/subfolder/main.cpp10
-rw-r--r--test cases/frameworks/4 qt/subfolder/meson.build4
-rw-r--r--test cases/frameworks/4 qt/subfolder/resources/stuff3.qrc6
-rw-r--r--test cases/frameworks/4 qt/subfolder/resources/thing.pngbin0 -> 40303 bytes
-rw-r--r--test cases/linuxlike/1 pkg-config/meson.build2
-rw-r--r--test cases/rust/4 polyglot/meson.build2
-rw-r--r--test cases/unit/21 warning location/a.c (renamed from test cases/unit/20 warning location/a.c)0
-rw-r--r--test cases/unit/21 warning location/b.c (renamed from test cases/unit/20 warning location/b.c)0
-rw-r--r--test cases/unit/21 warning location/conf.in (renamed from test cases/unit/20 warning location/conf.in)0
-rw-r--r--test cases/unit/21 warning location/main.c (renamed from test cases/unit/20 warning location/main.c)0
-rw-r--r--test cases/unit/21 warning location/meson.build (renamed from test cases/unit/20 warning location/meson.build)0
-rw-r--r--test cases/unit/21 warning location/sub/c.c (renamed from test cases/unit/20 warning location/sub/c.c)0
-rw-r--r--test cases/unit/21 warning location/sub/d.c (renamed from test cases/unit/20 warning location/sub/d.c)0
-rw-r--r--test cases/unit/21 warning location/sub/meson.build (renamed from test cases/unit/20 warning location/sub/meson.build)0
-rw-r--r--test cases/unit/21 warning location/sub/sub.c (renamed from test cases/unit/20 warning location/sub/sub.c)0
-rw-r--r--test cases/unit/22 unfound pkgconfig/meson.build15
-rw-r--r--test cases/unit/22 unfound pkgconfig/some.c3
120 files changed, 1094 insertions, 438 deletions
diff --git a/cross/ubuntu-armhf.txt b/cross/ubuntu-armhf.txt
index 367eba3..6246ffe 100644
--- a/cross/ubuntu-armhf.txt
+++ b/cross/ubuntu-armhf.txt
@@ -3,6 +3,7 @@
# when cross compiled binaries can't be run we don't do that
c = '/usr/bin/arm-linux-gnueabihf-gcc-7'
cpp = '/usr/bin/arm-linux-gnueabihf-g++-7'
+rust = ['rustc', '--target', 'arm-unknown-linux-gnueabihf', '-C', 'linker=/usr/bin/arm-linux-gnueabihf-gcc-7']
ar = '/usr/arm-linux-gnueabihf/bin/ar'
strip = '/usr/arm-linux-gnueabihf/bin/strip'
pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config'
diff --git a/data/syntax-highlighting/emacs/meson.el b/data/syntax-highlighting/emacs/meson.el
index 36f7eb9..45c6983 100644
--- a/data/syntax-highlighting/emacs/meson.el
+++ b/data/syntax-highlighting/emacs/meson.el
@@ -9,12 +9,10 @@ For detail, see `comment-dwim'."
)
(comment-dwim arg)))
-;;(setq mymeson-keywords-regex (regex-opt '("if", "endif", "foreach", "endforeach")))
-
;; keywords for syntax coloring
(setq meson-keywords
`(
- ( ,(regexp-opt '("if" "endif" "for" "foreach") 'word) . font-lock-keyword-face)
+ ( ,(regexp-opt '("elif" "if" "else" "endif" "foreach" "endforeach") 'word) . font-lock-keyword-face)
)
)
@@ -23,17 +21,17 @@ For detail, see `comment-dwim'."
(setq meson-syntax-table
(let ((synTable (make-syntax-table)))
- ;; bash style comment: “# …”
+ ;; bash style comment: “# …”
(modify-syntax-entry ?# "< b" synTable)
(modify-syntax-entry ?\n "> b" synTable)
synTable))
;; define the major mode.
-(define-derived-mode meson-mode fundamental-mode
+(define-derived-mode meson-mode prog-mode
"meson-mode is a major mode for editing Meson build definition files."
:syntax-table meson-syntax-table
-
+
(setq font-lock-defaults '(meson-keywords))
(setq mode-name "meson")
@@ -41,3 +39,4 @@ For detail, see `comment-dwim'."
(define-key meson-mode-map [remap comment-dwim] 'meson-comment-dwim)
)
+(add-to-list 'auto-mode-alist '("meson.build" . meson-mode))
diff --git a/data/syntax-highlighting/vim/syntax/meson.vim b/data/syntax-highlighting/vim/syntax/meson.vim
index e06b2df..83dd66a 100644
--- a/data/syntax-highlighting/vim/syntax/meson.vim
+++ b/data/syntax-highlighting/vim/syntax/meson.vim
@@ -29,7 +29,7 @@ endif
let s:cpo_save = &cpo
setlocal cpo&vim
-" https://github.com/mesonbuild/meson/wiki/Syntax
+" http://mesonbuild.com/Syntax.html
syn keyword mesonConditional elif else if endif
syn keyword mesonRepeat foreach endforeach
syn keyword mesonOperator and not or
@@ -55,7 +55,7 @@ syn match mesonEscape "\\N{\a\+\%(\s\a\+\)*}" contained
syn match mesonEscape "\\$"
" Meson only supports integer numbers
-" https://github.com/mesonbuild/meson/wiki/Syntax#numbers
+" http://mesonbuild.com/Syntax.html#numbers
syn match mesonNumber "\<\d\+\>"
" booleans
diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md
index cd7f07d..74d2355 100644
--- a/docs/markdown/Build-options.md
+++ b/docs/markdown/Build-options.md
@@ -16,6 +16,7 @@ Here is a simple option file.
option('someoption', type : 'string', value : 'optval', description : 'An option')
option('other_one', type : 'boolean', value : false)
option('combo_opt', type : 'combo', choices : ['one', 'two', 'three'], value : 'three')
+option('integer_opt', type : 'integer', min : 0, max : 5, value : 3)
option('free_array_opt', type : 'array', value : ['one', 'two'])
option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two'])
```
@@ -39,6 +40,12 @@ A combo allows any one of the values in the `choices` parameter to be
selected. If no default value is set then the first value will be the
default.
+## Integers
+
+An integer option contains a single integer with optional upper and
+lower values that are specified with the `min` and `max` keyword
+arguments. Available since Meson version 0.45.0.
+
### Arrays
Arrays represent an array of strings. By default the array can contain
@@ -101,3 +108,21 @@ double quotes.
**NOTE:** If you cannot call `meson configure` you likely have a old
version of Meson. In that case you can call `mesonconf` instead, but
that is deprecated in newer versions
+
+## Yielding to superproject option
+
+Suppose you have a master project and a subproject. In some cases it
+might be useful to have an option that has the same value in both of
+them. This can be achieved with the `yield` keyword. Suppose you have
+an option definition like this:
+
+```meson
+option('some_option', type : 'string', value : 'value', yield : true)
+```
+
+If you build this project on its own, this option behaves like
+usual. However if you build this project as a subproject of another
+project which also has an option called `some_option`, then calling
+`get_option` returns the value of the superproject. If the value of
+`yield` is `false`, `get_option` returns the value of the subproject's
+option.
diff --git a/docs/markdown/Compiler-properties.md b/docs/markdown/Compiler-properties.md
index 4def628..579417a 100644
--- a/docs/markdown/Compiler-properties.md
+++ b/docs/markdown/Compiler-properties.md
@@ -173,7 +173,7 @@ Does a structure contain a member?
==
Some platforms have different standard structures. Here's how one
-would check if a struct called `mystruct` from header `myheader.h</hh>
+would check if a struct called `mystruct` from header `myheader.h`
contains a member called `some_member`.
```meson
diff --git a/docs/markdown/Contributing.md b/docs/markdown/Contributing.md
index 169bf4c..293b629 100644
--- a/docs/markdown/Contributing.md
+++ b/docs/markdown/Contributing.md
@@ -20,7 +20,7 @@ test run before they are even considered for submission.
## Tests
-All new features must come with automatic tests that throughly prove
+All new features must come with automatic tests that thoroughly prove
that the feature is working as expected. Similarly bug fixes must come
with a unit test that demonstrates the bug, proves that it has been
fixed and prevents the feature from breaking in the future.
diff --git a/docs/markdown/Creating-Linux-binaries.md b/docs/markdown/Creating-Linux-binaries.md
index 8ca3ef0..084e157 100644
--- a/docs/markdown/Creating-Linux-binaries.md
+++ b/docs/markdown/Creating-Linux-binaries.md
@@ -61,7 +61,7 @@ Log out and back in and now your build environment is ready to use.
## Adding other tools
Old distros might have too old versions of some tools. For Meson this
-could nclude Python 3 and Ninja. If this is the case you need to
+could include Python 3 and Ninja. If this is the case you need to
download, build and install new versions into `~/devroot` in the usual
way.
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md
index b36d275..189db72 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -144,6 +144,13 @@ pass `gtest` or `gmock` to `dependency` and it will do everything for
you. If you want to use GMock, it is recommended to use GTest as well,
as getting it to work standalone is tricky.
+You can set the `main` keyword argument to `true` to use the `main()`
+function provided by GTest:
+```
+gtest_dep = dependency('gtest', main : true, required : false)
+e = executable('testprog', 'test.cc', dependencies : gtest_dep)
+test('gtest test', e)
+```
## MPI
MPI is supported for C, C++ and Fortran. Because dependencies are
diff --git a/docs/markdown/Disabler.md b/docs/markdown/Disabler.md
index 81417f6..4aed7ad 100644
--- a/docs/markdown/Disabler.md
+++ b/docs/markdown/Disabler.md
@@ -2,7 +2,9 @@
short-description: Disabling options
...
-# Disabling parts of the build (available since 0.44.0)
+# Disabling parts of the build
+
+*This feature is available since version 0.44.0.*
The following is a common fragment found in many projects:
diff --git a/docs/markdown/Generating-sources.md b/docs/markdown/Generating-sources.md
index ae1302b..2ea1021 100644
--- a/docs/markdown/Generating-sources.md
+++ b/docs/markdown/Generating-sources.md
@@ -4,7 +4,7 @@ short-description: Generation of source files before compilation
# Generating sources
- Sometimes source files need to be preprocessed before they are passed to the actual compiler. As an example you might want build an IDL compiler and then run some files through that to generate actual source files. In Meson this is done with [`generator()`](https://github.com/mesonbuild/meson/wiki/Reference-manual#generator) or [`custom_target()`](https://github.com/mesonbuild/meson/wiki/Reference-manual#custom_target).
+ Sometimes source files need to be preprocessed before they are passed to the actual compiler. As an example you might want build an IDL compiler and then run some files through that to generate actual source files. In Meson this is done with [`generator()`](Reference-manual.md#generator) or [`custom_target()`](Reference-manual.md#custom_target).
## Using custom_target()
@@ -45,7 +45,7 @@ Generators are similar to custom targets, except that we define a *generator*, w
Note that generators should only be used for outputs that will only be used as inputs for a build target or a custom target. When you use the processed output of a generator in multiple targets, the generator will be run multiple times to create outputs for each target. Each output will be created in a target-private directory `@BUILD_DIR@`.
-If you want to generate files for general purposes such as for generating headers to be used by several sources, or data that will be installed, and so on, use a [`custom_target()`](https://github.com/mesonbuild/meson/wiki/Reference-manual#custom_target) instead.
+If you want to generate files for general purposes such as for generating headers to be used by several sources, or data that will be installed, and so on, use a [`custom_target()`](Reference-manual.md#custom_target) instead.
```meson
diff --git a/docs/markdown/Icestorm-module.md b/docs/markdown/Icestorm-module.md
new file mode 100644
index 0000000..896311f
--- /dev/null
+++ b/docs/markdown/Icestorm-module.md
@@ -0,0 +1,27 @@
+# Unstable SIMD module
+
+This module provides is available since version 0.45.0.
+
+**Note**: this module is unstable. It is only provided as a technology
+preview. Its API may change in arbitrary ways between releases or it
+might be removed from Meson altogether.
+
+## Usage
+
+This module provides an experimental to create FPGA bitstreams using
+the [IceStorm](http://www.clifford.at/icestorm/) suite of tools.
+
+The module exposes only one method called `project` and it is used
+like this:
+
+ is.project('projname',
+ <verilog files>,
+ constraint_file : <pcf file>,
+ )
+
+The input to this function is the set of Verilog files and a
+constraint file. This produces output files called `projname.asc`,
+`projname.blif` and `projname.bin`. In addition it creates two run
+targets called `projname-time` for running timing analysis and
+`projname-upload` that uploads the generated bitstream to an FPGA
+devide using the `iceprog` programming executable.
diff --git a/docs/markdown/Installing.md b/docs/markdown/Installing.md
index 2663ff4..4670544 100644
--- a/docs/markdown/Installing.md
+++ b/docs/markdown/Installing.md
@@ -26,7 +26,7 @@ Other install commands are the following.
```meson
install_headers('header.h', subdir : 'projname') # -> include/projname/header.h
install_man('foo.1') # -> share/man/man1/foo.1.gz
-install_data('datafile.cat', install_dir : join_paths(get_option('datadir'), 'progname')) # -> share/progname/datafile.dat
+install_data('datafile.dat', install_dir : join_paths(get_option('datadir'), 'progname')) # -> share/progname/datafile.dat
```
Sometimes you want to copy an entire subtree directly. For this use case there is the `install_subdir` command, which can be used like this.
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index a3e1ef0..a557f0c 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -416,7 +416,7 @@ be passed to [shared and static libraries](#library).
dynamically exported, allowing modules built using the
[`shared_module`](#shared_module) function to refer to functions,
variables and other symbols defined in the executable itself. Implies
- the `implib` argument. Since 0.44.0
+ the `implib` argument. Since 0.45.0
- `implib` when set to true, an import library is generated for the
executable (the name of the import library is based on *exe_name*).
Alternatively, when set to a string, that gives the base name for
@@ -772,7 +772,7 @@ installed with a `.gz` suffix.
### install_subdir()
``` meson
- void install_subdir(subdir_name, install_dir : ..., exclude_files : ..., exclude_directories : ...)
+ void install_subdir(subdir_name, install_dir : ..., exclude_files : ..., exclude_directories : ..., strip_directory : ...)
```
Installs the entire given subdirectory and its contents from the
@@ -786,6 +786,46 @@ The following keyword arguments are supported:
- `exclude_directories`: a list of directory names that should not be installed.
Names are interpreted as paths relative to the `subdir_name` location.
- `install_dir`: the location to place the installed subdirectory.
+- `strip_directory`: install directory contents. `strip_directory=false` by default.
+ If `strip_directory=false` only last component of source path is used.
+ Since 0.45.0
+
+For a given directory `foo`:
+```text
+foo/
+ bar/
+ file1
+ file2
+```
+`install_subdir('foo', install_dir : 'share', strip_directory : false)` creates
+```text
+share/
+ foo/
+ bar/
+ file1
+ file2
+```
+
+`install_subdir('foo', install_dir : 'share', strip_directory : true)` creates
+```text
+share/
+ bar/
+ file1
+ file2
+```
+
+`install_subdir('foo/bar', install_dir : 'share', strip_directory : false)` creates
+```text
+share/
+ bar/
+ file1
+```
+
+`install_subdir('foo/bar', install_dir : 'share', strip_directory : true)` creates
+```text
+share/
+ file1
+```
### is_variable()
@@ -910,7 +950,8 @@ Project supports the following keyword arguments.
'GPL3']`. Note that the text is informal and is only written to
the dependency manifest. Meson does not do any license validation,
you are responsible for verifying that you abide by all licensing
- terms.
+ terms. You can access the value in your Meson build files with
+ `meson.project_license()`.
- `meson_version` takes a string describing which Meson version the
project requires. Usually something like `>0.28.0`.
@@ -944,13 +985,16 @@ respectively.
### run_target
``` meson
- buildtarget run_target(target_name, ...)
+runtarget run_target(target_name, ...)
```
This function creates a new top-level target that runs a specified
command with the specified arguments. Like all top-level targets, this
integrates with the selected backend. For instance, with Ninja you can
-run it as `ninja target_name`.
+run it as `ninja target_name`. Note that a run target produces no
+output as far as Meson is concerned. It is only meant for tasks such
+as running a code formatter or flashing an external device's firmware
+with a built file.
The script is run from an *unspecified* directory, and Meson will set
three environment variables `MESON_SOURCE_ROOT`, `MESON_BUILD_ROOT`
@@ -1247,6 +1291,8 @@ the following methods.
- `project_version()` returns the version string specified in `project` function call.
+- `project_license()` returns the array of licenses specified in `project` function call.
+
- `project_name()` returns the project name specified in the `project` function call.
- `version()` return a string with the version of Meson.
@@ -1539,7 +1585,7 @@ The following methods are defined for all [arrays](Syntax.md#arrays):
- `length()`, the size of the array
You can also iterate over arrays with the [`foreach`
-statement](https://github.com/mesonbuild/meson/wiki/Syntax#foreach-statements).
+statement](Syntax.md#foreach-statements).
## Returned objects
@@ -1636,6 +1682,8 @@ an external dependency with the following methods:
dependency, error out. (*Added 0.44.0*) You can also redefine a
variable by passing a list to the `define_variable` parameter
that can affect the retrieved variable: `['prefix', '/'])`.
+ (*Added 0.45.0*) A warning is issued if the variable is not defined,
+ unless a `default` parameter is specified.
- `get_configtool_variable(varname)` (*Added 0.44.0*) will get the
command line argument from the config tool (with `--` prepended), or,
diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md
index ee3b8c2..5ee0db1 100644
--- a/docs/markdown/Reference-tables.md
+++ b/docs/markdown/Reference-tables.md
@@ -57,7 +57,7 @@ These are provided by the `.system()` method call.
| windows | Any version of Windows |
| cygwin | The Cygwin environment for Windows |
| haiku | |
-| freebsd | FreeBSD and it's derivatives |
+| freebsd | FreeBSD and its derivatives |
| dragonfly | DragonFly BSD |
| netbsd | |
diff --git a/docs/markdown/Release-notes-for-0.38.0.md b/docs/markdown/Release-notes-for-0.38.0.md
index ca6602e..741c349 100644
--- a/docs/markdown/Release-notes-for-0.38.0.md
+++ b/docs/markdown/Release-notes-for-0.38.0.md
@@ -78,7 +78,7 @@ When using compilers that implement the [`__has_include()` preprocessor macro](h
# Array indexing now supports fallback values
-The second argument to the array [`.get()`](https://github.com/mesonbuild/meson/wiki/Reference-manual#array-object) function is now returned if the specified index could not be found
+The second argument to the array [`.get()`](Reference-manual.md#array-object) function is now returned if the specified index could not be found
```meson
array = [10, 11, 12, 13]
array.get(0) # this will return `10`
diff --git a/docs/markdown/Style-guide.md b/docs/markdown/Style-guide.md
new file mode 100644
index 0000000..9008592
--- /dev/null
+++ b/docs/markdown/Style-guide.md
@@ -0,0 +1,36 @@
+---
+short-description: Style recommendations for Meson files
+...
+
+# Style recommendations
+
+This page lists some recommendations on organizing and formatting your
+Meson build files.
+
+## Tabs or spaces?
+
+Always spaces.
+
+## Naming options
+
+There are two ways of naming project options. As an example for
+booleans the first one is `foo` and the second one is
+`enable-foo`. The former style is recommended, because in Meson
+options have strong type, rather than being just strings.
+
+You should try to name options the same as is common in other
+projects. This is especially important for yielding options, because
+they require that both the parent and subproject options have the same
+name.
+
+# Global arguments
+
+Prefer `add_project_arguments` to `add_global_arguments` because using
+the latter prevents using the project as a subproject.
+
+# Cross compilation arguments
+
+Try to keep cross compilation arguments away from your build files as
+much as possible. Keep them in the cross file instead. This adds
+portability, since all changes needed to compile to a different
+platform are isolated in one place.
diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md
index 84403f4..1005100 100644
--- a/docs/markdown/Syntax.md
+++ b/docs/markdown/Syntax.md
@@ -58,6 +58,12 @@ y = 3 * 4
d = 5 % 3 # Yields 2.
```
+Hexadecimal literals are supported since version 0.45.0:
+
+```meson
+int_255 = 0xFF
+```
+
Strings can be converted to a number like this:
```meson
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index 616fdc5..f02e4c7 100644
--- a/docs/markdown/Users.md
+++ b/docs/markdown/Users.md
@@ -10,8 +10,10 @@ If you have a project that uses Meson that you want to add to this list, let us
- [Arduino sample project](https://github.com/jpakkane/mesonarduino)
- [Budgie Desktop](https://github.com/budgie-desktop/budgie-desktop), a desktop environment built on GNOME technologies
- [casync](https://github.com/systemd/casync), Content-Addressable Data Synchronization Tool
+ - [Dpdk](http://dpdk.org/ml/archives/dev/2018-January/089724.html), Data plane development kit, a set of libraries and drivers for fast packet processing
- [Emeus](https://github.com/ebassi/emeus), Constraint based layout manager for GTK+
- [Frida](https://www.frida.re/), a dynamic binary instrumentation toolkit
+ - [fwupd](https://github.com/hughsie/fwupd), a simple daemon to allow session software to update firmware
- [Geary](https://wiki.gnome.org/Apps/Geary), an email application built around conversations, for the GNOME 3 desktop.
- [GLib](https://git.gnome.org/browse/glib/), cross-platform C library used by GTK+ and GStreamer (not the default yet)
- [Gnome Builder](https://git.gnome.org/browse/gnome-builder/), an IDE for the Gnome platform
@@ -25,24 +27,37 @@ If you have a project that uses Meson that you want to add to this list, let us
- [GTK+](https://git.gnome.org/browse/gtk+/), the multi-platform toolkit used by GNOME
- [GtkDApp](https://gitlab.com/csoriano/GtkDApp), an application template for developing Flatpak apps with Gtk+ and D
- [HexChat](https://github.com/hexchat/hexchat), a cross-platform IRC client in C
+ - [IGT](https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/), Linux kernel graphics driver test suite.
+ - [JsonCpp](https://github.com/open-source-parsers/jsoncpp), a C++ library for interacting with JSON
- [Json-glib](https://git.gnome.org/browse/json-glib), GLib-based JSON manipulation library
- [Ksh](https://github.com/att/ast), a Korn Shell
+ - [Libdrm](https://cgit.freedesktop.org/drm/libdrm/), a library for abstracting DRM kernel interfaces
- [Libepoxy](https://github.com/anholt/libepoxy/), a library for handling OpenGL function pointer management
- [Libgit2-glib](https://git.gnome.org/browse/libgit2-glib/), a GLib wrapper for libgit2
- [Libhttpseverywhere](https://github.com/grindhold/libhttpseverywhere), a library to enable httpseverywhere on any desktop app
+ - [Libosmscout](https://github.com/Framstag/libosmscout), a C++ library for offline map rendering, routing and location
+lookup based on OpenStreetMap data
+ - [Libva](https://github.com/intel/libva), an implementation for the VA (VIdeo Acceleration) API
- [Lightdm-Webkit2-Greeter](https://github.com/Antergos/lightdm-webkit2-greeter)
- [Kiwix libraries](https://github.com/kiwix/kiwix-lib)
+ - [Mesa](https://www.mesa3d.org/), An open source graphics driver project
- [Nautilus](https://git.gnome.org/browse/nautilus/commit/?id=ed5652c89ac0654df2e82b54b00b27d51c825465) the Gnome file manager
- [Orc](http://cgit.freedesktop.org/gstreamer/orc/), the Optimized Inner Loop Runtime Compiler (not the default yet)
+ - [Outlier](https://github.com/kerolasa/outlier), a small Hello World style meson example project
- [Pango](https://git.gnome.org/browse/pango/), an Internationalized text layout and rendering library (not the default yet)
- [Parzip](https://github.com/jpakkane/parzip), a multithreaded reimplementation of Zip
+ - [PipeWire](https://pipewire.org/), a framework for video and audio for containerized applications
- [Pitivi](http://pitivi.org/), a nonlinear video editor
- [Polari](https://git.gnome.org/browse/polari), an IRC client
+ - [radare2](https://github.com/radare/radare2), unix-like reverse engineering framework and commandline tools (not the default)
+ - [SSHFS](https://github.com/libfuse/sshfs), allows you to mount a remote filesystem using SFTP
- [Sysprof](https://wiki.gnome.org/Apps/Sysprof), a profiling tool
- [systemd](https://github.com/systemd/systemd), the init system
+ - [Taisei Project](https://taisei-project.org/), an open-source Touhou Project clone and fangame
- [Xorg](https://cgit.freedesktop.org/xorg/xserver/) the X.org display server (not the default yet)
- [Valum](https://github.com/valum-framework/valum), a micro web framework written in Vala
- [Wayland and Weston](https://lists.freedesktop.org/archives/wayland-devel/2016-November/031984.html), a next generation display server (not merged yet)
+ - [wlroots](https://github.com/swaywm/wlroots), a modular Wayland compositor library
- [ZStandard](https://github.com/facebook/zstd/commit/4dca56ed832c6a88108a2484a8f8ff63d8d76d91) a compression algorithm developed at Facebook (not used by default)
Note that a more up-to-date list of GNOME projects that use Meson can be found [here](https://wiki.gnome.org/Initiatives/GnomeGoals/MesonPorting).
diff --git a/docs/markdown/Videos.md b/docs/markdown/Videos.md
index 5abfbe4..d9ea34d 100644
--- a/docs/markdown/Videos.md
+++ b/docs/markdown/Videos.md
@@ -4,34 +4,28 @@ short-description: Videos about Meson
# Videos
-## An overview of meson
+ - [The Meson Build System, 4+ years of work to become an overnight
+ success](https://www.youtube.com/watch?v=gHdTzdXkhRY), Linux.conf.au 2018
-(from Linux.conf.au 2015 -- Auckland, New Zealand)
+ - [Meson and the changing Linux build
+ landscape](https://media.ccc.de/v/ASG2017-111-meson_and_the_changing_linux_build_landscape),
+ All Systems Go 2017
-<div class="video-container">
-<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/KPi0AuVpxLI" allowfullscreen></iframe>
-</div>
+ - [Meson, compiling the world with
+ Python](https://www.youtube.com/watch?v=sEO4DC8hm34), Europython
+ 2017
-## Talks about design, goals behind Meson's multiplatform dependency system was held
+ - [Builds, dependencies and deployment in a modern multiplatform
+ world](https://www.youtube.com/embed/CTJtKtQ8R5k), Linux.conf.au
+ 2016
-(From Linux.conf.au 2016 -- Geelong, Australia)
+ - [New world, new tools](https://www.youtube.com/embed/0-gx1qU2pPo),
+ Libre Application Summit 2016
-<div class="video-container">
-<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/CTJtKtQ8R5k" allowfullscreen></iframe>
-</div>
+ - [Making build systems not
+ suck](https://www.youtube.com/embed/KPi0AuVpxLI), Linux.conf.au
+ 2015, Auckland, New Zealand
-## Features and benefits of Meson's multiplatform support for building and dependencies]
-
-(Libre Application Summit 2016 talk _New world, new tools_ explored further)
-
-<div class="video-container">
-<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/0-gx1qU2pPo" allowfullscreen></iframe>
-</div>
-
-## The first ever public presentation on Meson
-
-(lightning talk at FOSDEM 2014)
-
-<video width="854" height="480" controls>
- <source src=http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2014/H2215_Ferrer/Sunday/Introducing_the_Meson_build_system.webm>
-</video>
+ - [Lightning talk at FOSDEM
+ 2014](http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2014/H2215_Ferrer/Sunday/Introducing_the_Meson_build_system.webm),
+ The first ever public presentation on Meson
diff --git a/docs/markdown/_Sidebar.md b/docs/markdown/_Sidebar.md
index 89fc523..2637d68 100644
--- a/docs/markdown/_Sidebar.md
+++ b/docs/markdown/_Sidebar.md
@@ -7,7 +7,7 @@
* [Tests](Unit-tests.md)
* [Syntax](Syntax.md)
-### [Modules](https://github.com/mesonbuild/meson/wiki/Module-reference.md)
+### [Modules](Module-reference.md)
* [gnome](Gnome-module.md)
* [i18n](i18n-module.md)
diff --git a/docs/markdown/i18n-module.md b/docs/markdown/i18n-module.md
index 8fb650a..88f059b 100644
--- a/docs/markdown/i18n-module.md
+++ b/docs/markdown/i18n-module.md
@@ -40,7 +40,7 @@ This function also defines targets for maintainers to use:
### i18n.merge_file()
This merges translations into a text file using `msgfmt`. See
-[custom_target](https://github.com/mesonbuild/meson/wiki/Reference%20manual#custom_target)
+[custom_target](Reference-manual.md#custom_target)
for normal keywords. In addition it accepts these keywords:
* `data_dirs`: (*Added 0.41.0*) list of directories for its files (See
diff --git a/docs/markdown/snippets/config-tool-cross.md b/docs/markdown/snippets/config-tool-cross.md
new file mode 100644
index 0000000..1102481
--- /dev/null
+++ b/docs/markdown/snippets/config-tool-cross.md
@@ -0,0 +1,13 @@
+# Config-Tool based dependencies can be specified in a cross file
+
+Tools like LLVM and pcap use a config tool for dependencies, this is a script
+or binary that is run to get configuration information (cflags, ldflags, etc)
+from.
+
+These binaries may now be specified in the `binaries` section of a cross file.
+
+```dosini
+[binaries]
+cc = ...
+llvm-config = '/usr/bin/llvm-config32'
+```
diff --git a/docs/markdown/snippets/deprecations.md b/docs/markdown/snippets/deprecations.md
new file mode 100644
index 0000000..adab2e6
--- /dev/null
+++ b/docs/markdown/snippets/deprecations.md
@@ -0,0 +1,14 @@
+## Removed two deprecated features
+
+The standalone `find_library` function has been a no-op for a long
+time. Starting with this version it becomes a hard error.
+
+There used to be a keywordless version of `run_target` which looked
+like this:
+
+ run_target('targetname', 'command', 'arg1', 'arg2')
+
+This is now an error. The correct format for this is now:
+
+ run_target('targetname',
+ command : ['command', 'arg1', 'arg2'])
diff --git a/docs/markdown/snippets/fpga.md b/docs/markdown/snippets/fpga.md
new file mode 100644
index 0000000..b5e4938
--- /dev/null
+++ b/docs/markdown/snippets/fpga.md
@@ -0,0 +1,12 @@
+## Experimental FPGA support
+
+This version adds support for generating, analysing and uploading FPGA
+programs using the [IceStorm
+toolchain](http://www.clifford.at/icestorm/). This support is
+experimental and is currently limited to the `iCE 40` series of FPGA
+chips.
+
+FPGA generation integrates with other parts of Meson seamlessly. As an
+example, [here](https://github.com/jpakkane/lm32) is an example
+project that compiles a simple firmware into Verilog and combines that
+with an lm32 softcore processor.
diff --git a/docs/markdown/snippets/hexnumbers.md b/docs/markdown/snippets/hexnumbers.md
new file mode 100644
index 0000000..840c0cb
--- /dev/null
+++ b/docs/markdown/snippets/hexnumbers.md
@@ -0,0 +1,5 @@
+## Hexadecimal string literals
+
+Hexadecimal integer literals can now be used in build and option files.
+
+ int_255 = 0xFF
diff --git a/docs/markdown/snippets/install_subdir-strip_directory.md b/docs/markdown/snippets/install_subdir-strip_directory.md
new file mode 100644
index 0000000..9ddb4a4
--- /dev/null
+++ b/docs/markdown/snippets/install_subdir-strip_directory.md
@@ -0,0 +1,4 @@
+## install_subdir() supports strip_directory
+
+If strip_directory=true install_subdir() installs directory contents
+instead of directory itself, stripping basename of the source directory.
diff --git a/docs/markdown/snippets/intopt.md b/docs/markdown/snippets/intopt.md
new file mode 100644
index 0000000..daf660b
--- /dev/null
+++ b/docs/markdown/snippets/intopt.md
@@ -0,0 +1,6 @@
+## Integer options
+
+There is a new integer option type with optional minimum and maximum
+values. It can be specified like this in the `meson_options.txt` file:
+
+ option('integer_option', type : 'integer', min : 0, max : 5, value : 3)
diff --git a/docs/markdown/snippets/project-license.md b/docs/markdown/snippets/project-license.md
new file mode 100644
index 0000000..5da2c6a
--- /dev/null
+++ b/docs/markdown/snippets/project-license.md
@@ -0,0 +1,4 @@
+## New method meson.project_license()
+
+The `meson` builtin object now has a `project_license()` method that returns a
+list of all licenses for the project.
diff --git a/docs/markdown/snippets/rust-cross.md b/docs/markdown/snippets/rust-cross.md
new file mode 100644
index 0000000..7f18c44
--- /dev/null
+++ b/docs/markdown/snippets/rust-cross.md
@@ -0,0 +1,16 @@
+## Rust cross-compilation
+
+Cross-compilation is now supported for Rust targets. Like other
+cross-compilers, the Rust binary must be specified in your cross
+file. It should specify a `--target` (as installed by `rustup target`)
+and a custom linker pointing to your C cross-compiler. For example:
+
+```
+[binaries]
+c = '/usr/bin/arm-linux-gnueabihf-gcc-7'
+rust = [
+ 'rustc',
+ '--target', 'arm-unknown-linux-gnueabihf',
+ '-C', 'linker=/usr/bin/arm-linux-gnueabihf-gcc-7',
+]
+```
diff --git a/docs/markdown/snippets/yield.md b/docs/markdown/snippets/yield.md
new file mode 100644
index 0000000..3880e67
--- /dev/null
+++ b/docs/markdown/snippets/yield.md
@@ -0,0 +1,8 @@
+## Yielding subproject option to superproject
+
+Normally project options are specific to the current project. However
+sometimes you want to have an option whose value is the same over all
+projects. This can be achieved with the new `yield` keyword for
+options. When set to `true`, getting the value of this option in
+`meson.build` files gets the value from the option with the same name
+in the master project (if such an option exists).
diff --git a/docs/sitemap.txt b/docs/sitemap.txt
index 87a5eb5..144ca4a 100644
--- a/docs/sitemap.txt
+++ b/docs/sitemap.txt
@@ -30,6 +30,7 @@ index.md
Modules.md
Gnome-module.md
i18n-module.md
+ Icestorm-module.md
Pkgconfig-module.md
Python-3-module.md
Qt4-module.md
@@ -51,6 +52,7 @@ index.md
Project-templates.md
Reference-manual.md
Reference-tables.md
+ Style-guide.md
FAQ.md
Reproducible-builds.md
howtox.md
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 5a5db22..292b027 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -322,7 +322,7 @@ class Backend:
continue
if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so']:
continue
- absdir = os.path.split(libpath)[0]
+ absdir = os.path.dirname(libpath)
rel_to_src = absdir[len(self.environment.get_source_dir()) + 1:]
assert(not os.path.isabs(rel_to_src))
paths.append(os.path.join(self.build_to_src, rel_to_src))
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 77c7d50..6ab67fb 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -38,8 +38,12 @@ else:
execute_wrapper = ''
rmfile_prefix = 'rm -f {} &&'
-def ninja_quote(text):
- for char in ('$', ' ', ':'):
+def ninja_quote(text, is_build_line=False):
+ if is_build_line:
+ qcs = ('$', ' ', ':')
+ else:
+ qcs = ('$', ' ')
+ for char in qcs:
text = text.replace(char, '$' + char)
if '\n' in text:
errmsg = '''Ninja does not support newlines in rules. The content was:
@@ -87,13 +91,13 @@ class NinjaBuildElement:
def write(self, outfile):
self.check_outputs()
- line = 'build %s: %s %s' % (' '.join([ninja_quote(i) for i in self.outfilenames]),
+ line = 'build %s: %s %s' % (' '.join([ninja_quote(i, True) for i in self.outfilenames]),
self.rule,
- ' '.join([ninja_quote(i) for i in self.infilenames]))
+ ' '.join([ninja_quote(i, True) for i in self.infilenames]))
if len(self.deps) > 0:
- line += ' | ' + ' '.join([ninja_quote(x) for x in self.deps])
+ line += ' | ' + ' '.join([ninja_quote(x, True) for x in self.deps])
if len(self.orderdeps) > 0:
- line += ' || ' + ' '.join([ninja_quote(x) for x in self.orderdeps])
+ line += ' || ' + ' '.join([ninja_quote(x, True) for x in self.orderdeps])
line += '\n'
# This is the only way I could find to make this work on all
# platforms including Windows command shell. Slash is a dir separator
@@ -823,7 +827,7 @@ int dummy;
if subdir is None:
subdir = os.path.join(manroot, 'man' + num)
srcabs = f.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())
- dstabs = os.path.join(subdir, os.path.split(f.fname)[1] + '.gz')
+ dstabs = os.path.join(subdir, os.path.basename(f.fname) + '.gz')
i = [srcabs, dstabs]
d.man.append(i)
@@ -836,24 +840,22 @@ int dummy;
subdir = de.install_dir
for f in de.sources:
assert(isinstance(f, mesonlib.File))
- plain_f = os.path.split(f.fname)[1]
+ plain_f = os.path.basename(f.fname)
dstabs = os.path.join(subdir, plain_f)
i = [f.absolute_path(srcdir, builddir), dstabs, de.install_mode]
d.data.append(i)
def generate_subdir_install(self, d):
for sd in self.build.get_install_subdirs():
- inst_subdir = sd.installable_subdir.rstrip('/')
- idir_parts = inst_subdir.split('/')
- if len(idir_parts) > 1:
- subdir = os.path.join(sd.source_subdir, '/'.join(idir_parts[:-1]))
- inst_dir = idir_parts[-1]
- else:
- subdir = sd.source_subdir
- inst_dir = sd.installable_subdir
- src_dir = os.path.join(self.environment.get_source_dir(), subdir)
- dst_dir = os.path.join(self.environment.get_prefix(), sd.install_dir)
- d.install_subdirs.append([src_dir, inst_dir, dst_dir, sd.install_mode, sd.exclude])
+ src_dir = os.path.join(self.environment.get_source_dir(),
+ sd.source_subdir,
+ sd.installable_subdir).rstrip('/')
+ dst_dir = os.path.join(self.environment.get_prefix(),
+ sd.install_dir)
+ if not sd.strip_directory:
+ dst_dir = os.path.join(dst_dir, os.path.basename(src_dir))
+ d.install_subdirs.append([src_dir, dst_dir, sd.install_mode,
+ sd.exclude])
def generate_tests(self, outfile):
self.serialize_tests()
@@ -1278,7 +1280,7 @@ int dummy;
# Target names really should not have slashes in them, but
# unfortunately we did not check for that and some downstream projects
# now have them. Once slashes are forbidden, remove this bit.
- target_slashname_workaround_dir = os.path.join(os.path.split(target.name)[0],
+ target_slashname_workaround_dir = os.path.join(os.path.dirname(target.name),
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
@@ -1291,7 +1293,11 @@ int dummy;
# installations
for rpath_arg in rpath_args:
args += ['-C', 'link-arg=' + rpath_arg + ':' + os.path.join(rustc.get_sysroot(), 'lib')]
- element = NinjaBuildElement(self.all_outputs, target_name, 'rust_COMPILER', relsrc)
+ crstr = ''
+ if target.is_cross:
+ crstr = '_CROSS'
+ compiler_name = 'rust%s_COMPILER' % crstr
+ element = NinjaBuildElement(self.all_outputs, target_name, compiler_name, relsrc)
if len(orderdeps) > 0:
element.add_orderdep(orderdeps)
element.add_item('ARGS', args)
@@ -1401,7 +1407,7 @@ int dummy;
objects = [] # Relative to swift invocation dir
rel_objects = [] # Relative to build.ninja
for i in abssrc + abs_generated:
- base = os.path.split(i)[1]
+ base = os.path.basename(i)
oname = os.path.splitext(base)[0] + '.o'
objects.append(oname)
rel_objects.append(os.path.join(self.get_target_private_dir(target), oname))
@@ -1579,8 +1585,11 @@ int dummy;
outfile.write(restat)
outfile.write('\n')
- def generate_rust_compile_rules(self, compiler, outfile):
- rule = 'rule %s_COMPILER\n' % compiler.get_language()
+ def generate_rust_compile_rules(self, compiler, outfile, is_cross):
+ crstr = ''
+ if is_cross:
+ crstr = '_CROSS'
+ rule = 'rule %s%s_COMPILER\n' % (compiler.get_language(), crstr)
invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()])
command = ' command = %s $ARGS $in\n' % invoc
description = ' description = Compiling Rust source $in.\n'
@@ -1671,8 +1680,7 @@ rule FORTRAN_DEP_HACK
self.generate_vala_compile_rules(compiler, outfile)
return
if langname == 'rust':
- if not is_cross:
- self.generate_rust_compile_rules(compiler, outfile)
+ self.generate_rust_compile_rules(compiler, outfile, is_cross)
return
if langname == 'swift':
if not is_cross:
@@ -1928,7 +1936,7 @@ rule FORTRAN_DEP_HACK
# Check if a source uses a module it exports itself.
# Potential bug if multiple targets have a file with
# the same name.
- if mod_source_file.fname == os.path.split(src)[1]:
+ if mod_source_file.fname == os.path.basename(src):
continue
mod_name = compiler.module_name_to_filename(
usematch.group(1))
@@ -2271,7 +2279,7 @@ rule FORTRAN_DEP_HACK
commands = []
commands += self.generate_basic_compiler_args(target, compiler)
- just_name = os.path.split(header)[1]
+ just_name = os.path.basename(header)
(objname, pch_args) = compiler.gen_pch_args(just_name, source, dst)
commands += pch_args
commands += self.get_compile_debugfile_args(compiler, target, objname)
@@ -2281,7 +2289,7 @@ rule FORTRAN_DEP_HACK
def generate_gcc_pch_command(self, target, compiler, pch):
commands = self._generate_single_compile(target, compiler)
dst = os.path.join(self.get_target_private_dir(target),
- os.path.split(pch)[-1] + '.' + compiler.get_pch_suffix())
+ os.path.basename(pch) + '.' + compiler.get_pch_suffix())
dep = dst + '.' + compiler.get_depfile_suffix()
return commands, dep, dst, [] # Gcc does not create an object file during pch generation.
@@ -2476,7 +2484,7 @@ rule FORTRAN_DEP_HACK
# unfortunately we did not check for that and some downstream projects
# now have them. Once slashes are forbidden, remove this bit.
target_slashname_workaround_dir = os.path.join(
- os.path.split(target.name)[0],
+ os.path.dirname(target.name),
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 1722db7..057e7c9 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -1034,7 +1034,7 @@ class Vs2010Backend(backends.Backend):
pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile')
# MSBuild searches for the header relative from the implementation, so we have to use
# just the file name instead of the relative path to the file.
- pch_file.text = os.path.split(header)[1]
+ pch_file.text = os.path.basename(header)
self.add_additional_options(lang, inc_cl, file_args)
self.add_preprocessor_defines(lang, inc_cl, file_defines)
self.add_include_dirs(lang, inc_cl, file_inc_dirs)
diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py
index aca3aea..3ae31e4 100644
--- a/mesonbuild/backend/xcodebackend.py
+++ b/mesonbuild/backend/xcodebackend.py
@@ -311,7 +311,7 @@ class XCodeBackend(backends.Backend):
for fname, idval in self.filemap.items():
fullpath = os.path.join(self.environment.get_source_dir(), fname)
xcodetype = self.get_xcodetype(fname)
- name = os.path.split(fname)[-1]
+ name = os.path.basename(fname)
path = fname
self.ofile.write(src_templ % (idval, fullpath, xcodetype, name, path))
target_templ = '%s /* %s */ = { isa = PBXFileReference; explicitFileType = "%s"; path = %s; refType = %d; sourceTree = BUILT_PRODUCTS_DIR; };\n'
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 5eab794..400b9e5 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -22,7 +22,7 @@ from . import mlog
from .mesonlib import File, MesonException, listify, extract_as_list
from .mesonlib import typeslistify, stringlistify, classify_unity_sources
from .mesonlib import get_filenames_templates_dict, substitute_values
-from .mesonlib import for_windows, for_darwin, for_cygwin
+from .mesonlib import for_windows, for_darwin, for_cygwin, for_android
from .compilers import is_object, clike_langs, sort_clike, lang_suffixes
known_basic_kwargs = {'install': True,
@@ -1065,7 +1065,7 @@ class Generator:
depfile = kwargs['depfile']
if not isinstance(depfile, str):
raise InvalidArguments('Depfile must be a string.')
- if os.path.split(depfile)[1] != depfile:
+ if os.path.basename(depfile) != depfile:
raise InvalidArguments('Depfile must be a plain filename without a subdirectory.')
self.depfile = depfile
if 'capture' in kwargs:
@@ -1075,7 +1075,7 @@ class Generator:
self.capture = capture
def get_base_outnames(self, inname):
- plainname = os.path.split(inname)[1]
+ plainname = os.path.basename(inname)
basename = os.path.splitext(plainname)[0]
bases = [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs]
return bases
@@ -1083,12 +1083,12 @@ class Generator:
def get_dep_outname(self, inname):
if self.depfile is None:
raise InvalidArguments('Tried to get dep name for rule that does not have dependency file defined.')
- plainname = os.path.split(inname)[1]
+ plainname = os.path.basename(inname)
basename = os.path.splitext(plainname)[0]
return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname)
def get_arglist(self, inname):
- plainname = os.path.split(inname)[1]
+ plainname = os.path.basename(inname)
basename = os.path.splitext(plainname)[0]
return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist]
@@ -1130,7 +1130,7 @@ class GeneratedList:
in_abs = infile.absolute_path(state.environment.source_dir, state.environment.build_dir)
assert(os.path.isabs(self.preserve_path_from))
rel = os.path.relpath(in_abs, self.preserve_path_from)
- path_segment = os.path.split(rel)[0]
+ path_segment = os.path.dirname(rel)
for of in outfiles:
result.append(os.path.join(path_segment, of))
return result
@@ -1393,6 +1393,11 @@ class SharedLibrary(BuildTarget):
else:
# libfoo.dylib
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
+ elif for_android(is_cross, env):
+ prefix = 'lib'
+ suffix = 'so'
+ # Android doesn't support shared_library versioning
+ self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
else:
prefix = 'lib'
suffix = 'so'
@@ -1414,25 +1419,32 @@ class SharedLibrary(BuildTarget):
def process_kwargs(self, kwargs, environment):
super().process_kwargs(kwargs, environment)
- # Shared library version
- if 'version' in kwargs:
- self.ltversion = kwargs['version']
- if not isinstance(self.ltversion, str):
- raise InvalidArguments('Shared library version needs to be a string, not ' + type(self.ltversion).__name__)
- if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', self.ltversion):
- raise InvalidArguments('Invalid Shared library version "{0}". Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.'.format(self.ltversion))
- # Try to extract/deduce the soversion
- if 'soversion' in kwargs:
- self.soversion = kwargs['soversion']
- if isinstance(self.soversion, int):
- self.soversion = str(self.soversion)
- if not isinstance(self.soversion, str):
- raise InvalidArguments('Shared library soversion is not a string or integer.')
- elif self.ltversion:
- # library version is defined, get the soversion from that
- # We replicate what Autotools does here and take the first
- # number of the version by default.
- self.soversion = self.ltversion.split('.')[0]
+
+ if not for_android(self.is_cross, self.environment):
+ supports_versioning = True
+ else:
+ supports_versioning = False
+
+ if supports_versioning:
+ # Shared library version
+ if 'version' in kwargs:
+ self.ltversion = kwargs['version']
+ if not isinstance(self.ltversion, str):
+ raise InvalidArguments('Shared library version needs to be a string, not ' + type(self.ltversion).__name__)
+ if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', self.ltversion):
+ raise InvalidArguments('Invalid Shared library version "{0}". Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.'.format(self.ltversion))
+ # Try to extract/deduce the soversion
+ if 'soversion' in kwargs:
+ self.soversion = kwargs['soversion']
+ if isinstance(self.soversion, int):
+ self.soversion = str(self.soversion)
+ if not isinstance(self.soversion, str):
+ raise InvalidArguments('Shared library soversion is not a string or integer.')
+ elif self.ltversion:
+ # library version is defined, get the soversion from that
+ # We replicate what Autotools does here and take the first
+ # number of the version by default.
+ self.soversion = self.ltversion.split('.')[0]
# Visual Studio module-definitions file
if 'vs_module_defs' in kwargs:
path = kwargs['vs_module_defs']
@@ -1637,6 +1649,10 @@ class CustomTarget(Target):
for i in self.outputs:
if not(isinstance(i, str)):
raise InvalidArguments('Output argument not a string.')
+ if i == '':
+ raise InvalidArguments('Output must not be empty.')
+ if i.strip() == '':
+ raise InvalidArguments('Output must not consist only of whitespace.')
if '/' in i:
raise InvalidArguments('Output must not contain a path segment.')
if '@INPUT@' in i or '@INPUT0@' in i:
@@ -1659,7 +1675,7 @@ class CustomTarget(Target):
depfile = kwargs['depfile']
if not isinstance(depfile, str):
raise InvalidArguments('Depfile must be a string.')
- if os.path.split(depfile)[1] != depfile:
+ if os.path.basename(depfile) != depfile:
raise InvalidArguments('Depfile must be a plain filename without a subdirectory.')
self.depfile = depfile
self.command = self.flatten_command(kwargs['command'])
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 4c6e3a2..a59b7d3 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -172,10 +172,10 @@ class CCompiler(Compiler):
return ' '.join(self.exelist)
def get_pch_use_args(self, pch_dir, header):
- return ['-include', os.path.split(header)[-1]]
+ return ['-include', os.path.basename(header)]
def get_pch_name(self, header_name):
- return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix()
+ return os.path.basename(header_name) + '.' + self.get_pch_suffix()
def get_linker_search_args(self, dirname):
return ['-L' + dirname]
@@ -184,7 +184,7 @@ class CCompiler(Compiler):
return []
def gen_export_dynamic_link_args(self, env):
- if for_windows(env.is_cross_build(), env):
+ if for_windows(env.is_cross_build(), env) or for_cygwin(env.is_cross_build(), env):
return ['-Wl,--export-all-symbols']
elif for_darwin(env.is_cross_build(), env):
return []
@@ -804,6 +804,13 @@ class CCompiler(Compiler):
return ['-pthread']
def has_multi_arguments(self, args, env):
+ for arg in args:
+ if arg.startswith('-Wl,'):
+ mlog.warning('''{} looks like a linker argument, but has_argument
+and other similar methods only support checking compiler arguments.
+Using them to check linker arguments are never supported, and results
+are likely to be wrong regardless of the compiler you are using.
+'''.format(arg))
return self.compiles('int i;\n', env, extra_args=args)
@@ -875,7 +882,7 @@ class GnuCCompiler(GnuCompiler, CCompiler):
return ['-shared']
def get_pch_use_args(self, pch_dir, header):
- return ['-fpch-preprocess', '-include', os.path.split(header)[-1]]
+ return ['-fpch-preprocess', '-include', os.path.basename(header)]
class IntelCCompiler(IntelCompiler, CCompiler):
@@ -954,13 +961,13 @@ class VisualStudioCCompiler(CCompiler):
return 'pch'
def get_pch_name(self, header):
- chopped = os.path.split(header)[-1].split('.')[:-1]
+ chopped = os.path.basename(header).split('.')[:-1]
chopped.append(self.get_pch_suffix())
pchname = '.'.join(chopped)
return pchname
def get_pch_use_args(self, pch_dir, header):
- base = os.path.split(header)[-1]
+ base = os.path.basename(header)
pchname = self.get_pch_name(header)
return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)]
@@ -1087,7 +1094,7 @@ class VisualStudioCCompiler(CCompiler):
mlog.debug('Running VS compile:')
mlog.debug('Command line: ', ' '.join(commands))
mlog.debug('Code:\n', code)
- p, stdo, stde = Popen_safe(commands, cwd=os.path.split(srcname)[0])
+ p, stdo, stde = Popen_safe(commands, cwd=os.path.dirname(srcname))
if p.returncode != 0:
return False
return not(warning_text in stde or warning_text in stdo)
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 2602d14..034fef4 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -137,8 +137,11 @@ gnulike_buildtype_linker_args = {'plain': [],
msvc_buildtype_linker_args = {'plain': [],
'debug': [],
'debugoptimized': [],
- 'release': [],
- 'minsize': ['/INCREMENTAL:NO'],
+ # The otherwise implicit REF and ICF linker
+ # optimisations are disabled by /DEBUG.
+ # REF implies ICF.
+ 'release': ['/OPT:REF'],
+ 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'],
}
java_buildtype_args = {'plain': [],
@@ -1040,7 +1043,7 @@ class GnuCompiler:
return 'gch'
def split_shlib_to_parts(self, fname):
- return os.path.split(fname)[0], fname
+ return os.path.dirname(fname), fname
def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module)
@@ -1188,10 +1191,10 @@ class IntelCompiler:
self.lang_header, '-include', header, '-x', 'none']
def get_pch_name(self, header_name):
- return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix()
+ return os.path.basename(header_name) + '.' + self.get_pch_suffix()
def split_shlib_to_parts(self, fname):
- return os.path.split(fname)[0], fname
+ return os.path.dirname(fname), fname
def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
if self.icc_type == ICC_STANDARD:
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 5e32ace..c10f38e 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -14,6 +14,7 @@
import os.path
+from .. import mlog
from .. import coredata
from ..mesonlib import version_compare
@@ -129,7 +130,7 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
return []
def get_pch_use_args(self, pch_dir, header):
- return ['-fpch-preprocess', '-include', os.path.split(header)[-1]]
+ return ['-fpch-preprocess', '-include', os.path.basename(header)]
class IntelCPPCompiler(IntelCompiler, CPPCompiler):
@@ -174,6 +175,13 @@ class IntelCPPCompiler(IntelCompiler, CPPCompiler):
return []
def has_multi_arguments(self, args, env):
+ for arg in args:
+ if arg.startswith('-Wl,'):
+ mlog.warning('''{} looks like a linker argument, but has_argument
+and other similar methods only support checking compiler arguments.
+Using them to check linker arguments are never supported, and results
+are likely to be wrong regardless of the compiler you are using.
+'''.format(arg))
return super().has_multi_arguments(args + ['-diag-error', '10006'], env)
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 1b42bfa..f9fcc1c 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -91,7 +91,7 @@ end program prog
return gnulike_buildtype_linker_args[buildtype]
def split_shlib_to_parts(self, fname):
- return os.path.split(fname)[0], fname
+ return os.path.dirname(fname), fname
def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module)
diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py
index b93289f..d1a05ed 100644
--- a/mesonbuild/compilers/rust.py
+++ b/mesonbuild/compilers/rust.py
@@ -19,9 +19,11 @@ from ..mesonlib import EnvironmentException, Popen_safe
from .compilers import Compiler, rust_buildtype_args
class RustCompiler(Compiler):
- def __init__(self, exelist, version):
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None):
self.language = 'rust'
super().__init__(exelist, version)
+ self.is_cross = is_cross
+ self.exe_wrapper = exe_wrapper
self.id = 'rustc'
def needs_static_linker(self):
@@ -41,7 +43,16 @@ class RustCompiler(Compiler):
pc.wait()
if pc.returncode != 0:
raise EnvironmentException('Rust compiler %s can not compile programs.' % self.name_string())
- if subprocess.call(output_name) != 0:
+ if self.is_cross:
+ if self.exe_wrapper is None:
+ # Can't check if the binaries run so we have to assume they do
+ return
+ cmdlist = self.exe_wrapper + [output_name]
+ else:
+ cmdlist = [output_name]
+ pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ pe.wait()
+ if pe.returncode != 0:
raise EnvironmentException('Executables created by Rust compiler %s are not runnable.' % self.name_string())
def get_dependency_gen_args(self, outfile):
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 0fdac8b..f87e62c 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -1,5 +1,4 @@
-
-# Copyright 2012-2017 The Meson development team
+# Copyright 2012-2018 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -25,12 +24,19 @@ import ast
version = '0.45.0.dev1'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'xcode']
+default_yielding = False
+
class UserOption:
- def __init__(self, name, description, choices):
+ def __init__(self, name, description, choices, yielding):
super().__init__()
self.name = name
self.choices = choices
self.description = description
+ if yielding is None:
+ yielding = default_yielding
+ if not isinstance(yielding, bool):
+ raise MesonException('Value of "yielding" must be a boolean.')
+ self.yielding = yielding
# Check that the input is a valid value and return the
# "cleaned" or "native" version. For example the Boolean
@@ -39,8 +45,8 @@ class UserOption:
raise RuntimeError('Derived option class did not override validate_value.')
class UserStringOption(UserOption):
- def __init__(self, name, description, value, choices=None):
- super().__init__(name, description, choices)
+ def __init__(self, name, description, value, choices=None, yielding=None):
+ super().__init__(name, description, choices, yielding)
self.set_value(value)
def validate(self, value):
@@ -56,8 +62,8 @@ class UserStringOption(UserOption):
return value
class UserBooleanOption(UserOption):
- def __init__(self, name, description, value):
- super().__init__(name, description, [True, False])
+ def __init__(self, name, description, value, yielding=None):
+ super().__init__(name, description, [True, False], yielding)
self.set_value(value)
def tobool(self, thing):
@@ -79,11 +85,17 @@ class UserBooleanOption(UserOption):
return self.tobool(value)
class UserIntegerOption(UserOption):
- def __init__(self, name, description, min_value, max_value, value):
- super().__init__(name, description, [True, False])
+ def __init__(self, name, description, min_value, max_value, value, yielding=None):
+ super().__init__(name, description, [True, False], yielding)
self.min_value = min_value
self.max_value = max_value
self.set_value(value)
+ c = []
+ if min_value is not None:
+ c.append('>=' + str(min_value))
+ if max_value is not None:
+ c.append('<=' + str(max_value))
+ self.choices = ', '.join(c)
def set_value(self, newvalue):
if isinstance(newvalue, str):
@@ -106,8 +118,8 @@ class UserIntegerOption(UserOption):
return self.toint(value)
class UserComboOption(UserOption):
- def __init__(self, name, description, choices, value):
- super().__init__(name, description, choices)
+ def __init__(self, name, description, choices, value, yielding=None):
+ super().__init__(name, description, choices, yielding)
if not isinstance(self.choices, list):
raise MesonException('Combo choices must be an array.')
for i in self.choices:
@@ -128,7 +140,7 @@ class UserComboOption(UserOption):
class UserArrayOption(UserOption):
def __init__(self, name, description, value, **kwargs):
- super().__init__(name, description, kwargs.get('choices', []))
+ super().__init__(name, description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None))
self.set_value(value, user_input=False)
def validate(self, value, user_input):
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 04ca706..66bc3b4 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -16,7 +16,7 @@
# Custom logic for several other packages are in separate files.
import os
-import sys
+import re
import stat
import shlex
import shutil
@@ -214,10 +214,12 @@ class ConfigToolDependency(ExternalDependency):
tools = None
tool_name = None
+ __strip_version = re.compile(r'^[0-9.]*')
def __init__(self, name, environment, language, kwargs):
super().__init__('config-tool', environment, language, kwargs)
self.name = name
+ self.native = kwargs.get('native', False)
self.tools = listify(kwargs.get('tools', self.tools))
req_version = kwargs.get('version', None)
@@ -229,6 +231,15 @@ class ConfigToolDependency(ExternalDependency):
return
self.version = version
+ def _sanitize_version(self, version):
+ """Remove any non-numeric, non-point version suffixes."""
+ m = self.__strip_version.match(version)
+ if m:
+ # Ensure that there isn't a trailing '.', such as an input like
+ # `1.2.3.git-1234`
+ return m.group(0).rstrip('.')
+ return version
+
@classmethod
def factory(cls, name, environment, language, kwargs, tools, tool_name):
"""Constructor for use in dependencies that can be found multiple ways.
@@ -260,8 +271,20 @@ class ConfigToolDependency(ExternalDependency):
if not isinstance(versions, list) and versions is not None:
versions = listify(versions)
+ if self.env.is_cross_build() and not self.native:
+ cross_file = self.env.cross_info.config['binaries']
+ try:
+ tools = [cross_file[self.tool_name]]
+ except KeyError:
+ mlog.warning('No entry for {0} specified in your cross file. '
+ 'Falling back to searching PATH. This may find a '
+ 'native version of {0}!'.format(self.tool_name))
+ tools = self.tools
+ else:
+ tools = self.tools
+
best_match = (None, None)
- for tool in self.tools:
+ for tool in tools:
try:
p, out = Popen_safe([tool, '--version'])[:2]
except (FileNotFoundError, PermissionError):
@@ -269,10 +292,10 @@ class ConfigToolDependency(ExternalDependency):
if p.returncode != 0:
continue
- out = out.strip()
+ out = self._sanitize_version(out.strip())
# Some tools, like pcap-config don't supply a version, but also
- # dont fail with --version, in that case just assume that there is
- # only one verison and return it.
+ # don't fail with --version, in that case just assume that there is
+ # only one version and return it.
if not out:
return (tool, 'none')
if versions:
@@ -543,6 +566,17 @@ class PkgConfigDependency(ExternalDependency):
(self.type_string, self.name))
else:
variable = out.strip()
+
+ # pkg-config doesn't distinguish between empty and non-existent variables
+ # use the variable list to check for variable existence
+ if not variable:
+ ret, out = self._call_pkgbin(['--print-variables', self.name])
+ if not re.search(r'^' + variable_name + r'$', out, re.MULTILINE):
+ if 'default' in kwargs:
+ variable = kwargs['default']
+ else:
+ mlog.warning("pkgconfig variable '%s' not defined for dependency %s." % (variable_name, self.name))
+
mlog.debug('Got pkgconfig variable %s : %s' % (variable_name, variable))
return variable
diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py
index 25316df..c254947 100644
--- a/mesonbuild/dependencies/dev.py
+++ b/mesonbuild/dependencies/dev.py
@@ -146,16 +146,6 @@ class LLVMDependency(ConfigToolDependency):
return
self.static = kwargs.get('static', False)
- # Currently meson doesn't really attempt to handle pre-release versions,
- # so strip the 'svn' off the end, since it will probably cuase problems
- # for users who want the patch version.
- #
- # If LLVM is built from svn then "svn" will be appended to the version
- # string, if it's built from a git mirror then "git-<very short sha>"
- # will be appended instead.
- self.version = self.version.rstrip('svn')
- self.version = self.version.split('git')[0]
-
self.provided_modules = self.get_config_value(['--components'], 'modules')
modules = stringlistify(extract_as_list(kwargs, 'modules'))
self.check_components(modules)
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 0570e88..af80160 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -63,9 +63,12 @@ from .base import (
# **On Unix**, official packaged versions of boost libraries follow the following schemes:
#
-# Linux / Debian: libboost_<module>.so.1.66.0 -> libboost_<module>.so
-# Linux / Red Hat: libboost_<module>.so.1.66.0 -> libboost_<module>.so
-# Linux / OpenSuse: libboost_<module>.so.1.66.0 -> libboost_<module>.so
+# Linux / Debian: libboost_<module>.so -> libboost_<module>.so.1.66.0
+# Linux / Red Hat: libboost_<module>.so -> libboost_<module>.so.1.66.0
+# Linux / OpenSuse: libboost_<module>.so -> libboost_<module>.so.1.66.0
+# Win / Cygwin: libboost_<module>.dll.a (location = /usr/lib)
+# libboost_<module>.a
+# cygboost_<module>_1_64.dll (location = /usr/bin)
# Mac / homebrew: libboost_<module>.dylib + libboost_<module>-mt.dylib (location = /usr/local/lib)
# Mac / macports: libboost_<module>.dylib + libboost_<module>-mt.dylib (location = /opt/local/lib)
#
@@ -147,6 +150,28 @@ class BoostDependency(ExternalDependency):
self.log_fail()
return
+ if self.check_invalid_modules():
+ return
+
+ mlog.debug('Boost library root dir is', mlog.bold(self.boost_root))
+ mlog.debug('Boost include directory is', mlog.bold(self.incdir))
+
+ self.lib_modules = {}
+ self.detect_version()
+ if self.is_found:
+ self.detect_lib_modules()
+ mlog.debug('Boost library directory is', mlog.bold(self.libdir))
+ for m in self.requested_modules:
+ if 'boost_' + m not in self.lib_modules:
+ mlog.debug('Requested Boost library {!r} not found'.format(m))
+ self.log_fail()
+ self.is_found = False
+ return
+ self.log_success()
+ else:
+ self.log_fail()
+
+ def check_invalid_modules(self):
invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS]
# previous versions of meson allowed include dirs as modules
@@ -163,21 +188,9 @@ class BoostDependency(ExternalDependency):
if invalid_modules:
mlog.log(mlog.red('ERROR:'), 'Invalid Boost modules: ' + ', '.join(invalid_modules))
self.log_fail()
- return
-
- mlog.debug('Boost library root dir is', mlog.bold(self.boost_root))
- mlog.debug('Boost include directory is', mlog.bold(self.incdir))
-
- self.lib_modules = {}
- self.detect_version()
- if self.is_found:
- self.detect_lib_modules()
- mlog.debug('Boost library directory is', mlog.bold(self.libdir))
- self.validate_requested()
- self.log_success()
+ return True
else:
- self.log_fail()
-
+ return False
def log_fail(self):
module_str = ', '.join(self.requested_modules)
@@ -262,12 +275,6 @@ class BoostDependency(ExternalDependency):
raise DependencyException('Boost module argument is not a string.')
return candidates
- def validate_requested(self):
- for m in self.requested_modules:
- if 'boost_' + m not in self.lib_modules:
- msg = 'Requested Boost library {!r} not found'
- raise DependencyException(msg.format(m))
-
def detect_version(self):
try:
version = self.compiler.get_define('BOOST_LIB_VERSION', '#include <boost/version.hpp>', self.env, self.get_compile_args(), [])
@@ -360,15 +367,23 @@ class BoostDependency(ExternalDependency):
fname = os.path.basename(entry)
self.lib_modules[self.modname_from_filename(fname)] = [fname]
+ # - Linux leaves off -mt but libraries are multithreading-aware.
+ # - Cygwin leaves off -mt but libraries are multithreading-aware.
+ # - Mac requires -mt for multithreading, so should not fall back
+ # to non-mt libraries.
+ def abi_tag(self):
+ if mesonlib.for_windows(self.want_cross, self.env):
+ return None
+ if self.is_multithreading and mesonlib.for_darwin(self.want_cross, self.env):
+ return '-mt'
+ else:
+ return ''
+
def detect_lib_modules_nix(self):
all_found = True
for module in self.requested_modules:
- args = None
- libname = 'boost_' + module
- if self.is_multithreading and mesonlib.for_darwin(self.want_cross, self.env):
- # - Linux leaves off -mt but libraries are multithreading-aware.
- # - Mac requires -mt for multithreading, so should not fall back to non-mt libraries.
- libname = libname + '-mt'
+ libname = 'boost_' + module + self.abi_tag()
+
args = self.compiler.find_library(libname, self.env, self.extra_lib_dirs())
if args is None:
mlog.debug('Couldn\'t find library "{}" for boost module "{}"'.format(module, libname))
@@ -417,29 +432,17 @@ class BoostDependency(ExternalDependency):
if modname not in self.lib_modules:
self.lib_modules[modname] = [entry]
- def get_win_link_args(self):
- args = []
- # TODO: should this check self.libdir?
- if self.libdir:
- args.append('-L' + self.libdir)
- for lib in self.requested_modules:
- args += self.lib_modules['boost_' + lib]
- return args
-
def extra_lib_dirs(self):
- dirs = []
- if self.boost_root:
- dirs = [os.path.join(self.boost_root, 'lib')]
- elif self.libdir:
- dirs = [self.libdir]
- return dirs
+ if self.libdir:
+ return [self.libdir]
+ elif self.boost_root:
+ return [os.path.join(self.boost_root, 'lib')]
+ return []
def get_link_args(self):
- if mesonlib.is_windows():
- return self.get_win_link_args()
args = []
for dir in self.extra_lib_dirs():
- args += ['-L' + dir]
+ args += self.compiler.get_linker_search_args(self.libdir)
for lib in self.requested_modules:
args += self.lib_modules['boost_' + lib]
return args
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index e5aa43e..52c670a 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -278,6 +278,7 @@ class Environment:
self.default_objc = ['cc']
self.default_objcpp = ['c++']
self.default_fortran = ['gfortran', 'g95', 'f95', 'f90', 'f77', 'ifort']
+ self.default_rust = ['rustc']
self.default_static_linker = ['ar']
self.vs_static_linker = ['lib']
self.gcc_static_linker = ['gcc-ar']
@@ -594,7 +595,7 @@ class Environment:
return self.scratch_dir
def get_depfixer(self):
- path = os.path.split(__file__)[0]
+ path = os.path.dirname(__file__)
return os.path.join(path, 'depfixer.py')
def detect_objc_compiler(self, want_cross):
@@ -688,16 +689,24 @@ class Environment:
return ValaCompiler(exelist, version)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
- def detect_rust_compiler(self):
- exelist = ['rustc']
- try:
- p, out = Popen_safe(exelist + ['--version'])[0:2]
- except OSError:
- raise EnvironmentException('Could not execute Rust compiler "%s"' % ' '.join(exelist))
- version = search_version(out)
- if 'rustc' in out:
- return RustCompiler(exelist, version)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
+ def detect_rust_compiler(self, want_cross):
+ popen_exceptions = {}
+ compilers, ccache, is_cross, exe_wrap = self._get_compilers('rust', 'RUSTC', want_cross)
+ for compiler in compilers:
+ if isinstance(compiler, str):
+ compiler = [compiler]
+ try:
+ p, out = Popen_safe(compiler + ['--version'])[0:2]
+ except OSError as e:
+ popen_exceptions[compiler] = e
+ continue
+
+ version = search_version(out)
+
+ if 'rustc' in out:
+ return RustCompiler(compiler, version, is_cross, exe_wrap)
+
+ self._handle_exceptions(popen_exceptions, compilers)
def detect_d_compiler(self, want_cross):
is_cross = False
@@ -968,7 +977,7 @@ class CrossBuildInfo:
def get_properties(self):
return self.config['properties']
- # Wehn compiling a cross compiler we use the native compiler for everything.
+ # When compiling a cross compiler we use the native compiler for everything.
# But not when cross compiling a cross compiler.
def need_cross_compiler(self):
return 'host_machine' in self.config
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index c759892..31d7616 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2017 The Meson development team
+# Copyright 2012-2018 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -36,8 +36,6 @@ from collections import namedtuple
import importlib
-run_depr_printed = False
-
def stringifyUserArguments(args):
if isinstance(args, list):
return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
@@ -509,13 +507,14 @@ class DataHolder(InterpreterObject, ObjectHolder):
return self.held_object.install_dir
class InstallDir(InterpreterObject):
- def __init__(self, src_subdir, inst_subdir, install_dir, install_mode, exclude):
+ def __init__(self, src_subdir, inst_subdir, install_dir, install_mode, exclude, strip_directory):
InterpreterObject.__init__(self)
self.source_subdir = src_subdir
self.installable_subdir = inst_subdir
self.install_dir = install_dir
self.install_mode = install_mode
self.exclude = exclude
+ self.strip_directory = strip_directory
class Man(InterpreterObject):
@@ -1170,6 +1169,7 @@ class MesonMain(InterpreterObject):
'add_postconf_script': self.add_postconf_script_method,
'install_dependency_manifest': self.install_dependency_manifest_method,
'project_version': self.project_version_method,
+ 'project_license': self.project_license_method,
'version': self.version_method,
'project_name': self.project_name_method,
'get_cross_property': self.get_cross_property_method,
@@ -1283,6 +1283,9 @@ class MesonMain(InterpreterObject):
def project_version_method(self, args, kwargs):
return self.build.dep_manifest[self.interpreter.active_projectname]['version']
+ def project_license_method(self, args, kwargs):
+ return self.build.dep_manifest[self.interpreter.active_projectname]['license']
+
def version_method(self, args, kwargs):
return coredata.version
@@ -1379,7 +1382,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
'build_target': build_target_kwargs,
'configure_file': {'input', 'output', 'configuration', 'command', 'install_dir', 'capture', 'install'},
'custom_target': {'input', 'output', 'command', 'install', 'install_dir', 'build_always', 'capture', 'depends', 'depend_files', 'depfile', 'build_by_default'},
- 'dependency': {'default_options', 'fallback', 'language', 'method', 'modules', 'optional_modules', 'native', 'required', 'static', 'version'},
+ 'dependency': {'default_options', 'fallback', 'language', 'main', 'method', 'modules', 'optional_modules', 'native', 'required', 'static', 'version'},
'declare_dependency': {'include_directories', 'link_with', 'sources', 'dependencies', 'compile_args', 'link_args', 'version'},
'executable': exe_kwargs,
'find_program': {'required', 'native'},
@@ -1388,7 +1391,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
'install_data': {'install_dir', 'install_mode', 'sources'},
'install_headers': {'install_dir', 'subdir'},
'install_man': {'install_dir'},
- 'install_subdir': {'exclude_files', 'exclude_directories', 'install_dir', 'install_mode'},
+ 'install_subdir': {'exclude_files', 'exclude_directories', 'install_dir', 'install_mode', 'strip_directory'},
'jar': jar_kwargs,
'project': {'version', 'meson_version', 'default_options', 'license', 'subproject_dir'},
'run_target': {'command', 'depends'},
@@ -1585,7 +1588,7 @@ class Interpreter(InterpreterBase):
modname = args[0]
if modname.startswith('unstable-'):
plainname = modname.split('-', 1)[1]
- mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases' % modname, location=node)
+ mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node)
modname = 'unstable_' + plainname
if modname not in self.environment.coredata.modules:
try:
@@ -1765,7 +1768,7 @@ external dependencies (including libraries) must go to "dependencies".''')
def func_get_option(self, nodes, args, kwargs):
if len(args) != 1:
raise InterpreterException('Argument required for get_option.')
- optname = args[0]
+ undecorated_optname = optname = args[0]
if ':' in optname:
raise InterpreterException('''Having a colon in option name is forbidden, projects are not allowed
to directly access options of other subprojects.''')
@@ -1784,7 +1787,11 @@ to directly access options of other subprojects.''')
if not coredata.is_builtin_option(optname) and self.is_subproject():
optname = self.subproject + ':' + optname
try:
- return self.environment.coredata.user_options[optname].value
+ opt = self.environment.coredata.user_options[optname]
+ if opt.yielding and ':' in optname:
+ # If option not present in superproject, keep the original.
+ opt = self.environment.coredata.user_options.get(undecorated_optname, opt)
+ return opt.value
except KeyError:
pass
if optname.endswith('_link_args'):
@@ -1992,9 +1999,9 @@ to directly access options of other subprojects.''')
if need_cross_compiler:
cross_comp = self.environment.detect_d_compiler(True)
elif lang == 'rust':
- comp = self.environment.detect_rust_compiler()
+ comp = self.environment.detect_rust_compiler(False)
if need_cross_compiler:
- cross_comp = comp # FIXME, not correct.
+ cross_comp = self.environment.detect_rust_compiler(True)
elif lang == 'fortran':
comp = self.environment.detect_fortran_compiler(False)
if need_cross_compiler:
@@ -2138,7 +2145,7 @@ to directly access options of other subprojects.''')
return progobj
def func_find_library(self, node, args, kwargs):
- mlog.log(mlog.red('DEPRECATION:'), 'find_library() is removed, use the corresponding method in compiler object instead.')
+ raise InvalidCode('find_library() is removed, use the corresponding method in a compiler object instead.')
def _find_cached_dep(self, name, kwargs):
# Check if we want this as a cross-dep or a native-dep
@@ -2447,15 +2454,8 @@ root and issuing %s.
@permittedKwargs(permitted_kwargs['run_target'])
def func_run_target(self, node, args, kwargs):
- global run_depr_printed
if len(args) > 1:
- if not run_depr_printed:
- mlog.log(mlog.red('DEPRECATION'), 'positional version of run_target is deprecated, use the keyword version instead.')
- run_depr_printed = True
- if 'command' in kwargs:
- raise InterpreterException('Can not have command both in positional and keyword arguments.')
- all_args = args[1:]
- deps = []
+ raise InvalidCode('Run_target takes only one positional argument: the target name.')
elif len(args) == 1:
if 'command' not in kwargs:
raise InterpreterException('Missing "command" keyword argument')
@@ -2679,6 +2679,12 @@ root and issuing %s.
install_dir = kwargs['install_dir']
if not isinstance(install_dir, str):
raise InvalidArguments('Keyword argument install_dir not a string.')
+ if 'strip_directory' in kwargs:
+ if not isinstance(kwargs['strip_directory'], bool):
+ raise InterpreterException('"strip_directory" keyword must be a boolean.')
+ strip_directory = kwargs['strip_directory']
+ else:
+ strip_directory = False
if 'exclude_files' in kwargs:
exclude = extract_as_list(kwargs, 'exclude_files')
for f in exclude:
@@ -2686,7 +2692,7 @@ root and issuing %s.
raise InvalidArguments('Exclude argument not a string.')
elif os.path.isabs(f):
raise InvalidArguments('Exclude argument cannot be absolute.')
- exclude_files = {os.path.join(subdir, f) for f in exclude}
+ exclude_files = set(exclude)
else:
exclude_files = set()
if 'exclude_directories' in kwargs:
@@ -2696,12 +2702,12 @@ root and issuing %s.
raise InvalidArguments('Exclude argument not a string.')
elif os.path.isabs(d):
raise InvalidArguments('Exclude argument cannot be absolute.')
- exclude_directories = {os.path.join(subdir, f) for f in exclude}
+ exclude_directories = set(exclude)
else:
exclude_directories = set()
exclude = (exclude_files, exclude_directories)
install_mode = self._get_kwarg_install_mode(kwargs)
- idir = InstallDir(self.subdir, subdir, install_dir, install_mode, exclude)
+ idir = InstallDir(self.subdir, subdir, install_dir, install_mode, exclude, strip_directory)
self.build.install_dirs.append(idir)
return idir
@@ -2748,7 +2754,7 @@ root and issuing %s.
values = mesonlib.get_filenames_templates_dict([ifile_abs], None)
outputs = mesonlib.substitute_values([output], values)
output = outputs[0]
- if os.path.split(output)[0] != '':
+ if os.path.dirname(output) != '':
raise InterpreterException('Output file name must not contain a subdirectory.')
(ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output))
ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname)
@@ -2765,7 +2771,7 @@ root and issuing %s.
var_list = ", ".join(map(repr, sorted(missing_variables)))
mlog.warning(
"The variable(s) %s in the input file %s are not "
- "present in the given configuration data" % (
+ "present in the given configuration data." % (
var_list, inputfile), location=node)
else:
mesonlib.dump_conf_header(ofile_abs, conf.held_object)
@@ -2986,7 +2992,7 @@ different subdirectory.
norm = os.path.relpath(norm, self.environment.source_dir)
assert(not os.path.isabs(norm))
(num_sps, sproj_name) = self.evaluate_subproject_info(norm, self.subproject_dir)
- plain_filename = os.path.split(norm)[-1]
+ plain_filename = os.path.basename(norm)
if num_sps == 0:
if self.subproject == '':
return
@@ -2999,6 +3005,8 @@ different subdirectory.
def source_strings_to_files(self, sources):
results = []
mesonlib.check_direntry_issues(sources)
+ if not isinstance(sources, list):
+ sources = [sources]
for s in sources:
if isinstance(s, (mesonlib.File, GeneratedListHolder,
CustomTargetHolder, CustomTargetIndexHolder)):
@@ -3015,6 +3023,8 @@ different subdirectory.
def add_target(self, name, tobj):
if name == '':
raise InterpreterException('Target name must not be empty.')
+ if name.strip() == '':
+ raise InterpreterException('Target name must not consist only of whitespace.')
if name.startswith('meson-'):
raise InvalidArguments("Target names starting with 'meson-' are reserved "
"for Meson's internal use. Please rename.")
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index 9dc6b0f..6618dc8 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -74,7 +74,7 @@ class permittedKwargs:
loc = None
for k in kwargs:
if k not in self.permitted:
- mlog.warning('''Passed invalid keyword argument "{}"'''.format(k), location=loc)
+ mlog.warning('''Passed invalid keyword argument "{}".'''.format(k), location=loc)
mlog.warning('This will become a hard error in the future.')
return f(s, node_or_state, args, kwargs)
return wrapped
@@ -265,6 +265,12 @@ class InterpreterBase:
if not isinstance(node.elseblock, mparser.EmptyNode):
self.evaluate_codeblock(node.elseblock)
+ def validate_comparison_types(self, val1, val2):
+ if type(val1) != type(val2):
+ mlog.warning('''Trying to compare values of different types ({}, {}).
+The result of this is undefined and will become a hard error
+in a future Meson release.'''.format(type(val1).__name__, type(val2).__name__))
+
def evaluate_comparison(self, node):
val1 = self.evaluate_statement(node.left)
if is_disabler(val1):
@@ -272,15 +278,11 @@ class InterpreterBase:
val2 = self.evaluate_statement(node.right)
if is_disabler(val2):
return val2
+ self.validate_comparison_types(val1, val2)
if node.ctype == '==':
return val1 == val2
elif node.ctype == '!=':
return val1 != val2
- elif not isinstance(val1, type(val2)):
- raise InterpreterException(
- 'Values of different types ({}, {}) cannot be compared using {}.'.format(type(val1).__name__,
- type(val2).__name__,
- node.ctype))
elif not self.is_elementary_type(val1):
raise InterpreterException('{} can only be compared for equality.'.format(node.left.value))
elif not self.is_elementary_type(val2):
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 4871bf7..65b689f 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -282,6 +282,9 @@ def is_osx():
def is_linux():
return platform.system().lower() == 'linux'
+def is_android():
+ return platform.system().lower() == 'android'
+
def is_haiku():
return platform.system().lower() == 'haiku'
@@ -350,6 +353,18 @@ def for_darwin(is_cross, env):
return env.cross_info.config['host_machine']['system'] == 'darwin'
return False
+def for_android(is_cross, env):
+ """
+ Host machine is Android?
+
+ Note: 'host' is the machine on which compiled binaries will run
+ """
+ if not is_cross:
+ return is_android()
+ elif env.cross_info.has_host():
+ return env.cross_info.config['host_machine']['system'] == 'android'
+ return False
+
def for_haiku(is_cross, env):
"""
Host machine is Haiku?
@@ -576,7 +591,8 @@ def do_conf_file(src, dst, confdata):
return missing_variables
def dump_conf_header(ofilename, cdata):
- with open(ofilename, 'w', encoding='utf-8') as ofile:
+ ofilename_tmp = ofilename + '~'
+ with open(ofilename_tmp, 'w', encoding='utf-8') as ofile:
ofile.write('''/*
* Autogenerated by the Meson build system.
* Do not edit, your changes will be lost.
@@ -598,6 +614,7 @@ def dump_conf_header(ofilename, cdata):
ofile.write('#define %s %s\n\n' % (k, v))
else:
raise MesonException('Unknown data type in configuration file entry: ' + k)
+ replace_if_different(ofilename, ofilename_tmp)
def replace_if_different(dst, dst_tmp):
# If contents are identical, don't touch the file to prevent
@@ -855,7 +872,7 @@ def get_filenames_templates_dict(inputs, outputs):
values['@INPUT{}@'.format(ii)] = vv
if len(inputs) == 1:
# Just one value, substitute @PLAINNAME@ and @BASENAME@
- values['@PLAINNAME@'] = plain = os.path.split(inputs[0])[1]
+ values['@PLAINNAME@'] = plain = os.path.basename(inputs[0])
values['@BASENAME@'] = os.path.splitext(plain)[0]
if outputs:
# Gather values derived from the outputs, similar to above.
@@ -863,7 +880,7 @@ def get_filenames_templates_dict(inputs, outputs):
for (ii, vv) in enumerate(outputs):
values['@OUTPUT{}@'.format(ii)] = vv
# Outdir should be the same for all outputs
- values['@OUTDIR@'] = os.path.split(outputs[0])[0]
+ values['@OUTDIR@'] = os.path.dirname(outputs[0])
# Many external programs fail on empty arguments.
if values['@OUTDIR@'] == '':
values['@OUTDIR@'] = '.'
@@ -893,7 +910,7 @@ def detect_subprojects(spdir_name, current_dir='', result=None):
if not os.path.exists(spdir):
return result
for trial in glob(os.path.join(spdir, '*')):
- basename = os.path.split(trial)[1]
+ basename = os.path.basename(trial)
if trial == 'packagecache':
continue
append_this = True
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index e48122f..619aa39 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -296,8 +296,6 @@ def run(original_args, mainfile=None):
# FALLTHROUGH like it's 1972.
elif cmd_name == 'introspect':
return mintro.run(remaining_args)
- elif cmd_name == 'test':
- return mtest.run(remaining_args)
elif cmd_name == 'rewrite':
return rewriter.run(remaining_args)
elif cmd_name == 'configure':
@@ -368,10 +366,11 @@ def run(original_args, mainfile=None):
app.generate()
except Exception as e:
if isinstance(e, MesonException):
+ mlog.log()
if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'):
- mlog.log(mlog.red('\nMeson encountered an error in file %s, line %d, column %d:' % (e.file, e.lineno, e.colno)))
+ mlog.log('%s:%d:%d:' % (e.file, e.lineno, e.colno), mlog.red('ERROR: '), end='')
else:
- mlog.log(mlog.red('\nMeson encountered an error:'))
+ mlog.log(mlog.red('ERROR: '), end='')
# Error message
mlog.log(e)
# Path to log file
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index b23869f..8cf66af 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -49,14 +49,14 @@ parser.add_argument('builddir', nargs='?', help='The build directory')
def determine_installed_path(target, installdata):
install_target = None
for i in installdata.targets:
- if os.path.split(i[0])[1] == target.get_filename(): # FIXME, might clash due to subprojects.
+ if os.path.basename(i[0]) == target.get_filename(): # FIXME, might clash due to subprojects.
install_target = i
break
if install_target is None:
raise RuntimeError('Something weird happened. File a bug.')
fname = i[0]
outdir = i[1]
- outname = os.path.join(installdata.prefix, outdir, os.path.split(fname)[-1])
+ outname = os.path.join(installdata.prefix, outdir, os.path.basename(fname))
# Normalize the path by using os.path.sep consistently, etc.
# Does not change the effective path.
return str(pathlib.PurePath(outname))
@@ -139,6 +139,8 @@ def add_keys(optlist, options):
elif isinstance(opt, coredata.UserComboOption):
optdict['choices'] = opt.choices
typestr = 'combo'
+ elif isinstance(opt, coredata.UserIntegerOption):
+ typestr = 'integer'
elif isinstance(opt, coredata.UserArrayOption):
typestr = 'array'
else:
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
index aa2ac20..273552d 100644
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -105,12 +105,15 @@ def log(*args, **kwargs):
def warning(*args, **kwargs):
from . import environment
+ args = (yellow('WARNING:'),) + args
+
if kwargs.get('location'):
location = kwargs['location']
del kwargs['location']
- args += ('in file {}, line {}.'.format(os.path.join(location.subdir, environment.build_filename), location.lineno),)
+ location = '{}:{}:'.format(os.path.join(location.subdir, environment.build_filename), location.lineno)
+ args = (location,) + args
- log(yellow('WARNING:'), *args, **kwargs)
+ log(*args, **kwargs)
# Format a list for logging purposes as a string. It separates
# all but the last item with commas, and the last with 'and'.
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index db85420..218e3b3 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -362,7 +362,7 @@ class GnomeModule(ExtensionModule):
ldflags.update([lib])
if isinstance(dep, PkgConfigDependency):
- girdir = dep.get_pkgconfig_variable("girdir", {})
+ girdir = dep.get_pkgconfig_variable("girdir", {'default': ''})
if girdir:
gi_includes.update([girdir])
elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
@@ -553,7 +553,7 @@ class GnomeModule(ExtensionModule):
if subdir not in typelib_includes:
typelib_includes.append(subdir)
elif isinstance(dep, PkgConfigDependency):
- girdir = dep.get_pkgconfig_variable("girdir", {})
+ girdir = dep.get_pkgconfig_variable("girdir", {'default': ''})
if girdir and girdir not in typelib_includes:
typelib_includes.append(girdir)
# ldflags will be misinterpreted by gir scanner (showing
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 54c2126..5573a2e 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -66,13 +66,15 @@ class DependenciesHelper:
elif hasattr(obj, 'generated_pc'):
processed_reqs.append(obj.generated_pc)
elif isinstance(obj, dependencies.PkgConfigDependency):
- processed_reqs.append(obj.name)
+ if obj.found():
+ processed_reqs.append(obj.name)
elif isinstance(obj, dependencies.ThreadDependency):
processed_libs += obj.get_compiler().thread_link_flags(obj.env)
processed_cflags += obj.get_compiler().thread_flags(obj.env)
elif isinstance(obj, dependencies.Dependency):
- processed_libs += obj.get_link_args()
- processed_cflags += obj.get_compile_args()
+ if obj.found():
+ processed_libs += obj.get_link_args()
+ processed_cflags += obj.get_compile_args()
elif isinstance(obj, (build.SharedLibrary, build.StaticLibrary)):
processed_libs.append(obj)
if public:
diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py
index 54e2c73..f5ce1ed 100644
--- a/mesonbuild/modules/qt.py
+++ b/mesonbuild/modules/qt.py
@@ -73,7 +73,7 @@ class QtBaseModule:
def parse_qrc(self, state, fname):
abspath = os.path.join(state.environment.source_dir, state.subdir, fname)
- relative_part = os.path.split(fname)[0]
+ relative_part = os.path.dirname(fname)
try:
tree = ET.parse(abspath)
root = tree.getroot()
@@ -83,7 +83,7 @@ class QtBaseModule:
mlog.warning("malformed rcc file: ", os.path.join(state.subdir, fname))
break
else:
- result.append(os.path.join(state.subdir, relative_part, child.text))
+ result.append(os.path.join(relative_part, child.text))
return result
except Exception:
return []
@@ -116,7 +116,7 @@ class QtBaseModule:
sources.append(res_target)
else:
for rcc_file in rcc_files:
- basename = os.path.split(rcc_file)[1]
+ basename = os.path.basename(rcc_file)
name = 'qt' + str(self.qt_version) + '-' + basename.replace('.', '_')
rcc_kwargs = {'input': rcc_file,
'output': name + '.cpp',
diff --git a/mesonbuild/modules/unstable_icestorm.py b/mesonbuild/modules/unstable_icestorm.py
new file mode 100644
index 0000000..0b7b339
--- /dev/null
+++ b/mesonbuild/modules/unstable_icestorm.py
@@ -0,0 +1,85 @@
+# Copyright 2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .. import mesonlib, compilers, mlog
+
+from . import ExtensionModule
+
+class IceStormModule(ExtensionModule):
+
+ def __init__(self):
+ super().__init__()
+ self.snippets.add('project')
+ self.yosys_bin = None
+
+ def detect_binaries(self, interpreter):
+ self.yosys_bin = interpreter.func_find_program(None, ['yosys'], {})
+ self.arachne_bin = interpreter.func_find_program(None, ['arachne-pnr'], {})
+ self.icepack_bin = interpreter.func_find_program(None, ['icepack'], {})
+ self.iceprog_bin = interpreter.func_find_program(None, ['iceprog'], {})
+ self.icetime_bin = interpreter.func_find_program(None, ['icetime'], {})
+
+ def project(self, interpreter, state, args, kwargs):
+ if not self.yosys_bin:
+ self.detect_binaries(interpreter)
+ result = []
+ if not len(args):
+ raise mesonlib.MesonException('Project requires at least one argument, which is the project name.')
+ proj_name = args[0]
+ arg_sources = args[1:]
+ if not isinstance(proj_name, str):
+ raise mesonlib.MesonException('Argument must be a string.')
+ kwarg_sources = kwargs.get('sources', [])
+ if not isinstance(kwarg_sources, list):
+ kwarg_sources = [kwarg_sources]
+ all_sources = interpreter.source_strings_to_files(interpreter.flatten(arg_sources + kwarg_sources))
+ if 'constraint_file' not in kwargs:
+ raise mesonlib.MesonException('Constraint file not specified.')
+
+ constraint_file = interpreter.source_strings_to_files(kwargs['constraint_file'])
+ if len(constraint_file) != 1:
+ raise mesonlib.MesonException('Constraint file must contain one and only one entry.')
+ blif_name = proj_name + '_blif'
+ blif_fname = proj_name + '.blif'
+ asc_name = proj_name + '_asc'
+ asc_fname = proj_name + '.asc'
+ bin_name = proj_name + '_bin'
+ bin_fname = proj_name + '.bin'
+ time_name = proj_name + '-time'
+ upload_name = proj_name + '-upload'
+
+ blif_target = interpreter.func_custom_target(None, [blif_name], {
+ 'input': all_sources,
+ 'output': blif_fname,
+ 'command': [self.yosys_bin, '-q', '-p', 'synth_ice40 -blif @OUTPUT@', '@INPUT@']})
+
+ asc_target = interpreter.func_custom_target(None, [asc_name], {
+ 'input': blif_target,
+ 'output': asc_fname,
+ 'command': [self.arachne_bin, '-q', '-d', '1k', '-p', constraint_file, '@INPUT@', '-o', '@OUTPUT@']})
+
+ bin_target = interpreter.func_custom_target(None, [bin_name], {
+ 'input': asc_target,
+ 'output': bin_fname,
+ 'command': [self.icepack_bin, '@INPUT@', '@OUTPUT@'],
+ 'build_by_default' : True})
+
+ up_target = interpreter.func_run_target(None, [upload_name], {
+ 'command': [self.iceprog_bin, bin_target]})
+
+ time_target = interpreter.func_run_target(None, [time_name], {
+ 'command' : [self.icetime_bin, bin_target]})
+
+def initialize():
+ return IceStormModule()
diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py
index eb03393..94d56e5 100644
--- a/mesonbuild/mparser.py
+++ b/mesonbuild/mparser.py
@@ -71,6 +71,7 @@ class Lexer:
# Need to be sorted longest to shortest.
('ignore', re.compile(r'[ \t]')),
('id', re.compile('[_a-zA-Z][_0-9a-zA-Z]*')),
+ ('hexnumber', re.compile('0[xX][0-9a-fA-F]+')),
('number', re.compile(r'\d+')),
('eol_cont', re.compile(r'\\\n')),
('eol', re.compile(r'\n')),
@@ -152,6 +153,9 @@ class Lexer:
line_start = mo.end() - len(lines[-1])
elif tid == 'number':
value = int(match_text)
+ elif tid == 'hexnumber':
+ tid = 'number'
+ value = int(match_text, base=16)
elif tid == 'eol' or tid == 'eol_cont':
lineno += 1
line_start = loc
@@ -368,7 +372,7 @@ class ArgumentNode:
def set_kwarg(self, name, value):
if name in self.kwargs:
- mlog.warning('Keyword argument "{}" defined multiple times'.format(name), location=self)
+ mlog.warning('Keyword argument "{}" defined multiple times.'.format(name), location=self)
mlog.warning('This will be an error in future Meson releases.')
self.kwargs[name] = value
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index b39f5af..95e532c 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -241,8 +241,8 @@ class TestHarness:
stdout = subprocess.PIPE
stderr = subprocess.PIPE if self.options and self.options.split else subprocess.STDOUT
- if not is_windows():
- setsid = os.setsid
+ if not is_windows():
+ setsid = os.setsid
p = subprocess.Popen(cmd,
stdout=stdout,
@@ -251,6 +251,7 @@ class TestHarness:
cwd=test.workdir,
preexec_fn=setsid)
timed_out = False
+ kill_test = False
if test.timeout is None:
timeout = None
else:
@@ -261,6 +262,11 @@ class TestHarness:
if self.options.verbose:
print("%s time out (After %d seconds)" % (test.name, timeout))
timed_out = True
+ except KeyboardInterrupt:
+ mlog.warning("CTRL-C detected while running %s" % (test.name))
+ kill_test = True
+
+ if kill_test or timed_out:
# Python does not provide multiplatform support for
# killing a process and all its children so we need
# to roll our own.
@@ -438,7 +444,7 @@ TIMEOUT: %4d
logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase)
if self.options.wrapper:
- namebase = os.path.split(self.get_wrapper()[0])[1]
+ namebase = os.path.basename(self.get_wrapper()[0])
elif self.options.setup:
namebase = self.options.setup
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index df945ab..d4ea06a 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -64,16 +64,21 @@ def permitted_kwargs(permitted):
optname_regex = re.compile('[^a-zA-Z0-9_-]')
-@permitted_kwargs({'value'})
+@permitted_kwargs({'value', 'yield'})
def StringParser(name, description, kwargs):
- return coredata.UserStringOption(name, description,
- kwargs.get('value', ''), kwargs.get('choices', []))
+ return coredata.UserStringOption(name,
+ description,
+ kwargs.get('value', ''),
+ kwargs.get('choices', []),
+ kwargs.get('yield', coredata.default_yielding))
-@permitted_kwargs({'value'})
+@permitted_kwargs({'value', 'yield'})
def BooleanParser(name, description, kwargs):
- return coredata.UserBooleanOption(name, description, kwargs.get('value', True))
+ return coredata.UserBooleanOption(name, description,
+ kwargs.get('value', True),
+ kwargs.get('yield', coredata.default_yielding))
-@permitted_kwargs({'value', 'choices'})
+@permitted_kwargs({'value', 'yiel', 'choices'})
def ComboParser(name, description, kwargs):
if 'choices' not in kwargs:
raise OptionException('Combo option missing "choices" keyword.')
@@ -83,9 +88,25 @@ def ComboParser(name, description, kwargs):
for i in choices:
if not isinstance(i, str):
raise OptionException('Combo choice elements must be strings.')
- return coredata.UserComboOption(name, description, choices, kwargs.get('value', choices[0]))
-
-@permitted_kwargs({'value', 'choices'})
+ return coredata.UserComboOption(name,
+ description,
+ choices,
+ kwargs.get('value', choices[0]),
+ kwargs.get('yield', coredata.default_yielding),)
+
+
+@permitted_kwargs({'value', 'min', 'max', 'yield'})
+def IntegerParser(name, description, kwargs):
+ if 'value' not in kwargs:
+ raise OptionException('Integer option must contain value argument.')
+ return coredata.UserIntegerOption(name,
+ description,
+ kwargs.get('min', None),
+ kwargs.get('max', None),
+ kwargs['value'],
+ kwargs.get('yield', coredata.default_yielding))
+
+@permitted_kwargs({'value', 'yield', 'choices'})
def string_array_parser(name, description, kwargs):
if 'choices' in kwargs:
choices = kwargs['choices']
@@ -100,11 +121,16 @@ def string_array_parser(name, description, kwargs):
value = kwargs.get('value', [])
if not isinstance(value, list):
raise OptionException('Array choices must be passed as an array.')
- return coredata.UserArrayOption(name, description, value, choices=choices)
+ return coredata.UserArrayOption(name,
+ description,
+ value,
+ choices=choices,
+ yielding=kwargs.get('yield', coredata.default_yielding))
option_types = {'string': StringParser,
'boolean': BooleanParser,
'combo': ComboParser,
+ 'integer': IntegerParser,
'array': string_array_parser,
}
diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py
index 25451d4..47f4cda 100644
--- a/mesonbuild/scripts/coverage.py
+++ b/mesonbuild/scripts/coverage.py
@@ -14,12 +14,7 @@
from mesonbuild import environment
-import sys, os, subprocess
-
-def remove_dir_from_trace(lcov_command, covfile, dirname):
- tmpfile = covfile + '.tmp'
- subprocess.check_call([lcov_command, '--remove', covfile, dirname, '-o', tmpfile])
- os.replace(tmpfile, covfile)
+import sys, os, subprocess, pathlib
def coverage(source_root, build_root, log_dir):
(gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools()
@@ -38,6 +33,7 @@ def coverage(source_root, build_root, log_dir):
covinfo = os.path.join(log_dir, 'coverage.info')
initial_tracefile = covinfo + '.initial'
run_tracefile = covinfo + '.run'
+ raw_tracefile = covinfo + '.raw'
subprocess.check_call([lcov_exe,
'--directory', build_root,
'--capture',
@@ -55,11 +51,12 @@ def coverage(source_root, build_root, log_dir):
subprocess.check_call([lcov_exe,
'-a', initial_tracefile,
'-a', run_tracefile,
- '-o', covinfo])
- remove_dir_from_trace(lcov_exe, covinfo, '/usr/include/*')
- remove_dir_from_trace(lcov_exe, covinfo, '/usr/local/include/*')
- remove_dir_from_trace(lcov_exe, covinfo, '/usr/src/*')
- remove_dir_from_trace(lcov_exe, covinfo, '/usr/lib/llvm-*/include/*')
+ '-o', raw_tracefile])
+ # Remove all directories outside the source_root from the covinfo
+ subprocess.check_call([lcov_exe,
+ '--extract', raw_tracefile,
+ os.path.join(source_root, '*'),
+ '--output-file', covinfo])
subprocess.check_call([genhtml_exe,
'--prefix', build_root,
'--output-directory', htmloutdir,
@@ -68,6 +65,15 @@ def coverage(source_root, build_root, log_dir):
'--show-details',
'--branch-coverage',
covinfo])
+ if gcovr_exe:
+ print('')
+ print('XML coverage report can be found at',
+ pathlib.Path(log_dir, 'coverage.xml').as_uri())
+ print('Text coverage report can be found at',
+ pathlib.Path(log_dir, 'coverage.txt').as_uri())
+ if lcov_exe and genhtml_exe:
+ print('Html coverage report can be found at',
+ pathlib.Path(htmloutdir, 'index.html').as_uri())
return 0
def run(args):
diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py
index 30ac54c..f308c5a 100644
--- a/mesonbuild/scripts/gettext.py
+++ b/mesonbuild/scripts/gettext.py
@@ -81,7 +81,7 @@ def do_install(src_sub, bld_sub, dest, pkgname, langs):
srcfile = os.path.join(bld_sub, l + '.gmo')
outfile = os.path.join(dest, l, 'LC_MESSAGES',
pkgname + '.mo')
- os.makedirs(os.path.split(outfile)[0], exist_ok=True)
+ os.makedirs(os.path.dirname(outfile), exist_ok=True)
shutil.copyfile(srcfile, outfile)
shutil.copystat(srcfile, outfile)
print('Installing %s to %s' % (srcfile, outfile))
diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py
index fe1de1f..cbc782d 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -128,20 +128,42 @@ def do_copyfile(from_file, to_file):
selinux_updates.append(to_file)
append_to_log(to_file)
-def do_copydir(data, src_prefix, src_dir, dst_dir, exclude):
+def do_copydir(data, src_dir, dst_dir, exclude):
'''
- Copies the directory @src_prefix (full path) into @dst_dir
-
- @src_dir is simply the parent directory of @src_prefix
+ Copies the contents of directory @src_dir into @dst_dir.
+
+ For directory
+ /foo/
+ bar/
+ excluded
+ foobar
+ file
+ do_copydir(..., '/foo', '/dst/dir', {'bar/excluded'}) creates
+ /dst/
+ dir/
+ bar/
+ foobar
+ file
+
+ Args:
+ src_dir: str, absolute path to the source directory
+ dst_dir: str, absolute path to the destination directory
+ exclude: (set(str), set(str)), tuple of (exclude_files, exclude_dirs),
+ each element of the set is a path relative to src_dir.
'''
+ if not os.path.isabs(src_dir):
+ raise ValueError('src_dir must be absolute, got %s' % src_dir)
+ if not os.path.isabs(dst_dir):
+ raise ValueError('dst_dir must be absolute, got %s' % dst_dir)
if exclude is not None:
exclude_files, exclude_dirs = exclude
else:
exclude_files = exclude_dirs = set()
- for root, dirs, files in os.walk(src_prefix):
+ for root, dirs, files in os.walk(src_dir):
+ assert os.path.isabs(root)
for d in dirs[:]:
- abs_src = os.path.join(src_dir, root, d)
- filepart = abs_src[len(src_dir) + 1:]
+ abs_src = os.path.join(root, d)
+ filepart = os.path.relpath(abs_src, start=src_dir)
abs_dst = os.path.join(dst_dir, filepart)
# Remove these so they aren't visited by os.walk at all.
if filepart in exclude_dirs:
@@ -155,8 +177,8 @@ def do_copydir(data, src_prefix, src_dir, dst_dir, exclude):
data.dirmaker.makedirs(abs_dst)
shutil.copystat(abs_src, abs_dst)
for f in files:
- abs_src = os.path.join(src_dir, root, f)
- filepart = abs_src[len(src_dir) + 1:]
+ abs_src = os.path.join(root, f)
+ filepart = os.path.relpath(abs_src, start=src_dir)
if filepart in exclude_files:
continue
abs_dst = os.path.join(dst_dir, filepart)
@@ -164,10 +186,10 @@ def do_copydir(data, src_prefix, src_dir, dst_dir, exclude):
print('Tried to copy file %s but a directory of that name already exists.' % abs_dst)
if os.path.exists(abs_dst):
os.unlink(abs_dst)
- parent_dir = os.path.split(abs_dst)[0]
+ parent_dir = os.path.dirname(abs_dst)
if not os.path.isdir(parent_dir):
os.mkdir(parent_dir)
- shutil.copystat(os.path.split(abs_src)[0], parent_dir)
+ shutil.copystat(os.path.dirname(abs_src), parent_dir)
shutil.copy2(abs_src, abs_dst, follow_symlinks=False)
append_to_log(abs_dst)
@@ -195,23 +217,19 @@ def do_install(datafilename):
run_install_script(d)
def install_subdirs(d):
- for (src_dir, inst_dir, dst_dir, mode, exclude) in d.install_subdirs:
- if src_dir.endswith('/') or src_dir.endswith('\\'):
- src_dir = src_dir[:-1]
- src_prefix = os.path.join(src_dir, inst_dir)
- print('Installing subdir %s to %s' % (src_prefix, dst_dir))
- dst_dir = get_destdir_path(d, dst_dir)
- d.dirmaker.makedirs(dst_dir, exist_ok=True)
- do_copydir(d, src_prefix, src_dir, dst_dir, exclude)
- dst_prefix = os.path.join(dst_dir, inst_dir)
- set_mode(dst_prefix, mode)
+ for (src_dir, dst_dir, mode, exclude) in d.install_subdirs:
+ full_dst_dir = get_destdir_path(d, dst_dir)
+ print('Installing subdir %s to %s' % (src_dir, full_dst_dir))
+ d.dirmaker.makedirs(full_dst_dir, exist_ok=True)
+ do_copydir(d, src_dir, full_dst_dir, exclude)
+ set_mode(full_dst_dir, mode)
def install_data(d):
for i in d.data:
fullfilename = i[0]
outfilename = get_destdir_path(d, i[1])
mode = i[2]
- outdir = os.path.split(outfilename)[0]
+ outdir = os.path.dirname(outfilename)
d.dirmaker.makedirs(outdir, exist_ok=True)
print('Installing %s to %s' % (fullfilename, outdir))
do_copyfile(fullfilename, outfilename)
@@ -221,7 +239,7 @@ def install_man(d):
for m in d.man:
full_source_filename = m[0]
outfilename = get_destdir_path(d, m[1])
- outdir = os.path.split(outfilename)[0]
+ outdir = os.path.dirname(outfilename)
d.dirmaker.makedirs(outdir, exist_ok=True)
print('Installing %s to %s' % (full_source_filename, outdir))
if outfilename.endswith('.gz') and not full_source_filename.endswith('.gz'):
@@ -238,7 +256,7 @@ def install_man(d):
def install_headers(d):
for t in d.headers:
fullfilename = t[0]
- fname = os.path.split(fullfilename)[1]
+ fname = os.path.basename(fullfilename)
outdir = get_destdir_path(d, t[1])
outfilename = os.path.join(outdir, fname)
print('Installing %s to %s' % (fname, outdir))
@@ -304,7 +322,7 @@ def install_targets(d):
for t in d.targets:
fname = check_for_stampfile(t[0])
outdir = get_destdir_path(d, t[1])
- outname = os.path.join(outdir, os.path.split(fname)[-1])
+ outname = os.path.join(outdir, os.path.basename(fname))
aliases = t[2]
should_strip = t[3]
install_rpath = t[4]
@@ -316,7 +334,7 @@ def install_targets(d):
do_copyfile(fname, outname)
if should_strip and d.strip_bin is not None:
if fname.endswith('.jar'):
- print('Not stripping jar target:', os.path.split(fname)[1])
+ print('Not stripping jar target:', os.path.basename(fname))
continue
print('Stripping target {!r}'.format(fname))
ps, stdo, stde = Popen_safe(d.strip_bin + [outname])
@@ -332,7 +350,7 @@ def install_targets(d):
do_copyfile(pdb_filename, pdb_outname)
elif os.path.isdir(fname):
fname = os.path.join(d.build_dir, fname.rstrip('/'))
- do_copydir(d, fname, os.path.dirname(fname), outdir, None)
+ do_copydir(d, fname, os.path.join(outdir, os.path.basename(fname)), None)
else:
raise RuntimeError('Unknown file type for {!r}'.format(fname))
printed_symlink_error = False
@@ -366,7 +384,7 @@ def run(args):
print('Installer script for Meson. Do not run on your own, mmm\'kay?')
print('meson_install.py [install info file]')
datafilename = args[0]
- private_dir = os.path.split(datafilename)[0]
+ private_dir = os.path.dirname(datafilename)
log_dir = os.path.join(private_dir, '../meson-logs')
with open(os.path.join(log_dir, 'install-log.txt'), 'w') as lf:
install_log_file = lf
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index 26a3489..bd440a1 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -164,17 +164,20 @@ class Resolver:
if not ret:
return False
# Submodule has not been added, add it
- if out.startswith(b'-'):
+ if out.startswith(b'+'):
+ mlog.warning('submodule {} might be out of date'.format(dirname))
+ return True
+ elif out.startswith(b'U'):
+ raise RuntimeError('submodule {} has merge conflicts'.format(dirname))
+ elif out.startswith(b'-'):
if subprocess.call(['git', '-C', self.subdir_root, 'submodule', 'update', '--init', dirname]) != 0:
return False
# Submodule was added already, but it wasn't populated. Do a checkout.
elif out.startswith(b' '):
if subprocess.call(['git', 'checkout', '.'], cwd=dirname):
return True
- else:
- m = 'Unknown git submodule output: {!r}'
- raise AssertionError(m.format(out))
- return True
+ m = 'Unknown git submodule output: {!r}'
+ raise RuntimeError(m.format(out))
def get_git(self, p):
checkoutdir = os.path.join(self.subdir_root, p.get('directory'))
diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py
index 0bdc417..09a0289 100644
--- a/mesonbuild/wrap/wraptool.py
+++ b/mesonbuild/wrap/wraptool.py
@@ -150,7 +150,7 @@ def do_promotion(from_path, spdir_name):
assert(from_path.endswith('.wrap'))
shutil.copy(from_path, spdir_name)
elif os.path.isdir(from_path):
- sproj_name = os.path.split(from_path)[1]
+ sproj_name = os.path.basename(from_path)
outputdir = os.path.join(spdir_name, sproj_name)
if os.path.exists(outputdir):
sys.exit('Output dir %s already exists. Will not overwrite.' % outputdir)
@@ -178,7 +178,7 @@ def promote(argument):
def status():
print('Subproject status')
for w in glob('subprojects/*.wrap'):
- name = os.path.split(w)[1][:-5]
+ name = os.path.basename(w)[:-5]
try:
(latest_branch, latest_revision) = get_latest_version(name)
except Exception:
diff --git a/run_project_tests.py b/run_project_tests.py
index d191e28..1d17000 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -31,7 +31,7 @@ import argparse
import xml.etree.ElementTree as ET
import time
import multiprocessing
-import concurrent.futures as conc
+from concurrent.futures import ProcessPoolExecutor
import re
from run_unittests import get_fake_options, run_configure
@@ -59,50 +59,6 @@ class TestResult:
self.buildtime = buildtime
self.testtime = testtime
-class DummyFuture(conc.Future):
- '''
- Dummy Future implementation that executes the provided function when you
- ask for the result. Used on platforms where sem_open() is not available:
- MSYS2, OpenBSD, etc: https://bugs.python.org/issue3770
- '''
- def set_function(self, fn, *args, **kwargs):
- self.fn = fn
- self.fn_args = args
- self.fn_kwargs = kwargs
-
- def result(self, **kwargs):
- try:
- result = self.fn(*self.fn_args, **self.fn_kwargs)
- except BaseException as e:
- self.set_exception(e)
- else:
- self.set_result(result)
- return super().result(**kwargs)
-
-
-class DummyExecutor(conc.Executor):
- '''
- Dummy single-thread 'concurrent' executor for use on platforms where
- sem_open is not available: https://bugs.python.org/issue3770
- '''
-
- def __init__(self):
- from threading import Lock
- self._shutdown = False
- self._shutdownLock = Lock()
-
- def submit(self, fn, *args, **kwargs):
- with self._shutdownLock:
- if self._shutdown:
- raise RuntimeError('Cannot schedule new futures after shutdown')
- f = DummyFuture()
- f.set_function(fn, *args, **kwargs)
- return f
-
- def shutdown(self, wait=True):
- with self._shutdownLock:
- self._shutdown = True
-
class AutoDeletedDir:
def __init__(self, d):
@@ -548,11 +504,7 @@ def _run_tests(all_tests, log_name_base, extra_args):
# Remove this once the following issue has been resolved:
# https://github.com/mesonbuild/meson/pull/2082
num_workers *= 2
- try:
- executor = conc.ProcessPoolExecutor(max_workers=num_workers)
- except ImportError:
- print('Platform doesn\'t ProcessPoolExecutor, falling back to single-threaded testing\n')
- executor = DummyExecutor()
+ executor = ProcessPoolExecutor(max_workers=num_workers)
for name, test_cases, skipped in all_tests:
current_suite = ET.SubElement(junit_root, 'testsuite', {'name': name, 'tests': str(len(test_cases))})
diff --git a/run_unittests.py b/run_unittests.py
index f61544f..103847a 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -433,14 +433,8 @@ class BasePlatformTests(unittest.TestCase):
src_root = os.path.dirname(__file__)
src_root = os.path.join(os.getcwd(), src_root)
self.src_root = src_root
- # In case the directory is inside a symlinked directory, find the real
- # path otherwise we might not find the srcdir from inside the builddir.
- self.builddir = os.path.realpath(tempfile.mkdtemp())
- self.logdir = os.path.join(self.builddir, 'meson-logs')
self.prefix = '/usr'
self.libdir = os.path.join(self.prefix, 'lib')
- self.installdir = os.path.join(self.builddir, 'install')
- self.distdir = os.path.join(self.builddir, 'meson-dist')
# Get the backend
# FIXME: Extract this from argv?
self.backend = getattr(Backend, os.environ.get('MESON_UNIT_TEST_BACKEND', 'ninja'))
@@ -449,7 +443,6 @@ class BasePlatformTests(unittest.TestCase):
self.meson_command = meson_command + self.meson_args
self.mconf_command = meson_command + ['configure']
self.mintro_command = meson_command + ['introspect']
- self.mtest_command = meson_command + ['test', '-C', self.builddir]
self.wrap_command = meson_command + ['wrap']
# Backend-specific build commands
self.build_command, self.clean_command, self.test_command, self.install_command, \
@@ -468,6 +461,20 @@ class BasePlatformTests(unittest.TestCase):
# XCode backend is untested with unit tests, help welcome!
self.no_rebuild_stdout = 'UNKNOWN BACKEND {!r}'.format(self.backend.name)
+ self.builddirs = []
+ self.new_builddir()
+
+ def new_builddir(self):
+ # In case the directory is inside a symlinked directory, find the real
+ # path otherwise we might not find the srcdir from inside the builddir.
+ self.builddir = os.path.realpath(tempfile.mkdtemp())
+ self.privatedir = os.path.join(self.builddir, 'meson-private')
+ self.logdir = os.path.join(self.builddir, 'meson-logs')
+ self.installdir = os.path.join(self.builddir, 'install')
+ self.distdir = os.path.join(self.builddir, 'meson-dist')
+ self.mtest_command = meson_command + ['test', '-C', self.builddir]
+ self.builddirs.append(self.builddir)
+
def _print_meson_log(self):
log = os.path.join(self.logdir, 'meson-log.txt')
if not os.path.isfile(log):
@@ -477,10 +484,11 @@ class BasePlatformTests(unittest.TestCase):
print(f.read())
def tearDown(self):
- try:
- windows_proof_rmtree(self.builddir)
- except FileNotFoundError:
- pass
+ for path in self.builddirs:
+ try:
+ windows_proof_rmtree(path)
+ except FileNotFoundError:
+ pass
os.environ = self.orig_env
super().tearDown()
@@ -1702,16 +1710,16 @@ int main(int argc, char **argv) {
self.build()
def test_warning_location(self):
- tdir = os.path.join(self.unit_test_dir, '20 warning location')
+ tdir = os.path.join(self.unit_test_dir, '21 warning location')
out = self.init(tdir)
for expected in [
- r'WARNING: Keyword argument "link_with" defined multiple times in file meson.build, line 4',
- r'WARNING: Keyword argument "link_with" defined multiple times in file sub' + os.path.sep + r'meson.build, line 3',
- r'WARNING: a warning of some sort in file meson.build, line 6',
- r'WARNING: subdir warning in file sub' + os.path.sep + r'meson.build, line 4',
- r'WARNING: Module unstable-simd has no backwards or forwards compatibility and might not exist in future releases in file meson.build, line 7',
- r"WARNING: The variable(s) 'MISSING' in the input file conf.in are not present in the given configuration data in file meson.build, line 10",
- r'WARNING: Passed invalid keyword argument "invalid" in file meson.build, line 1'
+ r'meson.build:4: WARNING: Keyword argument "link_with" defined multiple times.',
+ r'sub' + os.path.sep + r'meson.build:3: WARNING: Keyword argument "link_with" defined multiple times.',
+ r'meson.build:6: WARNING: a warning of some sort',
+ r'sub' + os.path.sep + r'meson.build:4: WARNING: subdir warning',
+ r'meson.build:7: WARNING: Module unstable-simd has no backwards or forwards compatibility and might not exist in future releases.',
+ r"meson.build:10: WARNING: The variable(s) 'MISSING' in the input file conf.in are not present in the given configuration data.",
+ r'meson.build:1: WARNING: Passed invalid keyword argument "invalid".',
]:
self.assertRegex(out, re.escape(expected))
@@ -2059,11 +2067,17 @@ class LinuxlikeTests(BasePlatformTests):
'''
Test that generated pkg-config files correctly handle dependencies
'''
-
testdir = os.path.join(self.common_test_dir, '51 pkgconfig-gen')
self.init(testdir)
+ privatedir1 = self.privatedir
- os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir
+ self.new_builddir()
+ os.environ['PKG_CONFIG_LIBDIR'] = privatedir1
+ testdir = os.path.join(self.common_test_dir, '51 pkgconfig-gen', 'dependencies')
+ self.init(testdir)
+ privatedir2 = self.privatedir
+
+ os.environ['PKG_CONFIG_LIBDIR'] = os.pathsep.join([privatedir1, privatedir2])
cmd = ['pkg-config', 'dependency-test']
out = self._run(cmd + ['--print-requires']).strip().split()
@@ -2085,6 +2099,12 @@ class LinuxlikeTests(BasePlatformTests):
'-llibinternal', '-lcustom2',
'-lfoo']))
+ def test_pkg_unfound(self):
+ testdir = os.path.join(self.unit_test_dir, '22 unfound pkgconfig')
+ self.init(testdir)
+ pcfile = open(os.path.join(self.privatedir, 'somename.pc')).read()
+ self.assertFalse('blub_blob_blib' in pcfile)
+
def test_vala_c_warnings(self):
'''
Test that no warnings are emitted for C code generated by Vala. This
diff --git a/test cases/common/140 get define/meson.build b/test cases/common/140 get define/meson.build
index fd87177..9f5539b 100644
--- a/test cases/common/140 get define/meson.build
+++ b/test cases/common/140 get define/meson.build
@@ -66,8 +66,8 @@ foreach lang : ['c', 'cpp']
if meson.is_cross_build()
# Can't use an empty array as a fallback here because of
# https://github.com/mesonbuild/meson/issues/1481
- lang_args = meson.get_cross_property(lang + '_args', false)
- if lang_args != false
+ lang_args = meson.get_cross_property(lang + '_args', [])
+ if lang_args.length() != 0
foreach lang_arg : lang_args
if lang_arg.contains('MESON_TEST_ISSUE_1665')
run_1665_test = true
diff --git a/test cases/common/173 preserve gendir/base.inp b/test cases/common/174 preserve gendir/base.inp
index df967b9..df967b9 100644
--- a/test cases/common/173 preserve gendir/base.inp
+++ b/test cases/common/174 preserve gendir/base.inp
diff --git a/test cases/common/173 preserve gendir/com/mesonbuild/subbie.inp b/test cases/common/174 preserve gendir/com/mesonbuild/subbie.inp
index df0f4e9..df0f4e9 100644
--- a/test cases/common/173 preserve gendir/com/mesonbuild/subbie.inp
+++ b/test cases/common/174 preserve gendir/com/mesonbuild/subbie.inp
diff --git a/test cases/common/173 preserve gendir/genprog.py b/test cases/common/174 preserve gendir/genprog.py
index 8bd2b9d..1e10998 100755
--- a/test cases/common/173 preserve gendir/genprog.py
+++ b/test cases/common/174 preserve gendir/genprog.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
import os, sys, argparse
-import pathlib
h_templ = '''#pragma once
diff --git a/test cases/common/173 preserve gendir/meson.build b/test cases/common/174 preserve gendir/meson.build
index ce219f0..ce219f0 100644
--- a/test cases/common/173 preserve gendir/meson.build
+++ b/test cases/common/174 preserve gendir/meson.build
diff --git a/test cases/common/173 preserve gendir/testprog.c b/test cases/common/174 preserve gendir/testprog.c
index 46b4602..46b4602 100644
--- a/test cases/common/173 preserve gendir/testprog.c
+++ b/test cases/common/174 preserve gendir/testprog.c
diff --git a/test cases/common/175 get project license/bar.c b/test cases/common/175 get project license/bar.c
new file mode 100644
index 0000000..864869b
--- /dev/null
+++ b/test cases/common/175 get project license/bar.c
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+int main(int argc, char **argv) {
+ printf("I'm a main project bar.\n");
+ return 0;
+}
diff --git a/test cases/common/175 get project license/meson.build b/test cases/common/175 get project license/meson.build
new file mode 100644
index 0000000..37303e3
--- /dev/null
+++ b/test cases/common/175 get project license/meson.build
@@ -0,0 +1,8 @@
+project('bar', 'c', license: 'Apache')
+
+executable('bar', 'bar.c')
+
+license = meson.project_license()[0]
+if license != 'Apache'
+ error('The license should be Apache, but it is: ' + license)
+endif
diff --git a/test cases/common/176 yield/meson.build b/test cases/common/176 yield/meson.build
new file mode 100644
index 0000000..ba3e426
--- /dev/null
+++ b/test cases/common/176 yield/meson.build
@@ -0,0 +1,6 @@
+project('yield_options', 'c')
+
+subproject('sub')
+
+assert(get_option('unshared_option') == 'one', 'Unshared option has wrong value in superproject.')
+assert(get_option('shared_option') == 'two', 'Unshared option has wrong value in superproject..')
diff --git a/test cases/common/176 yield/meson_options.txt b/test cases/common/176 yield/meson_options.txt
new file mode 100644
index 0000000..36bad4b
--- /dev/null
+++ b/test cases/common/176 yield/meson_options.txt
@@ -0,0 +1,2 @@
+option('unshared_option', type : 'string', value : 'one')
+option('shared_option', type : 'string', value : 'two')
diff --git a/test cases/common/176 yield/subprojects/sub/meson.build b/test cases/common/176 yield/subprojects/sub/meson.build
new file mode 100644
index 0000000..3a506e0
--- /dev/null
+++ b/test cases/common/176 yield/subprojects/sub/meson.build
@@ -0,0 +1,4 @@
+project('subbie', 'c')
+
+assert(get_option('unshared_option') == 'three', 'Unshared option has wrong value in subproject.')
+assert(get_option('shared_option') == 'two', 'Shared option has wrong value in subproject.')
diff --git a/test cases/common/176 yield/subprojects/sub/meson_options.txt b/test cases/common/176 yield/subprojects/sub/meson_options.txt
new file mode 100644
index 0000000..a96c307
--- /dev/null
+++ b/test cases/common/176 yield/subprojects/sub/meson_options.txt
@@ -0,0 +1,2 @@
+option('unshared_option', type : 'string', value : 'three', yield : false)
+option('shared_option', type : 'string', value : 'four', yield : true)
diff --git a/test cases/common/47 options/meson.build b/test cases/common/47 options/meson.build
index 863703c..f177aa4 100644
--- a/test cases/common/47 options/meson.build
+++ b/test cases/common/47 options/meson.build
@@ -25,3 +25,7 @@ endif
if get_option('includedir') != 'include'
error('Incorrect value in builtin option.')
endif
+
+if get_option('integer_opt') != 3
+ error('Incorrect value in integer option.')
+endif
diff --git a/test cases/common/47 options/meson_options.txt b/test cases/common/47 options/meson_options.txt
index 6bd0346..4e1c8d8 100644
--- a/test cases/common/47 options/meson_options.txt
+++ b/test cases/common/47 options/meson_options.txt
@@ -3,3 +3,4 @@ option('other_one', type : 'boolean', value : false)
option('combo_opt', type : 'combo', choices : ['one', 'two', 'combo'], value : 'combo')
option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two'])
option('free_array_opt', type : 'array')
+option('integer_opt', type : 'integer', min : 0, max : 5, value : 3)
diff --git a/test cases/common/51 pkgconfig-gen/dependencies/exposed.c b/test cases/common/51 pkgconfig-gen/dependencies/exposed.c
new file mode 100644
index 0000000..005202e
--- /dev/null
+++ b/test cases/common/51 pkgconfig-gen/dependencies/exposed.c
@@ -0,0 +1,3 @@
+int exposed_function() {
+ return 42;
+}
diff --git a/test cases/common/51 pkgconfig-gen/dependencies/internal.c b/test cases/common/51 pkgconfig-gen/dependencies/internal.c
new file mode 100644
index 0000000..1a41b11
--- /dev/null
+++ b/test cases/common/51 pkgconfig-gen/dependencies/internal.c
@@ -0,0 +1,3 @@
+int internal_function() {
+ return 42;
+}
diff --git a/test cases/common/51 pkgconfig-gen/dependencies/meson.build b/test cases/common/51 pkgconfig-gen/dependencies/meson.build
new file mode 100644
index 0000000..a767eb5
--- /dev/null
+++ b/test cases/common/51 pkgconfig-gen/dependencies/meson.build
@@ -0,0 +1,38 @@
+project('pkgconfig-gen-dependencies', 'c')
+
+pkgg = import('pkgconfig')
+
+# libmain internally use libinternal and expose libexpose in its API
+exposed_lib = shared_library('libexposed', 'exposed.c')
+internal_lib = shared_library('libinternal', 'internal.c')
+main_lib = shared_library('libmain', link_with : [exposed_lib, internal_lib])
+
+pkgg.generate(libraries : exposed_lib,
+ version : '1.0',
+ name : 'libexposed',
+ description : 'An exposed library in dependency test.'
+)
+
+# Declare a few different Dependency objects
+pc_dep = dependency('libfoo')
+notfound_dep = dependency('notfound', required : false)
+threads_dep = dependency('threads')
+custom_dep = declare_dependency(link_args : ['-lcustom'], compile_args : ['-DCUSTOM'])
+custom2_dep = declare_dependency(link_args : ['-lcustom2'], compile_args : ['-DCUSTOM2'])
+
+# Generate a PC file:
+# - Having libmain in libraries should pull implicitely libexposed and libinternal in Libs.private
+# - Having libexposed in libraries should remove it from Libs.private
+# - We generated a pc file for libexposed so it should be in Requires instead of Libs
+# - Having threads_dep in libraries should add '-pthread' in both Libs and Cflags
+# - Having custom_dep in libraries and libraries_private should only add it in Libs
+# - Having custom2_dep in libraries_private should not add its Cflags
+# - Having pc_dep in libraries_private should add it in Requires.private
+# - notfound_dep is not required so it shouldn't appear in the pc file.
+pkgg.generate(libraries : [main_lib, exposed_lib, threads_dep , custom_dep],
+ libraries_private : [custom_dep, custom2_dep, pc_dep, notfound_dep],
+ version : '1.0',
+ name : 'dependency-test',
+ filebase : 'dependency-test',
+ description : 'A dependency test.'
+)
diff --git a/test cases/common/51 pkgconfig-gen/meson.build b/test cases/common/51 pkgconfig-gen/meson.build
index a8dd092..f9d7f7f 100644
--- a/test cases/common/51 pkgconfig-gen/meson.build
+++ b/test cases/common/51 pkgconfig-gen/meson.build
@@ -46,36 +46,3 @@ pkgg.generate(
description : 'A foo library.',
variables : ['foo=bar', 'datadir=${prefix}/data']
)
-
-# libmain internally use libinternal and expose libexpose in its API
-exposed_lib = shared_library('libexposed', 'simple.c')
-internal_lib = shared_library('libinternal', 'simple.c')
-main_lib = shared_library('libmain', link_with : [exposed_lib, internal_lib])
-
-pkgg.generate(libraries : exposed_lib,
- version : libver,
- name : 'libexposed',
- description : 'An exposed library in dependency test.'
-)
-
-# Declare a few different Dependency objects
-pc_dep = dependency('libfoo', required : false)
-threads_dep = dependency('threads', required : false)
-custom_dep = declare_dependency(link_args : ['-lcustom'], compile_args : ['-DCUSTOM'])
-custom2_dep = declare_dependency(link_args : ['-lcustom2'], compile_args : ['-DCUSTOM2'])
-
-# Generate a PC file:
-# - Having libmain in libraries should pull implicitely libexposed and libinternal in Libs.private
-# - Having libexposed in libraries should remove it from Libs.private
-# - We generated a pc file for libexposed so it should be in Requires instead of Libs
-# - Having threads_dep in libraries should add '-pthread' in both Libs and Cflags
-# - Having custom_dep in libraries and libraries_private should only add it in Libs
-# - Having custom2_dep in libraries_private should not add its Cflags
-# - Having pc_dep in libraries_private should add it in Requires.private
-pkgg.generate(libraries : [main_lib, exposed_lib, threads_dep , custom_dep],
- libraries_private : [custom_dep, custom2_dep, pc_dep],
- version : libver,
- name : 'dependency-test',
- filebase : 'dependency-test',
- description : 'A dependency test.'
-)
diff --git a/test cases/common/58 run target/meson.build b/test cases/common/58 run target/meson.build
index 686db1f..93a4ad0 100644
--- a/test cases/common/58 run target/meson.build
+++ b/test cases/common/58 run target/meson.build
@@ -1,8 +1,5 @@
project('run target', 'c')
-# deprecated format, fix once we remove support for it.
-run_target('mycommand','scripts/script.sh')
-
# Make it possible to run built programs.
# In cross builds exe_wrapper should be added if it exists.
diff --git a/test cases/common/66 install subdir/installed_files.txt b/test cases/common/66 install subdir/installed_files.txt
index e5d2307..3f561d5 100644
--- a/test cases/common/66 install subdir/installed_files.txt
+++ b/test cases/common/66 install subdir/installed_files.txt
@@ -1,3 +1,9 @@
+usr/share/dircheck/fifth.dat
+usr/share/dircheck/seventh.dat
+usr/share/dircheck/nineth.dat
+usr/share/eighth.dat
+usr/share/fourth.dat
+usr/share/sixth.dat
usr/share/sub1/data1.dat
usr/share/sub1/second.dat
usr/share/sub1/third.dat
diff --git a/test cases/common/66 install subdir/meson.build b/test cases/common/66 install subdir/meson.build
index 18e0eaf..403b6f0 100644
--- a/test cases/common/66 install subdir/meson.build
+++ b/test cases/common/66 install subdir/meson.build
@@ -11,3 +11,7 @@ subdir('subdir')
# and read-list perms for owner and group
install_subdir('sub1', install_dir : 'share', install_mode : ['rwxr-x--t', 'root'])
install_subdir('sub/sub1', install_dir : 'share')
+
+# strip_directory
+install_subdir('sub_elided', install_dir : 'share', strip_directory : true)
+install_subdir('nested_elided/sub', install_dir : 'share', strip_directory : true)
diff --git a/test cases/common/66 install subdir/nested_elided/sub/dircheck/nineth.dat b/test cases/common/66 install subdir/nested_elided/sub/dircheck/nineth.dat
new file mode 100644
index 0000000..c4eaca7
--- /dev/null
+++ b/test cases/common/66 install subdir/nested_elided/sub/dircheck/nineth.dat
@@ -0,0 +1 @@
+Nested file under nested elided directory.
diff --git a/test cases/common/66 install subdir/nested_elided/sub/eighth.dat b/test cases/common/66 install subdir/nested_elided/sub/eighth.dat
new file mode 100644
index 0000000..fa9b7b7
--- /dev/null
+++ b/test cases/common/66 install subdir/nested_elided/sub/eighth.dat
@@ -0,0 +1 @@
+File in nested elided directory.
diff --git a/test cases/common/66 install subdir/sub_elided/dircheck/fifth.dat b/test cases/common/66 install subdir/sub_elided/dircheck/fifth.dat
new file mode 100644
index 0000000..b6ca009
--- /dev/null
+++ b/test cases/common/66 install subdir/sub_elided/dircheck/fifth.dat
@@ -0,0 +1 @@
+Data file in a subdir of elided directory.
diff --git a/test cases/common/66 install subdir/sub_elided/fourth.dat b/test cases/common/66 install subdir/sub_elided/fourth.dat
new file mode 100644
index 0000000..ca5f26a
--- /dev/null
+++ b/test cases/common/66 install subdir/sub_elided/fourth.dat
@@ -0,0 +1 @@
+Test that this file is installed directly into install_dir.
diff --git a/test cases/common/66 install subdir/subdir/meson.build b/test cases/common/66 install subdir/subdir/meson.build
index a1dadd4..0f81cdb 100644
--- a/test cases/common/66 install subdir/subdir/meson.build
+++ b/test cases/common/66 install subdir/subdir/meson.build
@@ -1,3 +1,5 @@
install_subdir('sub1', install_dir : 'share',
# This mode will be overridden by the mode set in the outer install_subdir
install_mode : 'rwxr-x---')
+
+install_subdir('sub_elided', install_dir : 'share', strip_directory : true)
diff --git a/test cases/common/66 install subdir/subdir/sub_elided/dircheck/seventh.dat b/test cases/common/66 install subdir/subdir/sub_elided/dircheck/seventh.dat
new file mode 100644
index 0000000..ea0b8dc
--- /dev/null
+++ b/test cases/common/66 install subdir/subdir/sub_elided/dircheck/seventh.dat
@@ -0,0 +1 @@
+Nested file in a subdir.
diff --git a/test cases/common/66 install subdir/subdir/sub_elided/sixth.dat b/test cases/common/66 install subdir/subdir/sub_elided/sixth.dat
new file mode 100644
index 0000000..140f075
--- /dev/null
+++ b/test cases/common/66 install subdir/subdir/sub_elided/sixth.dat
@@ -0,0 +1 @@
+Elide test file in a subdir.
diff --git a/test cases/common/68 number arithmetic/meson.build b/test cases/common/68 number arithmetic/meson.build
index 495a83e..f2e84a8 100644
--- a/test cases/common/68 number arithmetic/meson.build
+++ b/test cases/common/68 number arithmetic/meson.build
@@ -56,3 +56,9 @@ assert(3 >= 3, 'Gte broken')
assert(true.to_int() == 1,'bool to_int() broken')
assert(false.to_int() == 0,'bool to_int() broken')
+
+hex_255 = 0xff
+hex2_255 = 0XFF
+
+assert(hex_255 == 255, 'Hex parsing is broken.')
+assert(hex2_255 == 255, 'Uppercase hex parsing is broken.')
diff --git a/test cases/common/90 identical target name in subproject/meson.build b/test cases/common/90 identical target name in subproject/meson.build
index 98e4891..e804d3c 100644
--- a/test cases/common/90 identical target name in subproject/meson.build
+++ b/test cases/common/90 identical target name in subproject/meson.build
@@ -3,4 +3,4 @@ project('toplevel bar', 'c')
subproject('foo')
executable('bar', 'bar.c')
-run_target('nop', 'true')
+run_target('nop', command : ['true'])
diff --git a/test cases/common/90 identical target name in subproject/subprojects/foo/meson.build b/test cases/common/90 identical target name in subproject/subprojects/foo/meson.build
index a7a31b1..3f22337 100644
--- a/test cases/common/90 identical target name in subproject/subprojects/foo/meson.build
+++ b/test cases/common/90 identical target name in subproject/subprojects/foo/meson.build
@@ -1,4 +1,4 @@
project('subfoo', 'c')
executable('bar', 'bar.c')
-run_target('nop', 'true')
+run_target('nop', command : ['true'])
diff --git a/test cases/failing/68 subproj different versions/meson.build b/test cases/failing/68 subproj different versions/meson.build
index 7690277..e964e42 100644
--- a/test cases/failing/68 subproj different versions/meson.build
+++ b/test cases/failing/68 subproj different versions/meson.build
@@ -3,7 +3,7 @@ project('super', 'c')
# A will use version 1 of C
a_dep = dependency('a', fallback: ['a', 'a_dep'])
-# B will fail becuase it requests version 2 of C
+# B will fail because it requests version 2 of C
b_dep = dependency('b', fallback: ['b', 'b_dep'])
main = executable('main', files('main.c'), dependencies: [a_dep, b_dep])
diff --git a/test cases/fpga/1 simple/meson.build b/test cases/fpga/1 simple/meson.build
new file mode 100644
index 0000000..eff8088
--- /dev/null
+++ b/test cases/fpga/1 simple/meson.build
@@ -0,0 +1,9 @@
+project('lattice', 'c')
+
+is = import('unstable_icestorm')
+
+is.project('spin',
+ 'spin.v',
+ constraint_file : 'spin.pcf',
+)
+
diff --git a/test cases/fpga/1 simple/spin.pcf b/test cases/fpga/1 simple/spin.pcf
new file mode 100644
index 0000000..de06f5d
--- /dev/null
+++ b/test cases/fpga/1 simple/spin.pcf
@@ -0,0 +1,6 @@
+set_io LED1 99
+set_io LED2 98
+set_io LED3 97
+set_io LED4 96
+set_io LED5 95
+set_io clk 21
diff --git a/test cases/fpga/1 simple/spin.v b/test cases/fpga/1 simple/spin.v
new file mode 100644
index 0000000..edc40c4
--- /dev/null
+++ b/test cases/fpga/1 simple/spin.v
@@ -0,0 +1,32 @@
+
+module top(input clk, output LED1, output LED2, output LED3, output LED4, output LED5);
+
+ reg ready = 0;
+ reg [23:0] divider;
+ reg [3:0] spin;
+
+ always @(posedge clk) begin
+ if (ready)
+ begin
+ if (divider == 6000000)
+ begin
+ divider <= 0;
+ spin <= {spin[2], spin[3], spin[0], spin[1]};
+ end
+ else
+ divider <= divider + 1;
+ end
+ else
+ begin
+ ready <= 1;
+ spin <= 4'b1010;
+ divider <= 0;
+ end
+ end
+
+ assign LED1 = spin[0];
+ assign LED2 = spin[1];
+ assign LED3 = spin[2];
+ assign LED4 = spin[3];
+ assign LED5 = 1;
+endmodule
diff --git a/test cases/frameworks/1 boost/linkexe.cc b/test cases/frameworks/1 boost/linkexe.cc
index 240c7c1..e00edee 100644
--- a/test cases/frameworks/1 boost/linkexe.cc
+++ b/test cases/frameworks/1 boost/linkexe.cc
@@ -1,3 +1,5 @@
+#define _XOPEN_SOURCE 500
+
#include<boost/thread.hpp>
boost::recursive_mutex m;
diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build
index 7c33268..b0e848d 100644
--- a/test cases/frameworks/4 qt/meson.build
+++ b/test cases/frameworks/4 qt/meson.build
@@ -92,5 +92,8 @@ foreach qt : ['qt4', 'qt5']
plugin = library(qt + 'plugin', 'plugin/plugin.cpp', pluginpreprocess,
include_directories : plugin_includes,
dependencies : qtcore)
+ if qt == 'qt5'
+ subdir('subfolder')
+ endif
endif
endforeach
diff --git a/test cases/frameworks/4 qt/subfolder/main.cpp b/test cases/frameworks/4 qt/subfolder/main.cpp
new file mode 100644
index 0000000..61cc9d4
--- /dev/null
+++ b/test cases/frameworks/4 qt/subfolder/main.cpp
@@ -0,0 +1,10 @@
+#include <QImage>
+
+int main(int argc, char **argv) {
+ Q_INIT_RESOURCE(stuff3);
+ QImage qi(":/thing.png");
+ if(qi.width() != 640) {
+ return 1;
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/test cases/frameworks/4 qt/subfolder/meson.build b/test cases/frameworks/4 qt/subfolder/meson.build
new file mode 100644
index 0000000..d3ff609
--- /dev/null
+++ b/test cases/frameworks/4 qt/subfolder/meson.build
@@ -0,0 +1,4 @@
+
+qresources = qtmodule.preprocess(qresources : 'resources/stuff3.qrc')
+
+app = executable('subfolder', 'main.cpp', qresources, dependencies : qtdep)
diff --git a/test cases/frameworks/4 qt/subfolder/resources/stuff3.qrc b/test cases/frameworks/4 qt/subfolder/resources/stuff3.qrc
new file mode 100644
index 0000000..fdfb58e
--- /dev/null
+++ b/test cases/frameworks/4 qt/subfolder/resources/stuff3.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file>thing.png</file>
+ </qresource>
+</RCC>
diff --git a/test cases/frameworks/4 qt/subfolder/resources/thing.png b/test cases/frameworks/4 qt/subfolder/resources/thing.png
new file mode 100644
index 0000000..4b001bd
--- /dev/null
+++ b/test cases/frameworks/4 qt/subfolder/resources/thing.png
Binary files differ
diff --git a/test cases/linuxlike/1 pkg-config/meson.build b/test cases/linuxlike/1 pkg-config/meson.build
index 30e5d25..17ee192 100644
--- a/test cases/linuxlike/1 pkg-config/meson.build
+++ b/test cases/linuxlike/1 pkg-config/meson.build
@@ -17,6 +17,8 @@ test('zlibtest', exe)
zprefix = dep.get_pkgconfig_variable('prefix') # Always set but we can't be sure what the value is.
# pkg-config returns empty string for not defined variables
assert(dep.get_pkgconfig_variable('nonexisting') == '', 'Value of unknown variable is not empty.')
+# ... unless default: is used
+assert(dep.get_pkgconfig_variable('nonexisting', default: 'foo') == 'foo', 'Value of unknown variable is not defaulted.')
# pkg-config is able to replace variables
assert(dep.get_pkgconfig_variable('prefix', define_variable: ['prefix', '/tmp']) == '/tmp', 'prefix variable has not been replaced.')
diff --git a/test cases/rust/4 polyglot/meson.build b/test cases/rust/4 polyglot/meson.build
index a20d766..b7eef57 100644
--- a/test cases/rust/4 polyglot/meson.build
+++ b/test cases/rust/4 polyglot/meson.build
@@ -1,5 +1,5 @@
project('rust and c polyglot executable', 'c', 'rust')
-l = library('stuff', 'stuff.rs', install : true)
+l = library('stuff', 'stuff.rs', rust_crate_type: 'cdylib', install : true)
e = executable('prog', 'prog.c', link_with : l, install : true)
test('polyglottest', e)
diff --git a/test cases/unit/20 warning location/a.c b/test cases/unit/21 warning location/a.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/a.c
+++ b/test cases/unit/21 warning location/a.c
diff --git a/test cases/unit/20 warning location/b.c b/test cases/unit/21 warning location/b.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/b.c
+++ b/test cases/unit/21 warning location/b.c
diff --git a/test cases/unit/20 warning location/conf.in b/test cases/unit/21 warning location/conf.in
index a2903ed..a2903ed 100644
--- a/test cases/unit/20 warning location/conf.in
+++ b/test cases/unit/21 warning location/conf.in
diff --git a/test cases/unit/20 warning location/main.c b/test cases/unit/21 warning location/main.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/main.c
+++ b/test cases/unit/21 warning location/main.c
diff --git a/test cases/unit/20 warning location/meson.build b/test cases/unit/21 warning location/meson.build
index 15295a9..15295a9 100644
--- a/test cases/unit/20 warning location/meson.build
+++ b/test cases/unit/21 warning location/meson.build
diff --git a/test cases/unit/20 warning location/sub/c.c b/test cases/unit/21 warning location/sub/c.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/sub/c.c
+++ b/test cases/unit/21 warning location/sub/c.c
diff --git a/test cases/unit/20 warning location/sub/d.c b/test cases/unit/21 warning location/sub/d.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/sub/d.c
+++ b/test cases/unit/21 warning location/sub/d.c
diff --git a/test cases/unit/20 warning location/sub/meson.build b/test cases/unit/21 warning location/sub/meson.build
index 27f6778..27f6778 100644
--- a/test cases/unit/20 warning location/sub/meson.build
+++ b/test cases/unit/21 warning location/sub/meson.build
diff --git a/test cases/unit/20 warning location/sub/sub.c b/test cases/unit/21 warning location/sub/sub.c
index e69de29..e69de29 100644
--- a/test cases/unit/20 warning location/sub/sub.c
+++ b/test cases/unit/21 warning location/sub/sub.c
diff --git a/test cases/unit/22 unfound pkgconfig/meson.build b/test cases/unit/22 unfound pkgconfig/meson.build
new file mode 100644
index 0000000..1285c0a
--- /dev/null
+++ b/test cases/unit/22 unfound pkgconfig/meson.build
@@ -0,0 +1,15 @@
+project('foobar', 'c')
+
+unfound = dependency('blub_blob_blib', required : false)
+
+pkgg = import('pkgconfig')
+
+l = shared_library('somename', 'some.c',
+ dependencies : unfound)
+
+pkgg.generate(
+ libraries : l,
+ name : 'somename',
+ version : '1.0.0',
+ description : 'A test library.',
+)
diff --git a/test cases/unit/22 unfound pkgconfig/some.c b/test cases/unit/22 unfound pkgconfig/some.c
new file mode 100644
index 0000000..fb765fb
--- /dev/null
+++ b/test cases/unit/22 unfound pkgconfig/some.c
@@ -0,0 +1,3 @@
+int some() {
+ return 6;
+}