aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml8
-rw-r--r--.travis.yml8
-rw-r--r--ci/appveyor-install.bat4
-rw-r--r--contributing.txt2
-rw-r--r--docs/markdown/Compiler-properties.md23
-rw-r--r--docs/markdown/D.md89
-rw-r--r--docs/markdown/Getting-meson.md2
-rw-r--r--docs/markdown/Gnome-module.md4
-rw-r--r--docs/markdown/Pkgconfig-module.md2
-rw-r--r--docs/markdown/Reference-manual.md18
-rw-r--r--docs/markdown/Reference-tables.md60
-rw-r--r--docs/markdown/Videos.md8
-rw-r--r--docs/markdown/index.md6
-rw-r--r--docs/sitemap.txt2
-rw-r--r--mesonbuild/backend/backends.py67
-rw-r--r--mesonbuild/backend/ninjabackend.py52
-rw-r--r--mesonbuild/backend/vs2010backend.py34
-rw-r--r--mesonbuild/build.py20
-rw-r--r--mesonbuild/compilers/d.py55
-rw-r--r--mesonbuild/environment.py5
-rw-r--r--mesonbuild/interpreter.py14
-rw-r--r--mesonbuild/mesonlib.py3
-rw-r--r--mesonbuild/mesonmain.py19
-rw-r--r--mesonbuild/mlog.py3
-rw-r--r--mesonbuild/modules/gnome.py10
-rw-r--r--mesonbuild/modules/pkgconfig.py8
-rw-r--r--mesonbuild/mtest.py6
-rw-r--r--mesonbuild/scripts/yelphelper.py4
-rwxr-xr-xmsi/createmsi.py15
-rwxr-xr-xrun_tests.py8
-rw-r--r--test cases/common/159 reserved targets/meson.build5
-rw-r--r--test cases/common/160 duplicate source names/dir1/file.c16
-rw-r--r--test cases/common/160 duplicate source names/dir1/meson.build1
-rw-r--r--test cases/common/160 duplicate source names/dir2/dir1/file.c1
-rw-r--r--test cases/common/160 duplicate source names/dir2/file.c1
-rw-r--r--test cases/common/160 duplicate source names/dir2/meson.build1
-rw-r--r--test cases/common/160 duplicate source names/dir3/dir1/file.c1
-rw-r--r--test cases/common/160 duplicate source names/dir3/file.c1
-rw-r--r--test cases/common/160 duplicate source names/dir3/meson.build1
-rw-r--r--test cases/common/160 duplicate source names/meson.build7
-rw-r--r--test cases/d/9 features/app.d51
-rw-r--r--test cases/d/9 features/data/food.txt6
-rw-r--r--test cases/d/9 features/data/people.txt5
-rw-r--r--test cases/d/9 features/meson.build29
-rw-r--r--test cases/frameworks/13 yelp/help/LINGUAS2
-rw-r--r--test cases/frameworks/13 yelp/help/meson.build6
-rw-r--r--test cases/frameworks/13 yelp/installed_files.txt6
-rw-r--r--test cases/frameworks/7 gnome/gdbus/meson.build3
-rw-r--r--test cases/vala/12 custom output/bar.vala0
-rw-r--r--test cases/vala/12 custom output/meson.build10
-rwxr-xr-xtools/cmake2meson.py9
51 files changed, 550 insertions, 171 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index d8a4b12..ac69dd4 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -49,17 +49,15 @@ branches:
only:
- master
-skip_commits:
- files:
- - docs/**/*
-
install:
- cmd: set "ORIG_PATH=%PATH%"
# Boost 1.56.0: https://www.appveyor.com/docs/build-environment/#boost
#- cmd: set "BOOST_ROOT=C:\Libraries\boost"
+ # Use a Ninja with QuLogic's patch: https://github.com/ninja-build/ninja/issues/1219
+ - cmd: set "MESON_FIXED_NINJA=1"
+ - ps: (new-object net.webclient).DownloadFile('http://nirbheek.in/files/binaries/ninja/win32/ninja.exe', 'C:\projects\meson\ninja.exe')
# Use the x86 python only when building for x86 for the cpython tests.
# For all other archs (including, say, arm), use the x64 python.
- - ps: (new-object net.webclient).DownloadFile('https://www.dropbox.com/s/bbzvepq85hv47x1/ninja.exe?dl=1', 'C:\projects\meson\ninja.exe')
- cmd: if %arch%==x86 (set MESON_PYTHON_PATH=C:\python34) else (set MESON_PYTHON_PATH=C:\python34-x64)
# Set paths and config for each build type.
diff --git a/.travis.yml b/.travis.yml
index 5b6e022..559b39c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -30,7 +30,9 @@ matrix:
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ninja python3; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python3; fi
+ # Use a Ninja with QuLogic's patch: https://github.com/ninja-build/ninja/issues/1219
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir -p $HOME/tools; curl -L http://nirbheek.in/files/binaries/ninja/macos/ninja -o $HOME/tools/ninja; chmod +x $HOME/tools/ninja; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull jpakkane/mesonci:zesty; fi
# We need to copy the current checkout inside the Docker container,
@@ -45,6 +47,6 @@ script:
ci_env=`bash <(curl -s https://codecov.io/env)`
docker run $ci_env -v ${PWD}/.coverage:/root/.coverage \
withgit \
- /bin/sh -c "cd /root && CC=$CC CXX=$CXX OBJC=$CC OBJCXX=$CXX ./run_tests.py -- $MESON_ARGS && chmod -R a+rwX .coverage"
+ /bin/sh -c "cd /root && mkdir -p tools; wget -c http://nirbheek.in/files/binaries/ninja/linux-amd64/ninja -O /root/tools/ninja; chmod +x /root/tools/ninja; CC=$CC CXX=$CXX OBJC=$CC OBJCXX=$CXX PATH=/root/tools:$PATH MESON_FIXED_NINJA=1 ./run_tests.py -- $MESON_ARGS && chmod -R a+rwX .coverage"
fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) OBJC=$CC OBJCXX=$CXX ./run_tests.py --backend=ninja -- $MESON_ARGS ; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) OBJC=$CC OBJCXX=$CXX PATH=$HOME/tools:$PATH MESON_FIXED_NINJA=1 ./run_tests.py --backend=ninja -- $MESON_ARGS ; fi
diff --git a/ci/appveyor-install.bat b/ci/appveyor-install.bat
index becc80a..9eddeac 100644
--- a/ci/appveyor-install.bat
+++ b/ci/appveyor-install.bat
@@ -1,5 +1,7 @@
set CACHE=C:\cache
set CYGWIN_MIRROR="http://cygwin.mirror.constant.com"
+set CYGWIN_ADDITIONAL_REPO="http://www.dronecode.org.uk/cygwin/"
+set CYGWIN_ADDITIONAL_REPO_KEY="http://www.dronecode.org.uk/cygwin/dronecode.gpg"
if _%arch%_ == _x64_ set SETUP=setup-x86_64.exe && set CYGWIN_ROOT=C:\cygwin64
if _%arch%_ == _x86_ set SETUP=setup-x86.exe && set CYGWIN_ROOT=C:\cygwin
@@ -7,5 +9,5 @@ if _%arch%_ == _x86_ set SETUP=setup-x86.exe && set CYGWIN_ROOT=C:\cygwin
if not exist %CACHE% mkdir %CACHE%
echo Updating Cygwin and installing ninja and test prerequisites
-%CYGWIN_ROOT%\%SETUP% -qnNdO -R "%CYGWIN_ROOT%" -s "%CYGWIN_MIRROR%" -l "%CACHE%" -g -P "ninja,gcc-objc,gcc-objc++,libglib2.0-devel,zlib-devel,python3-pip"
+%CYGWIN_ROOT%\%SETUP% -qnNdO -R "%CYGWIN_ROOT%" -s "%CYGWIN_MIRROR%" -s "%CYGWIN_ADDITIONAL_REPO%" -K "%CYGWIN_ADDITIONAL_REPO_KEY%" -l "%CACHE%" -g -P "ninja,gcc-objc,gcc-objc++,libglib2.0-devel,zlib-devel,python3-pip"
echo Install done
diff --git a/contributing.txt b/contributing.txt
index c4809ec..094c5e6 100644
--- a/contributing.txt
+++ b/contributing.txt
@@ -58,7 +58,7 @@ These are bad because they would make Meson's DSL Turing complete. The
second feature is a Make backend.
The FAQ has specific information why these two features will not be
-added to Meson: https://github.com/mesonbuild/meson/wiki/FAQ
+added to Meson: http://mesonbuild.com/FAQ.html
Merge requests adding either of these two features will be automatically
rejected. Please save everyone's time (especially your own) and don't start
diff --git a/docs/markdown/Compiler-properties.md b/docs/markdown/Compiler-properties.md
index 5978b5d..06efff3 100644
--- a/docs/markdown/Compiler-properties.md
+++ b/docs/markdown/Compiler-properties.md
@@ -29,26 +29,9 @@ Compiler id
==
The compiler object has a method called `get_id`, which returns a
-lower case string describing the "family" of the compiler. It has one
-of the following values.
-
-| Value | Compiler family |
-| ----- | ---------------- |
-| gcc | The GNU Compiler Collection |
-| clang | The Clang compiler |
-| msvc | Microsoft Visual Studio |
-| intel | Intel compiler |
-| llvm | LLVM-based compiler (Swift, D) |
-| mono | Xamarin C# compiler |
-| dmd | D lang reference compiler |
-| rustc | Rust compiler |
-| valac | Vala compiler |
-| pathscale | The Pathscale Fortran compiler |
-| pgi | The Portland Fortran compiler |
-| sun | Sun Fortran compiler |
-| g95 | The G95 Fortran compiler |
-| open64 | The Open64 Fortran Compiler |
-| nagfor | The NAG Fortran compiler |
+lower case string describing the "family" of the compiler. See
+[reference tables](Reference-tables.md) for a list of supported
+compiler ids.
Does code compile?
==
diff --git a/docs/markdown/D.md b/docs/markdown/D.md
new file mode 100644
index 0000000..7b0d485
--- /dev/null
+++ b/docs/markdown/D.md
@@ -0,0 +1,89 @@
+---
+title: D
+short-description: Compiling D sources
+...
+
+# Compiling D applications
+
+Meson has support for compiling D programs. A minimal `meson.build` file for D looks like this:
+
+```meson
+project('myapp', 'd')
+
+executable('myapp', 'app.d')
+```
+
+## Compiling different versions
+
+If you are using the [version()](https://dlang.org/spec/version.html) feature for conditional compilation, you can use it using the `d_module_versions`
+target property:
+```meson
+project('myapp', 'd')
+executable('myapp', 'app.d', d_module_versions: ['Demo', 'FeatureA'])
+```
+
+## Using embedded unittests
+
+If you are using embedded [unittest functions](https://dlang.org/spec/unittest.html), your source code needs to be compiled twice, once in regular
+mode, and once with unittests active. This is done by setting the `d_unittest` target property to `true`.
+Meson will only ever pass the respective compiler's `-unittest` flag, and never have the compiler generate an empty main function.
+If you need that feature in a portable way, create an empty `main()` function for unittests yourself, since the GNU D compiler
+does not have this feature.
+
+This is an example for using D unittests with Meson:
+```meson
+project('myapp_tested', 'd')
+
+myapp_src = ['app.d', 'alpha.d', 'beta.d']
+executable('myapp', myapp_src)
+
+test_exe = executable('myapp_test', myapp_src, d_unittest: true)
+test('myapptest', test_exe)
+```
+
+# Compiling D libraries and installing them
+
+Building D libraries is a straightforward process, not different from how C libraries are built in Meson. You should generate a pkg-config file
+and install it, in order to make other software on the system find the dependency once it is installed.
+
+This is an example on how to build a D shared library:
+```meson
+project('mylib', 'd', version: '1.2.0')
+
+project_soversion = 0
+glib_dep = dependency('glib-2.0')
+
+my_lib = library('mylib',
+ ['src/mylib/libfunctions.d'],
+ dependencies: [glib_dep],
+ install: true,
+ version: meson.project_version(),
+ soversion: project_soversion,
+ d_module_versions: ['FeatureA', 'featureB']
+)
+pkgc.generate(name: 'mylib',
+ libraries: my_lib,
+ subdirs: 'd/mylib',
+ version: meson.project_version(),
+ description: 'A simple example D library.',
+ d_module_versions: ['FeatureA']
+)
+install_subdir('src/mylib/', install_dir: 'include/d/mylib/')
+```
+
+It is important to make the D sources install in a subdirectory in the include path, in this case `/usr/include/d/mylib/mylib`.
+All D compilers include the `/usr/include/d` directory by default, and if your library would be installed into `/usr/include/d/mylib`, there
+is a high chance that, when you compile your project again on a machine where you installed it, the compiler will prefer the old installed include over
+the new version in the source tree, leading to very confusing errors.
+
+This is an example of how to use the D library we just built and installed in an application:
+```meson
+project('myapp', 'd')
+
+mylib_dep = dependency('mylib', version: '>= 1.2.0')
+myapp_src = ['app.d', 'alpha.d', 'beta.d']
+executable('myapp', myapp_src, dependencies: [mylib_dep])
+```
+
+Please keep in mind that the library and executable would both need to be built with the exact same D compiler and D compiler version. The D ABI is not
+stable across compilers and their versions, and mixing compilers will lead to problems.
diff --git a/docs/markdown/Getting-meson.md b/docs/markdown/Getting-meson.md
index d654ff3..8664d61 100644
--- a/docs/markdown/Getting-meson.md
+++ b/docs/markdown/Getting-meson.md
@@ -5,7 +5,7 @@
Meson releases can be downloaded from the [GitHub release page].
Meson is also available in the [Python Package Index] and can be
-installed with <tt>pip3 install meson</tt>.
+installed with `pip3 install meson`.
The newest development code can be obtained directly from [Git]
diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md
index 3672761..99a9c8e 100644
--- a/docs/markdown/Gnome-module.md
+++ b/docs/markdown/Gnome-module.md
@@ -226,6 +226,7 @@ files and the second specifies the XML file name.
* `namespace`: namespace of the interface
* `object_manager`: *(Added 0.40.0)* if true generates object manager code
* `annotations`: *(Added 0.43.0)* list of lists of 3 strings for the annotation for `'ELEMENT', 'KEY', 'VALUE'`
+* `docbook`: *(Added 0.43.0)* prefix to generate `'PREFIX'-NAME.xml` docbooks
Returns an opaque object containing the source files. Add it to a top
level target's source list.
@@ -241,7 +242,8 @@ gdbus_src = gnome.gdbus_codegen('example-interface', 'com.example.Sample.xml',
namespace : 'Sample',
annotations : [
['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true']
- ]
+ ],
+ docbook : 'example-interface-doc'
)
```
diff --git a/docs/markdown/Pkgconfig-module.md b/docs/markdown/Pkgconfig-module.md
index 5a660fd..7f767f1 100644
--- a/docs/markdown/Pkgconfig-module.md
+++ b/docs/markdown/Pkgconfig-module.md
@@ -41,3 +41,5 @@ keyword arguments.
e.g. `datadir=${prefix}/share`. The names `prefix`, `libdir` and
`installdir` are reserved and may not be used.
- `version` a string describing the version of this library
+- `d_module_versions` a list of module version flags used when compiling
+ D sources referred to by this pkg-config file
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 34b473d..2025ab5 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -424,6 +424,10 @@ be passed to [shared and static libraries](#library).
- `override_options` takes an array of strings in the same format as
`project`'s `default_options` overriding the values of these options
for this target only, since 0.40.0
+- `d_import_dirs` list of directories to look in for string imports used
+ in the D programmling language
+- `d_unittest`, when set to true, the D modules are compiled in debug mode
+- `d_module_versions` list of module versions set when compiling D sources
The list of `sources`, `objects`, and `dependencies` is always
flattened, which means you can freely nest and add lists while
@@ -835,7 +839,7 @@ This function prints its argument to stdout.
The first argument to this function must be a string defining the name
of this project. It is followed by programming languages that the
project uses. Supported values for languages are `c`, `cpp` (for
-`C++`), `objc`, `objcpp`, `fortran`, `java`, `cs` (for `C#`) and
+`C++`), `d`, `objc`, `objcpp`, `fortran`, `java`, `cs` (for `C#`) and
`vala`. In versions before `0.40.0` you must have at least one
language listed.
@@ -1176,11 +1180,13 @@ the following methods.
Python](https://docs.python.org/3/library/os.path.html#os.path.join)
special-case absolute paths.
- `MESONINTROSPECT` contains the path to the `mesonintrospect`
- executable that corresponds to the `meson` executable that was used
- to configure the build. (This might be a different path then the
- first `mesonintrospect` executable found in `PATH`.) It can be used
- to query build configuration.
+ `MESONINTROSPECT` contains the path to the introspect command that
+ corresponds to the `meson` executable that was used to configure the
+ build. (This might be a different path then the first executable
+ found in `PATH`.) It can be used to query build configuration. Note
+ that the value may contain many parts, i.e. it may be `python3
+ /path/to/meson.py introspect`. The user is responsible for splitting
+ the string to an array if needed.
- `source_root()` returns a string with the absolute path to the
source root directory. Note: you should use the `files()` function
diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md
new file mode 100644
index 0000000..b604fb6
--- /dev/null
+++ b/docs/markdown/Reference-tables.md
@@ -0,0 +1,60 @@
+# Reference tables
+
+## Compiler ids
+
+These are return values of the `get_id` method in a compiler object.
+
+| Value | Compiler family |
+| ----- | ---------------- |
+| gcc | The GNU Compiler Collection |
+| clang | The Clang compiler |
+| msvc | Microsoft Visual Studio |
+| intel | Intel compiler |
+| llvm | LLVM-based compiler (Swift, D) |
+| mono | Xamarin C# compiler |
+| dmd | D lang reference compiler |
+| rustc | Rust compiler |
+| valac | Vala compiler |
+| pathscale | The Pathscale Fortran compiler |
+| pgi | The Portland Fortran compiler |
+| sun | Sun Fortran compiler |
+| g95 | The G95 Fortran compiler |
+| open64 | The Open64 Fortran Compiler |
+| nagfor | The NAG Fortran compiler |
+
+## Script environment variables
+
+| Value | Comment |
+| ----- | ------- |
+| MESON_SOURCE_ROOT | Absolute path to the source dir |
+| MESON_BUILD_ROOT | Absolute path to the build dir |
+| MESONINTROSPECT | Command to run to run the introspection command, may be of the form `python /path/to/meson introspect`, user is responsible for splitting the path if necessary. |
+| MESON_SUBDIR | Current subdirectory, only set for `run_command` |
+
+## CPU families
+
+These are returned by the `cpu_family` method of `build_machine`,
+`host_machine` and `target_machine`. For cross compilation they are
+set in the cross file.
+
+| Value | Comment |
+| ----- | ------- |
+| x86 | 32 bit x86 processor |
+| x86_64 | 64 bit x86 processor |
+| arm | 32 bit ARM processor |
+
+Any cpu family not listed in the above list is not guaranteed to
+remain stable in future releases.
+
+## Operating system names
+
+These are provided by the `.system()` method call.
+
+| Value | Comment |
+| ----- | ------- |
+| linux | |
+| darwin | Either OSX or iOS |
+| windows | Any version of Windows |
+
+Any string not listed above is not guaranteed to remain stable in
+future releases. \ No newline at end of file
diff --git a/docs/markdown/Videos.md b/docs/markdown/Videos.md
index ab128c6..5abfbe4 100644
--- a/docs/markdown/Videos.md
+++ b/docs/markdown/Videos.md
@@ -9,7 +9,7 @@ short-description: Videos about Meson
(from Linux.conf.au 2015 -- Auckland, New Zealand)
<div class="video-container">
-<iframe width="854" height="480" src="https://www.youtube.com/embed/KPi0AuVpxLI" frameborder="0" allowfullscreen></iframe>
+<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/KPi0AuVpxLI" allowfullscreen></iframe>
</div>
## Talks about design, goals behind Meson's multiplatform dependency system was held
@@ -17,7 +17,7 @@ short-description: Videos about Meson
(From Linux.conf.au 2016 -- Geelong, Australia)
<div class="video-container">
-<iframe width="854" height="480" src="https://www.youtube.com/embed/CTJtKtQ8R5k" frameborder="0" allowfullscreen></iframe>
+<iframe width="854" height="480" style="border:0;" src="https://www.youtube.com/embed/CTJtKtQ8R5k" allowfullscreen></iframe>
</div>
## Features and benefits of Meson's multiplatform support for building and dependencies]
@@ -25,7 +25,7 @@ short-description: Videos about Meson
(Libre Application Summit 2016 talk _New world, new tools_ explored further)
<div class="video-container">
-<iframe width="854" height="480" src="https://www.youtube.com/embed/0-gx1qU2pPo" frameborder="0" allowfullscreen></iframe>
+<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
@@ -33,5 +33,5 @@ short-description: Videos about 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>
+ <source src=http://mirror.onet.pl/pub/mirrors/video.fosdem.org/2014/H2215_Ferrer/Sunday/Introducing_the_Meson_build_system.webm>
</video>
diff --git a/docs/markdown/index.md b/docs/markdown/index.md
index 8e35a4d..81c17ff 100644
--- a/docs/markdown/index.md
+++ b/docs/markdown/index.md
@@ -13,7 +13,7 @@ The main design point of Meson is that every moment a developer spends writing o
## Features
* multiplatform support for Linux, OSX, Windows, GCC, Clang, Visual Studio and others
-* supported languages include C, C++, Fortran, Java, Rust
+* supported languages include C, C++, D, Fortran, Java, Rust
* build definitions in a very readable and user friendly non-Turing complete DSL
* cross compilation for many operating systems as well as bare metal
* optimized for extremely fast full and incremental builds without sacrificing correctness
@@ -24,10 +24,10 @@ The main design point of Meson is that every moment a developer spends writing o
There are two main methods of connecting with other Meson developers. The first one is the mailing list, which is hosted at [Google Groups](https://groups.google.com/forum/#!forum/mesonbuild).
-The second way is via IRC. The channel to use is <tt>#mesonbuild</tt> at [Freenode](https://freenode.net/).
+The second way is via IRC. The channel to use is `#mesonbuild` at [Freenode](https://freenode.net/).
## Development
-All development on Meson is done on [GitHub project](https://github.com/mesonbuild/meson). For further info look into the <tt>contributing.txt</tt> file that comes with Meson's source checkout.
+All development on Meson is done on [GitHub project](https://github.com/mesonbuild/meson). For further info look into the `contributing.txt` file that comes with Meson's source checkout.
You do not need to sign a CLA to contribute to Meson.
diff --git a/docs/sitemap.txt b/docs/sitemap.txt
index af8aede..89dfdbd 100644
--- a/docs/sitemap.txt
+++ b/docs/sitemap.txt
@@ -38,6 +38,7 @@ index.md
Windows-module.md
Java.md
Vala.md
+ D.md
IDE-integration.md
Custom-build-targets.md
Build-system-converters.md
@@ -47,6 +48,7 @@ index.md
Creating-OSX-packages.md
Creating-Linux-binaries.md
Reference-manual.md
+ Reference-tables.md
FAQ.md
Reproducible-builds.md
howtox.md
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 4dbf41c..97959b6 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -65,12 +65,12 @@ class ExecutableSerialisation:
self.capture = capture
class TestSerialisation:
- def __init__(self, name, suite, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env,
+ def __init__(self, name, suite, fname, is_cross_built, exe_wrapper, is_parallel, cmd_args, env,
should_fail, timeout, workdir, extra_paths):
self.name = name
self.suite = suite
self.fname = fname
- self.is_cross = is_cross
+ self.is_cross_built = is_cross_built
self.exe_runner = exe_wrapper
self.is_parallel = is_parallel
self.cmd_args = cmd_args
@@ -180,8 +180,9 @@ class Backend:
# target that the GeneratedList is used in
return os.path.join(self.get_target_private_dir(target), src)
- def get_unity_source_filename(self, target, suffix):
- return target.name + '-unity.' + suffix
+ def get_unity_source_file(self, target, suffix):
+ osrc = target.name + '-unity.' + suffix
+ return mesonlib.File.from_built_file(self.get_target_private_dir(target), osrc)
def generate_unity_files(self, target, unity_src):
abs_files = []
@@ -189,18 +190,15 @@ class Backend:
compsrcs = classify_unity_sources(target.compilers.values(), unity_src)
def init_language_file(suffix):
- unity_src_name = self.get_unity_source_filename(target, suffix)
- unity_src_subdir = self.get_target_private_dir_abs(target)
- outfilename = os.path.join(unity_src_subdir,
- unity_src_name)
- outfileabs = os.path.join(self.environment.get_build_dir(),
- outfilename)
+ unity_src = self.get_unity_source_file(target, suffix)
+ outfileabs = unity_src.absolute_path(self.environment.get_source_dir(),
+ self.environment.get_build_dir())
outfileabs_tmp = outfileabs + '.tmp'
abs_files.append(outfileabs)
outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp)
if not os.path.exists(outfileabs_tmp_dir):
os.makedirs(outfileabs_tmp_dir)
- result.append(mesonlib.File(True, unity_src_subdir, unity_src_name))
+ result.append(unity_src)
return open(outfileabs_tmp, 'w')
# For each language, generate a unity source file and return the list
@@ -257,11 +255,11 @@ class Backend:
else:
exe_cmd = [exe]
exe_needs_wrapper = False
- is_cross = exe_needs_wrapper and \
+ is_cross_built = exe_needs_wrapper and \
self.environment.is_cross_build() and \
self.environment.cross_info.need_cross_compiler() and \
self.environment.cross_info.need_exe_wrapper()
- if is_cross:
+ if is_cross_built:
exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None)
else:
exe_wrapper = None
@@ -270,7 +268,7 @@ class Backend:
else:
extra_paths = []
es = ExecutableSerialisation(basename, exe_cmd, cmd_args, env,
- is_cross, exe_wrapper, workdir,
+ is_cross_built, exe_wrapper, workdir,
extra_paths, capture)
pickle.dump(es, f)
return exe_data
@@ -310,13 +308,35 @@ class Backend:
return result
def object_filename_from_source(self, target, source, is_unity):
- if isinstance(source, mesonlib.File):
- source = source.fname
+ assert isinstance(source, mesonlib.File)
+ build_dir = self.environment.get_build_dir()
+ rel_src = source.rel_to_builddir(self.build_to_src)
# foo.vala files compile down to foo.c and then foo.c.o, not foo.vala.o
- if source.endswith(('.vala', '.gs')):
+ if rel_src.endswith(('.vala', '.gs')):
+ # See description in generate_vala_compile for this logic.
+ if source.is_built:
+ if os.path.isabs(rel_src):
+ rel_src = rel_src[len(build_dir) + 1:]
+ rel_src = os.path.relpath(rel_src, self.get_target_private_dir(target))
+ else:
+ rel_src = os.path.basename(rel_src)
if is_unity:
- return source[:-5] + '.c.' + self.environment.get_object_suffix()
- source = os.path.join(self.get_target_private_dir(target), source[:-5] + '.c')
+ return 'meson-generated_' + rel_src[:-5] + '.c.' + self.environment.get_object_suffix()
+ # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix.
+ source = 'meson-generated_' + rel_src[:-5] + '.c'
+ elif source.is_built:
+ if os.path.isabs(rel_src):
+ rel_src = rel_src[len(build_dir) + 1:]
+ targetdir = self.get_target_private_dir(target)
+ # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix.
+ source = 'meson-generated_' + os.path.relpath(rel_src, targetdir)
+ else:
+ if os.path.isabs(rel_src):
+ # Not from the source directory; hopefully this doesn't conflict with user's source files.
+ source = os.path.basename(rel_src)
+ else:
+ source = os.path.relpath(os.path.join(build_dir, rel_src),
+ os.path.join(self.environment.get_source_dir(), target.get_subdir()))
return source.replace('/', '_').replace('\\', '_') + '.' + self.environment.get_object_suffix()
def determine_ext_objs(self, target, extobj, proj_dir_to_build_root):
@@ -330,9 +350,8 @@ class Backend:
extobj.srclist[0])
# There is a potential conflict here, but it is unlikely that
# anyone both enables unity builds and has a file called foo-unity.cpp.
- osrc = self.get_unity_source_filename(extobj.target,
- comp.get_default_suffix())
- osrc = os.path.join(self.get_target_private_dir(extobj.target), osrc)
+ osrc = self.get_unity_source_file(extobj.target,
+ comp.get_default_suffix())
objname = self.object_filename_from_source(extobj.target, osrc, True)
objname = objname.replace('/', '_').replace('\\', '_')
objpath = os.path.join(proj_dir_to_build_root, targetdir, objname)
@@ -515,6 +534,10 @@ class Backend:
self.environment.cross_info.need_exe_wrapper()
if isinstance(exe, build.BuildTarget):
is_cross = is_cross and exe.is_cross
+ if isinstance(exe, dependencies.ExternalProgram):
+ # E.g. an external verificator or simulator program run on a generated executable.
+ # Can always be run.
+ is_cross = False
if is_cross:
exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None)
else:
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index bff173a..7088c1e 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -192,6 +192,9 @@ int dummy;
def generate(self, interp):
self.interpreter = interp
+ self.ninja_command = environment.detect_ninja(log=True)
+ if self.ninja_command is None:
+ raise MesonException('Could not detect Ninja v1.5 or newer')
outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename)
tempfilename = outfilename + '~'
with open(tempfilename, 'w') as outfile:
@@ -225,11 +228,10 @@ int dummy;
# http://clang.llvm.org/docs/JSONCompilationDatabase.html
def generate_compdb(self):
- ninja_exe = environment.detect_ninja()
pch_compilers = ['%s_PCH' % i for i in self.build.compilers]
native_compilers = ['%s_COMPILER' % i for i in self.build.compilers]
cross_compilers = ['%s_CROSS_COMPILER' % i for i in self.build.cross_compilers]
- ninja_compdb = [ninja_exe, '-t', 'compdb'] + pch_compilers + native_compilers + cross_compilers
+ ninja_compdb = [self.ninja_command, '-t', 'compdb'] + pch_compilers + native_compilers + cross_compilers
builddir = self.environment.get_build_dir()
try:
jsondb = subprocess.check_output(ninja_compdb, cwd=builddir)
@@ -1046,7 +1048,7 @@ int dummy;
if hasattr(i, 'fname'):
i = i.fname
if i.endswith('vala'):
- vapiname = dep.name + '.vapi'
+ vapiname = dep.vala_vapi
fullname = os.path.join(self.get_target_dir(dep), vapiname)
result.add(fullname)
break
@@ -2116,39 +2118,21 @@ rule FORTRAN_DEP_HACK
self.target_arg_cache[key] = commands
commands = CompilerArgs(commands.compiler, commands)
- if isinstance(src, mesonlib.File) and src.is_built:
- rel_src = os.path.join(src.subdir, src.fname)
- if os.path.isabs(rel_src):
- assert(rel_src.startswith(self.environment.get_build_dir()))
- rel_src = rel_src[len(self.environment.get_build_dir()) + 1:]
- abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
- elif isinstance(src, mesonlib.File):
+ build_dir = self.environment.get_build_dir()
+ if isinstance(src, File):
rel_src = src.rel_to_builddir(self.build_to_src)
- abs_src = src.absolute_path(self.environment.get_source_dir(),
- self.environment.get_build_dir())
+ if os.path.isabs(rel_src):
+ # Source files may not be from the source directory if they originate in source-only libraries,
+ # so we can't assert that the absolute path is anywhere in particular.
+ if src.is_built:
+ assert rel_src.startswith(build_dir)
+ rel_src = rel_src[len(build_dir) + 1:]
elif is_generated:
raise AssertionError('BUG: broken generated source file handling for {!r}'.format(src))
else:
- if isinstance(src, File):
- rel_src = src.rel_to_builddir(self.build_to_src)
- else:
- raise InvalidArguments('Invalid source type: {!r}'.format(src))
- abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
- if isinstance(src, File):
- if src.is_built:
- src_filename = os.path.join(src.subdir, src.fname)
- if os.path.isabs(src_filename):
- assert(src_filename.startswith(self.environment.get_build_dir()))
- src_filename = src_filename[len(self.environment.get_build_dir()) + 1:]
- else:
- src_filename = src.fname
- elif os.path.isabs(src):
- src_filename = os.path.basename(src)
- else:
- src_filename = src
- obj_basename = src_filename.replace('/', '_').replace('\\', '_')
+ raise InvalidArguments('Invalid source type: {!r}'.format(src))
+ obj_basename = self.object_filename_from_source(target, src, self.is_unity(target))
rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename)
- rel_obj += '.' + self.environment.get_object_suffix()
dep_file = compiler.depfile_for_object(rel_obj)
# Add MSVC debug file generation compile flags: /Fd /FS
@@ -2181,6 +2165,7 @@ rule FORTRAN_DEP_HACK
# outdir argument instead.
# https://github.com/mesonbuild/meson/issues/1348
if not is_generated:
+ abs_src = os.path.join(build_dir, rel_src)
extra_deps += self.get_fortran_deps(compiler, abs_src, target)
# Dependency hack. Remove once multiple outputs in Ninja is fixed:
# https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8
@@ -2583,11 +2568,8 @@ rule FORTRAN_DEP_HACK
default = 'default all\n\n'
outfile.write(default)
- ninja_command = environment.detect_ninja()
- if ninja_command is None:
- raise MesonException('Could not detect Ninja v1.6 or newer')
elem = NinjaBuildElement(self.all_outputs, 'meson-clean', 'CUSTOM_COMMAND', 'PHONY')
- elem.add_item('COMMAND', [ninja_command, '-t', 'clean'])
+ elem.add_item('COMMAND', [self.ninja_command, '-t', 'clean'])
elem.add_item('description', 'Cleaning.')
# Alias that runs the above-defined meson-clean target
self.create_target_alias('meson-clean', outfile)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index ec5ad7d..0bbc17c 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -80,39 +80,10 @@ class Vs2010Backend(backends.Backend):
super().__init__(build)
self.name = 'vs2010'
self.project_file_version = '10.0.30319.1'
- self.sources_conflicts = {}
self.platform_toolset = None
self.vs_version = '2010'
self.windows_target_platform_version = None
- def object_filename_from_source(self, target, source, is_unity=False):
- basename = os.path.basename(source.fname)
- filename_without_extension = '.'.join(basename.split('.')[:-1])
- if basename in self.sources_conflicts[target.get_id()]:
- # If there are multiple source files with the same basename, we must resolve the conflict
- # by giving each a unique object output file.
- filename_without_extension = '.'.join(source.fname.split('.')[:-1]).replace('/', '_').replace('\\', '_')
- return filename_without_extension + '.' + self.environment.get_object_suffix()
-
- def resolve_source_conflicts(self):
- for name, target in self.build.targets.items():
- if not isinstance(target, BuildTarget):
- continue
- conflicts = {}
- for s in target.get_sources():
- if hasattr(s, 'held_object'):
- s = s.held_object
- if not isinstance(s, File):
- continue
- basename = os.path.basename(s.fname)
- conflicting_sources = conflicts.get(basename, None)
- if conflicting_sources is None:
- conflicting_sources = []
- conflicts[basename] = conflicting_sources
- conflicting_sources.append(s)
- self.sources_conflicts[target.get_id()] = {name: src_conflicts for name, src_conflicts in conflicts.items()
- if len(src_conflicts) > 1}
-
def generate_custom_generator_commands(self, target, parent_node):
generator_output_files = []
custom_target_include_dirs = []
@@ -164,7 +135,6 @@ class Vs2010Backend(backends.Backend):
return generator_output_files, custom_target_output_files, custom_target_include_dirs
def generate(self, interp):
- self.resolve_source_conflicts()
self.interpreter = interp
target_machine = self.interpreter.builtin['target_machine'].cpu_family_method(None, None)
if target_machine.endswith('64'):
@@ -1004,9 +974,7 @@ class Vs2010Backend(backends.Backend):
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)
- basename = os.path.basename(s.fname)
- if basename in self.sources_conflicts[target.get_id()]:
- ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + self.object_filename_from_source(target, s)
+ ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + self.object_filename_from_source(target, s, False)
for s in gen_src:
inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s)
lang = Vs2010Backend.lang_from_source_file(s)
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 89689d7..5bf2874 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -36,6 +36,9 @@ known_basic_kwargs = {'install': True,
'vala_args': True,
'fortran_args': True,
'd_args': True,
+ 'd_import_dirs': True,
+ 'd_unittest': True,
+ 'd_module_versions': True,
'java_args': True,
'rust_args': True,
'link_args': True,
@@ -351,11 +354,11 @@ class BuildTarget(Target):
# 1. Pre-existing objects provided by the user with the `objects:` kwarg
# 2. Compiled objects created by and extracted from another target
self.process_objectlist(objects)
+ self.process_compilers()
self.process_kwargs(kwargs, environment)
self.check_unknown_kwargs(kwargs)
if not self.sources and not self.generated and not self.objects:
raise InvalidArguments('Build target %s has no sources.' % name)
- self.process_compilers()
self.validate_sources()
self.validate_cross_install(environment)
@@ -669,8 +672,23 @@ class BuildTarget(Target):
self.vala_header = kwargs.get('vala_header', self.name + '.h')
self.vala_vapi = kwargs.get('vala_vapi', self.name + '.vapi')
self.vala_gir = kwargs.get('vala_gir', None)
+
dlist = stringlistify(kwargs.get('d_args', []))
self.add_compiler_args('d', dlist)
+ dfeatures = dict()
+ dfeature_unittest = kwargs.get('d_unittest', False)
+ if dfeature_unittest:
+ dfeatures['unittest'] = dfeature_unittest
+ dfeature_versions = kwargs.get('d_module_versions', None)
+ if dfeature_versions:
+ dfeatures['versions'] = dfeature_versions
+ dfeature_import_dirs = kwargs.get('d_import_dirs', None)
+ if dfeature_import_dirs:
+ dfeatures['import_dirs'] = dfeature_import_dirs
+ if dfeatures:
+ if 'd' in self.compilers:
+ self.add_compiler_args('d', self.compilers['d'].get_feature_args(dfeatures))
+
self.link_args = flatten(kwargs.get('link_args', []))
for i in self.link_args:
if not isinstance(i, str):
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index a989704..9739f28 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -27,6 +27,20 @@ from .compilers import (
CompilerArgs,
)
+d_feature_args = {'gcc': {'unittest': '-funittest',
+ 'version': '-fversion',
+ 'import_dir': '-J'
+ },
+ 'llvm': {'unittest': '-unittest',
+ 'version': '-d-version',
+ 'import_dir': '-J'
+ },
+ 'dmd': {'unittest': '-unittest',
+ 'version': '-version',
+ 'import_dir': '-J'
+ }
+ }
+
class DCompiler(Compiler):
def __init__(self, exelist, version, is_cross):
self.language = 'd'
@@ -79,8 +93,42 @@ class DCompiler(Compiler):
# FIXME: Make this work for Windows, MacOS and cross-compiling
return get_gcc_soname_args(GCC_STANDARD, prefix, shlib_name, suffix, path, soversion, is_shared_module)
- def get_unittest_args(self):
- return ['-unittest']
+ def get_feature_args(self, kwargs):
+ res = []
+ if 'unittest' in kwargs:
+ unittest = kwargs.pop('unittest')
+ unittest_arg = d_feature_args[self.id]['unittest']
+ if not unittest_arg:
+ raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string())
+ if unittest:
+ res.append(unittest_arg)
+
+ if 'versions' in kwargs:
+ versions = kwargs.pop('versions')
+ if not isinstance(versions, list):
+ versions = [versions]
+
+ version_arg = d_feature_args[self.id]['version']
+ if not version_arg:
+ raise EnvironmentException('D compiler %s does not support the "feature versions" feature.' % self.name_string())
+ for v in versions:
+ res.append('{0}={1}'.format(version_arg, v))
+
+ if 'import_dirs' in kwargs:
+ import_dirs = kwargs.pop('import_dirs')
+ if not isinstance(import_dirs, list):
+ import_dirs = [import_dirs]
+
+ import_dir_arg = d_feature_args[self.id]['import_dir']
+ if not import_dir_arg:
+ raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string())
+ for d in import_dirs:
+ res.append('{0}{1}'.format(import_dir_arg, d))
+
+ if kwargs:
+ raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys()))
+
+ return res
def get_buildtype_linker_args(self, buildtype):
return []
@@ -217,9 +265,6 @@ class GnuDCompiler(DCompiler):
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
- def get_unittest_args(self):
- return ['-funittest']
-
class LLVMDCompiler(DCompiler):
def __init__(self, exelist, version, is_cross):
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 0b2a159..2f33a03 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -90,16 +90,19 @@ def find_coverage_tools():
genhtml_exe = None
return gcovr_exe, lcov_exe, genhtml_exe
-def detect_ninja(version='1.5'):
+def detect_ninja(version='1.5', log=False):
for n in ['ninja', 'ninja-build']:
try:
p, found = Popen_safe([n, '--version'])[0:2]
except (FileNotFoundError, PermissionError):
# Doesn't exist in PATH or isn't executable
continue
+ found = found.strip()
# Perhaps we should add a way for the caller to know the failure mode
# (not found or too old)
if p.returncode == 0 and mesonlib.version_compare(found, '>=' + version):
+ if log:
+ mlog.log('Found ninja-{} at {}'.format(found, shlex.quote(shutil.which(n))))
return n
def detect_native_windows_arch():
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 6083c61..fc0e4ee 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -752,10 +752,13 @@ class CompilerHolder(InterpreterObject):
return self.compiler.symbols_have_underscore_prefix(self.environment)
def unittest_args_method(self, args, kwargs):
- # At time, only D compilers have this feature.
- if not hasattr(self.compiler, 'get_unittest_args'):
- raise InterpreterException('This {} compiler has no unittest arguments.'.format(self.compiler.get_display_language()))
- return self.compiler.get_unittest_args()
+ '''
+ This function is deprecated and should not be used.
+ It can be removed in a future version of Meson.
+ '''
+ if not hasattr(self.compiler, 'get_feature_args'):
+ raise InterpreterException('This {} compiler has no feature arguments.'.format(self.compiler.get_display_language()))
+ return self.compiler.get_feature_args({'unittest': 'true'})
def has_member_method(self, args, kwargs):
if len(args) != 2:
@@ -1249,6 +1252,9 @@ pch_kwargs = set(['c_pch', 'cpp_pch'])
lang_arg_kwargs = set(['c_args',
'cpp_args',
'd_args',
+ 'd_import_dirs',
+ 'd_unittest',
+ 'd_module_versions',
'fortran_args',
'java_args',
'objc_args',
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 4862e23..d03e5a2 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -215,6 +215,9 @@ def is_osx():
def is_linux():
return platform.system().lower() == 'linux'
+def is_haiku():
+ return platform.system().lower() == 'haiku'
+
def is_windows():
platname = platform.system().lower()
return platname == 'windows' or 'mingw' in platname
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index ec2bc58..1657ddd 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -121,13 +121,12 @@ class MesonApp:
priv_dir = os.path.join(build_dir, 'meson-private/coredata.dat')
if os.path.exists(priv_dir):
if not handshake:
- print('''Trying to run Meson on a build directory that has already been configured.
-If you want to build it, just run your build command (e.g. ninja) inside the
-build directory. Meson will autodetect any changes in your setup and regenerate
-itself as required. Though it shouldn't be necessary, running ninja reconfigure
-will force Meson to regenerate the build files.
-
-If you want to change option values, use meson configure instead.''')
+ print('Directory already configured, exiting Meson. Just run your build command\n'
+ '(e.g. ninja) and Meson will regenerate as necessary. If ninja fails, run ninja\n'
+ 'reconfigure to force Meson to regenerate.\n'
+ '\nIf build failures persist, manually wipe your build directory to clear any\n'
+ 'stored system data.\n'
+ '\nTo change option values, run meson configure instead.')
sys.exit(0)
else:
if handshake:
@@ -341,7 +340,7 @@ def run(args, mainfile=None):
dir2 = '.'
try:
if mainfile is None:
- sys.exit('I iz broken. Sorry.')
+ raise AssertionError('I iz broken. Sorry.')
app = MesonApp(dir1, dir2, mainfile, handshake, options, sys.argv)
except Exception as e:
# Log directory does not exist, so just print
@@ -357,7 +356,11 @@ def run(args, mainfile=None):
mlog.log(mlog.red('\nMeson encountered an error in file %s, line %d, column %d:' % (e.file, e.lineno, e.colno)))
else:
mlog.log(mlog.red('\nMeson encountered an error:'))
+ # Error message
mlog.log(e)
+ # Path to log file
+ logfile = os.path.join(app.build_dir, environment.Environment.log_dir, mlog.log_fname)
+ mlog.log("\nA full log can be found at", mlog.bold(logfile))
if os.environ.get('MESON_FORCE_BACKTRACE'):
raise
else:
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
index 659c8f5..18c1e6a 100644
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -22,11 +22,12 @@ colorize_console = platform.system().lower() != 'windows' and os.isatty(sys.stdo
os.environ.get('TERM') != 'dumb'
log_dir = None
log_file = None
+log_fname = 'meson-log.txt'
def initialize(logdir):
global log_dir, log_file
log_dir = logdir
- log_file = open(os.path.join(logdir, 'meson-log.txt'), 'w', encoding='utf8')
+ log_file = open(os.path.join(logdir, log_fname), 'w', encoding='utf8')
def shutdown():
global log_file
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index cb8f560..fcdd193 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -680,6 +680,11 @@ class GnomeModule(ExtensionModule):
source_str = '@@'.join(sources)
langs = mesonlib.stringlistify(kwargs.pop('languages', []))
+ if langs:
+ mlog.log(mlog.red('DEPRECATION:'), '''The "languages" argument of gnome.yelp() is deprecated.
+Use a LINGUAS file in the sources directory instead.
+This will become a hard error in the future.''')
+
media = mesonlib.stringlistify(kwargs.pop('media', []))
symlinks = kwargs.pop('symlink_media', True)
@@ -850,7 +855,8 @@ class GnomeModule(ExtensionModule):
return []
- @permittedKwargs({'interface_prefix', 'namespace', 'object_manager', 'build_by_default', 'annotations'})
+ @permittedKwargs({'interface_prefix', 'namespace', 'object_manager', 'build_by_default',
+ 'annotations', 'docbook'})
def gdbus_codegen(self, state, args, kwargs):
if len(args) != 2:
raise MesonException('Gdbus_codegen takes two arguments, name and xml file.')
@@ -864,6 +870,8 @@ class GnomeModule(ExtensionModule):
cmd += ['--c-namespace', kwargs.pop('namespace')]
if kwargs.get('object_manager', False):
cmd += ['--c-generate-object-manager']
+ if 'docbook' in kwargs:
+ cmd += ['--generate-docbook', kwargs.pop('docbook')]
# Annotations are a bit ugly in that they are a list of lists of strings...
annotations = kwargs.pop('annotations', [])
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 0a0498c..a7a35d5 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -121,7 +121,7 @@ class PkgConfigModule(ExtensionModule):
@permittedKwargs({'libraries', 'version', 'name', 'description', 'filebase',
'subdirs', 'requires', 'requires_private', 'libraries_private',
- 'install_dir', 'extra_cflags', 'variables', 'url'})
+ 'install_dir', 'extra_cflags', 'variables', 'url', 'd_module_versions'})
def generate(self, state, args, kwargs):
if len(args) > 0:
raise mesonlib.MesonException('Pkgconfig_gen takes no positional arguments.')
@@ -148,6 +148,12 @@ class PkgConfigModule(ExtensionModule):
conflicts = mesonlib.stringlistify(kwargs.get('conflicts', []))
extra_cflags = mesonlib.stringlistify(kwargs.get('extra_cflags', []))
+ dversions = kwargs.get('d_module_versions', None)
+ if dversions:
+ compiler = state.environment.coredata.compilers.get('d')
+ if compiler:
+ extra_cflags.extend(compiler.get_feature_args({'versions': dversions}))
+
def parse_variable_list(stringlist):
reserved = ['prefix', 'libdir', 'includedir']
variables = []
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index 2520ae8..4e049a8 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -195,10 +195,10 @@ class TestHarness:
def run_single_test(self, wrap, test):
if test.fname[0].endswith('.jar'):
cmd = ['java', '-jar'] + test.fname
- elif not test.is_cross and run_with_mono(test.fname[0]):
+ elif not test.is_cross_built and run_with_mono(test.fname[0]):
cmd = ['mono'] + test.fname
else:
- if test.is_cross:
+ if test.is_cross_built:
if test.exe_runner is None:
# Can not run test on cross compiled executable
# because there is no execute wrapper.
@@ -224,7 +224,7 @@ class TestHarness:
child_env.update(test.env)
if len(test.extra_paths) > 0:
- child_env['PATH'] += os.pathsep.join([''] + test.extra_paths)
+ child_env['PATH'] = os.pathsep.join(test.extra_paths + ['']) + child_env['PATH']
# If MALLOC_PERTURB_ is not set, or if it is set to an empty value,
# (i.e., the test or the environment don't explicitly set it), set
diff --git a/mesonbuild/scripts/yelphelper.py b/mesonbuild/scripts/yelphelper.py
index 978a870..ab99267 100644
--- a/mesonbuild/scripts/yelphelper.py
+++ b/mesonbuild/scripts/yelphelper.py
@@ -18,6 +18,7 @@ import shutil
import argparse
from .. import mlog
from . import destdir_join
+from .gettext import read_linguas
parser = argparse.ArgumentParser()
parser.add_argument('command')
@@ -108,6 +109,9 @@ def run(args):
build_subdir = os.path.join(os.environ['MESON_BUILD_ROOT'], options.subdir)
abs_sources = [os.path.join(src_subdir, 'C', source) for source in sources]
+ if not langs:
+ langs = read_linguas(src_subdir)
+
if options.command == 'pot':
build_pot(src_subdir, options.project_id, sources)
elif options.command == 'update-po':
diff --git a/msi/createmsi.py b/msi/createmsi.py
index 921e2ac..13b4081 100755
--- a/msi/createmsi.py
+++ b/msi/createmsi.py
@@ -77,8 +77,16 @@ class PackageGenerator:
modules = [os.path.splitext(os.path.split(x)[1])[0] for x in glob(os.path.join('mesonbuild/modules/*'))]
modules = ['mesonbuild.modules.' + x for x in modules if not x.startswith('_')]
modulestr = ','.join(modules)
- subprocess.check_call(['c:\\Python\python.exe',
- 'c:\\Python\Scripts\\cxfreeze',
+ python = 'c:\\Python\python.exe'
+ if sys.executable:
+ python = sys.executable
+ cxfreeze = os.path.join(os.path.dirname(python), "Scripts", "cxfreeze")
+ if not os.path.isfile(cxfreeze):
+ print("ERROR: This script requires cx_freeze module")
+ sys.exit(1)
+
+ subprocess.check_call([python,
+ cxfreeze,
'--target-dir',
main_stage,
'--include-modules',
@@ -214,6 +222,9 @@ class PackageGenerator:
wixdir = 'c:\\Program Files\\Wix Toolset v3.11\\bin'
if not os.path.isdir(wixdir):
wixdir = 'c:\\Program Files (x86)\\Wix Toolset v3.11\\bin'
+ if not os.path.isdir(wixdir):
+ print("ERROR: This script requires WIX")
+ sys.exit(1)
subprocess.check_call([os.path.join(wixdir, 'candle'), self.main_xml])
subprocess.check_call([os.path.join(wixdir, 'light'),
'-ext', 'WixUIExtension',
diff --git a/run_tests.py b/run_tests.py
index efbdaaa..f74ff13 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -104,6 +104,12 @@ def get_backend_commands(backend, debug=False):
return cmd, clean_cmd, test_cmd, install_cmd, uninstall_cmd
def ensure_backend_detects_changes(backend):
+ # We're using a ninja with QuLogic's patch for sub-1s resolution timestamps
+ # and not running on HFS+ which only stores dates in seconds:
+ # https://developer.apple.com/legacy/library/technotes/tn/tn1150.html#HFSPlusDates
+ # FIXME: Upgrade Travis image to Apple FS when that becomes available
+ if 'MESON_FIXED_NINJA' in os.environ and not mesonlib.is_osx():
+ return
# This is needed to increase the difference between build.ninja's
# timestamp and the timestamp of whatever you changed due to a Ninja
# bug: https://github.com/ninja-build/ninja/issues/371
@@ -171,7 +177,7 @@ if __name__ == '__main__':
backend = Backend.xcode
break
# Running on a developer machine? Be nice!
- if not mesonlib.is_windows() and 'TRAVIS' not in os.environ:
+ if not mesonlib.is_windows() and not mesonlib.is_haiku() and 'TRAVIS' not in os.environ:
os.nice(20)
# Appveyor sets the `platform` environment variable which completely messes
# up building with the vs2010 and vs2015 backends.
diff --git a/test cases/common/159 reserved targets/meson.build b/test cases/common/159 reserved targets/meson.build
index 26572c0..24fd937 100644
--- a/test cases/common/159 reserved targets/meson.build
+++ b/test cases/common/159 reserved targets/meson.build
@@ -26,6 +26,9 @@ subdir('uninstall')
subdir('runtarget')
+py3 = import('python3').find_python()
+
custom_target('ctlist-test', output : 'out.txt',
- command : ['echo'], capture : true,
+ command : [py3, '-c', 'print("")'],
+ capture : true,
build_by_default : true)
diff --git a/test cases/common/160 duplicate source names/dir1/file.c b/test cases/common/160 duplicate source names/dir1/file.c
new file mode 100644
index 0000000..094e187
--- /dev/null
+++ b/test cases/common/160 duplicate source names/dir1/file.c
@@ -0,0 +1,16 @@
+extern int dir2;
+extern int dir2_dir1;
+extern int dir3;
+extern int dir3_dir1;
+
+int main() {
+ if (dir2 != 20)
+ return 1;
+ if (dir2_dir1 != 21)
+ return 1;
+ if (dir3 != 30)
+ return 1;
+ if (dir3_dir1 != 31)
+ return 1;
+ return 0;
+}
diff --git a/test cases/common/160 duplicate source names/dir1/meson.build b/test cases/common/160 duplicate source names/dir1/meson.build
new file mode 100644
index 0000000..00bc85d
--- /dev/null
+++ b/test cases/common/160 duplicate source names/dir1/meson.build
@@ -0,0 +1 @@
+sources += files('file.c')
diff --git a/test cases/common/160 duplicate source names/dir2/dir1/file.c b/test cases/common/160 duplicate source names/dir2/dir1/file.c
new file mode 100644
index 0000000..5aac8e5
--- /dev/null
+++ b/test cases/common/160 duplicate source names/dir2/dir1/file.c
@@ -0,0 +1 @@
+int dir2_dir1 = 21;
diff --git a/test cases/common/160 duplicate source names/dir2/file.c b/test cases/common/160 duplicate source names/dir2/file.c
new file mode 100644
index 0000000..6cf8d66
--- /dev/null
+++ b/test cases/common/160 duplicate source names/dir2/file.c
@@ -0,0 +1 @@
+int dir2 = 20;
diff --git a/test cases/common/160 duplicate source names/dir2/meson.build b/test cases/common/160 duplicate source names/dir2/meson.build
new file mode 100644
index 0000000..f116a02
--- /dev/null
+++ b/test cases/common/160 duplicate source names/dir2/meson.build
@@ -0,0 +1 @@
+sources += files('file.c', 'dir1/file.c')
diff --git a/test cases/common/160 duplicate source names/dir3/dir1/file.c b/test cases/common/160 duplicate source names/dir3/dir1/file.c
new file mode 100644
index 0000000..04667c2
--- /dev/null
+++ b/test cases/common/160 duplicate source names/dir3/dir1/file.c
@@ -0,0 +1 @@
+int dir3_dir1 = 31;
diff --git a/test cases/common/160 duplicate source names/dir3/file.c b/test cases/common/160 duplicate source names/dir3/file.c
new file mode 100644
index 0000000..d16d0a8
--- /dev/null
+++ b/test cases/common/160 duplicate source names/dir3/file.c
@@ -0,0 +1 @@
+int dir3 = 30;
diff --git a/test cases/common/160 duplicate source names/dir3/meson.build b/test cases/common/160 duplicate source names/dir3/meson.build
new file mode 100644
index 0000000..70ddbf2
--- /dev/null
+++ b/test cases/common/160 duplicate source names/dir3/meson.build
@@ -0,0 +1 @@
+lib = static_library('lib', 'file.c', 'dir1/file.c')
diff --git a/test cases/common/160 duplicate source names/meson.build b/test cases/common/160 duplicate source names/meson.build
new file mode 100644
index 0000000..cac5194
--- /dev/null
+++ b/test cases/common/160 duplicate source names/meson.build
@@ -0,0 +1,7 @@
+project('proj', 'c')
+
+sources = []
+subdir('dir1')
+subdir('dir2')
+subdir('dir3')
+executable('a.out', sources : sources, objects : lib.extract_all_objects())
diff --git a/test cases/d/9 features/app.d b/test cases/d/9 features/app.d
new file mode 100644
index 0000000..37cc1dd
--- /dev/null
+++ b/test cases/d/9 features/app.d
@@ -0,0 +1,51 @@
+
+import std.stdio;
+import std.array : split;
+import std.string : strip;
+
+auto getMenu ()
+{
+ auto foods = import ("food.txt").strip.split ("\n");
+ return foods;
+}
+
+auto getPeople ()
+{
+ return import ("people.txt").strip.split ("\n");
+}
+
+void main (string[] args)
+{
+ import std.array : join;
+ import core.stdc.stdlib : exit;
+
+ immutable request = args[1];
+ if (request == "menu") {
+ version (No_Menu) {
+ } else {
+ writeln ("On the menu: ", getMenu.join (", "));
+ exit (0);
+ }
+ }
+
+ version (With_People) {
+ if (request == "people") {
+ writeln ("People: ", getPeople.join (", "));
+ exit (0);
+ }
+ }
+
+ // we fail here
+ exit (1);
+}
+
+unittest
+{
+ writeln ("TEST");
+ import core.stdc.stdlib : exit;
+
+ writeln(getMenu);
+ assert (getMenu () == ["Spam", "Eggs", "Spam", "Baked Beans", "Spam", "Spam"]);
+
+ exit (0);
+}
diff --git a/test cases/d/9 features/data/food.txt b/test cases/d/9 features/data/food.txt
new file mode 100644
index 0000000..8275dd0
--- /dev/null
+++ b/test cases/d/9 features/data/food.txt
@@ -0,0 +1,6 @@
+Spam
+Eggs
+Spam
+Baked Beans
+Spam
+Spam
diff --git a/test cases/d/9 features/data/people.txt b/test cases/d/9 features/data/people.txt
new file mode 100644
index 0000000..abbae06
--- /dev/null
+++ b/test cases/d/9 features/data/people.txt
@@ -0,0 +1,5 @@
+Rick
+Morty
+Summer
+Beth
+Jerry
diff --git a/test cases/d/9 features/meson.build b/test cases/d/9 features/meson.build
new file mode 100644
index 0000000..9e63710
--- /dev/null
+++ b/test cases/d/9 features/meson.build
@@ -0,0 +1,29 @@
+project('D Features', 'd')
+
+# directory for data
+data_dir = join_paths(meson.current_source_dir(), 'data')
+
+e_plain = executable('dapp_menu',
+ 'app.d',
+ d_import_dirs: [data_dir]
+)
+test('dapp_menu_t_fail', e_plain, should_fail: true)
+test('dapp_menu_t', e_plain, args: ['menu'])
+
+# test feature versions and string imports
+e_versions = executable('dapp_versions',
+ 'app.d',
+ d_import_dirs: [data_dir],
+ d_module_versions: ['No_Menu', 'With_People']
+)
+test('dapp_versions_t_fail', e_versions, args: ['menu'], should_fail: true)
+test('dapp_versions_t', e_versions, args: ['people'])
+
+# test everything and unittests
+e_test = executable('dapp_test',
+ 'app.d',
+ d_import_dirs: [data_dir],
+ d_module_versions: ['No_Menu', 'With_People'],
+ d_unittest: true
+)
+test('dapp_test', e_test)
diff --git a/test cases/frameworks/13 yelp/help/LINGUAS b/test cases/frameworks/13 yelp/help/LINGUAS
new file mode 100644
index 0000000..173f978
--- /dev/null
+++ b/test cases/frameworks/13 yelp/help/LINGUAS
@@ -0,0 +1,2 @@
+de
+es
diff --git a/test cases/frameworks/13 yelp/help/meson.build b/test cases/frameworks/13 yelp/help/meson.build
index 85bc980..c8edd61 100644
--- a/test cases/frameworks/13 yelp/help/meson.build
+++ b/test cases/frameworks/13 yelp/help/meson.build
@@ -13,3 +13,9 @@ gnome.yelp('meson-symlink',
symlink_media: true,
languages: ['de', 'es'],
)
+
+gnome.yelp('meson-linguas',
+ sources: 'index.page',
+ media: 'media/test.txt',
+ symlink_media: false,
+)
diff --git a/test cases/frameworks/13 yelp/installed_files.txt b/test cases/frameworks/13 yelp/installed_files.txt
index 9fc097d..1f6522f 100644
--- a/test cases/frameworks/13 yelp/installed_files.txt
+++ b/test cases/frameworks/13 yelp/installed_files.txt
@@ -10,3 +10,9 @@ usr/share/help/es/meson-symlink/media/test.txt
usr/share/help/es/meson-symlink/index.page
usr/share/help/de/meson-symlink/index.page
usr/share/help/de/meson-symlink/media/test.txt
+usr/share/help/C/meson-linguas/index.page
+usr/share/help/C/meson-linguas/media/test.txt
+usr/share/help/es/meson-linguas/media/test.txt
+usr/share/help/es/meson-linguas/index.page
+usr/share/help/de/meson-linguas/index.page
+usr/share/help/de/meson-linguas/media/test.txt
diff --git a/test cases/frameworks/7 gnome/gdbus/meson.build b/test cases/frameworks/7 gnome/gdbus/meson.build
index f8a8eba..ea91caa 100644
--- a/test cases/frameworks/7 gnome/gdbus/meson.build
+++ b/test cases/frameworks/7 gnome/gdbus/meson.build
@@ -3,7 +3,8 @@ gdbus_src = gnome.gdbus_codegen('generated-gdbus', 'com.example.Sample.xml',
namespace : 'Sample',
annotations : [
['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true']
- ]
+ ],
+ docbook : 'generated-gdbus-doc'
)
gdbus_exe = executable('gdbus-test', 'gdbusprog.c',
diff --git a/test cases/vala/12 custom output/bar.vala b/test cases/vala/12 custom output/bar.vala
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/vala/12 custom output/bar.vala
diff --git a/test cases/vala/12 custom output/meson.build b/test cases/vala/12 custom output/meson.build
index ef6dbb5..c328959 100644
--- a/test cases/vala/12 custom output/meson.build
+++ b/test cases/vala/12 custom output/meson.build
@@ -3,7 +3,11 @@ project('valatest', 'c', 'vala')
glib = dependency('glib-2.0')
gobject = dependency('gobject-2.0')
-library('foo-1.0', 'foo.vala',
- vala_header: 'foo.h',
- vala_vapi: 'foo.vapi',
+foo_lib = library('foo-1.0', 'foo.vala',
+ vala_header: 'foo.h',
+ vala_vapi: 'foo.vapi',
+ dependencies: [glib, gobject])
+
+library('bar', 'bar.vala',
+ link_with: [foo_lib],
dependencies: [glib, gobject])
diff --git a/tools/cmake2meson.py b/tools/cmake2meson.py
index 0789a0c..5fe433c 100755
--- a/tools/cmake2meson.py
+++ b/tools/cmake2meson.py
@@ -26,7 +26,7 @@ class Token:
class Statement:
def __init__(self, name, args):
- self.name = name
+ self.name = name.lower()
self.args = args
class Lexer:
@@ -120,7 +120,10 @@ class Parser:
args.append(self.arguments())
self.expect('rparen')
arg = self.current
- if self.accept('string') \
+ if self.accept('comment'):
+ rest = self.arguments()
+ args += rest
+ elif self.accept('string') \
or self.accept('varexp') \
or self.accept('id'):
args.append(arg)
@@ -155,7 +158,7 @@ class Converter:
if i.tid == 'id':
res.append("'%s'" % i.value)
elif i.tid == 'varexp':
- res.append('%s' % i.value)
+ res.append('%s' % i.value.lower())
elif i.tid == 'string':
res.append("'%s'" % i.value)
else: