diff options
104 files changed, 875 insertions, 497 deletions
diff --git a/contributing.txt b/contributing.txt index cb71ca0..fc6e0ba 100644 --- a/contributing.txt +++ b/contributing.txt @@ -46,7 +46,7 @@ What not to contribute? There are a few things that people seem to want to add to Meson but which are not there by design and will not be added either. -The first one is defining your own functions or a generalised for loop. +The first one is defining your own functions or a generalized for loop. These are bad because they would make Meson's DSL Turing complete. The second feature is a Make backend. diff --git a/docs/markdown/Adding-arguments.md b/docs/markdown/Adding-arguments.md index 80f02d9..e049e82 100644 --- a/docs/markdown/Adding-arguments.md +++ b/docs/markdown/Adding-arguments.md @@ -1,3 +1,7 @@ +--- +short-description: Adding compiler arguments +... + # Adding arguments Often you need to specify extra compiler arguments. Meson provides two different ways to achieve this: global arguments and per-target arguments. @@ -11,7 +15,7 @@ Global compiler arguments are set with the following command. As an example you add_global_arguments('-DFOO=bar', language : 'c') ``` -This makes Meson add the define to all C compilations. Usually you would use this setting for flags for global settings. Note that for setting the C/C++ language standard (the `-std=c99` argument in Gcc), you would probably want to use a default option of the `project()` function. For details see the [reference manual](Reference manual). +This makes Meson add the define to all C compilations. Usually you would use this setting for flags for global settings. Note that for setting the C/C++ language standard (the `-std=c99` argument in GCC), you would probably want to use a default option of the `project()` function. For details see the [reference manual](Reference manual). Global arguments have certain limitations. They all have to be defined before any build targets are specified. This ensures that the global flags are the same for every single source file built in the entire project with one exception. Compilation tests that are run as part of your project configuration do not use these flags. The reason for that is that you may need to run a test compile with and without a given flag to determine your build setup. For this reason tests do not use these global arguments. diff --git a/docs/markdown/Adding-new-projects-to-wrapdb.md b/docs/markdown/Adding-new-projects-to-wrapdb.md index ceaa51f..e14e0ac 100644 --- a/docs/markdown/Adding-new-projects-to-wrapdb.md +++ b/docs/markdown/Adding-new-projects-to-wrapdb.md @@ -4,7 +4,7 @@ ## Overview -The wrap provider service is a simple web service that makes it easy to download build definitions for projects. It works in much the same way as Debian: we take the unaltered upstream source package and add a new build system to it as a patch. These build systems are stored as Git repositories on Github. They only contain build definition files. You may also think of them as an overlay to upstream source. +The wrap provider service is a simple web service that makes it easy to download build definitions for projects. It works in much the same way as Debian: we take the unaltered upstream source package and add a new build system to it as a patch. These build systems are stored as Git repositories on GitHub. They only contain build definition files. You may also think of them as an overlay to upstream source. ## Creator script @@ -16,7 +16,7 @@ Wrapped subprojects are used much like external dependencies. Thus they should h ## Adding new project to the Wrap provider service -Each project gets its own repo. It is initialised like this: +Each project gets its own repo. It is initialized like this: git init git add readme.txt @@ -37,13 +37,13 @@ Create a new branch whose name matches the upstream release number. git checkout master git checkout -b 1.0.0 git push origin 1.0.0 - (or from Github web page, remember to branch from master) + (or from GitHub web page, remember to branch from master) Branch names must fully match this regexp: `[a-z0-9._]+`. ## Adding a new release to an existing branch -Here is where the magic happens. Whenever a new commit is pushed into Github's project branch, a new wrap is generated with an incremented version number. All the old releases remain unaltered. New commits are always done via Github merge requests and must be reviewed by someone other than the submitter. +Here is where the magic happens. Whenever a new commit is pushed into GitHub's project branch, a new wrap is generated with an incremented version number. All the old releases remain unaltered. New commits are always done via GitHub merge requests and must be reviewed by someone other than the submitter. Note that your Git repo must *not* contain the subdirectory of the source release. That gets added automatically by the service. You also must *not* commit any source code from the original tarball into the wrap repository. @@ -61,7 +61,7 @@ First you need to fork the repository to your own page. Then you can create the git commit -a -m 'Created wrap files for libfoo-1.0.0.' git push origin 1.0.0 -Now you can file a merge request. Remember to file it against branch 1.0.0 rather than master. Github should do this automatically. +Now you can file a merge request. Remember to file it against branch 1.0.0 rather than master. GitHub should do this automatically. ## Changes to original source diff --git a/docs/markdown/Additionnal.md b/docs/markdown/Additional.md index 2fff488..2fff488 100644 --- a/docs/markdown/Additionnal.md +++ b/docs/markdown/Additional.md diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md index 64e2d38..6029a2c 100644 --- a/docs/markdown/Build-options.md +++ b/docs/markdown/Build-options.md @@ -1,3 +1,7 @@ +--- +short-description: Build options to configure project properties +... + # Build options Most non-trivial builds require user-settable options. As an example a program may have two different data backends that are selectable at build time. Meson provides for this by having a option definition file. Its name is `meson_options.txt` and it is placed at the root of your source tree. diff --git a/docs/markdown/Build-system-converters.md b/docs/markdown/Build-system-converters.md index f4ee501..18e7470 100644 --- a/docs/markdown/Build-system-converters.md +++ b/docs/markdown/Build-system-converters.md @@ -1,3 +1,7 @@ +--- +short-description: Converting other build systems to Meson +... + # Build system converters Moving from one build system into another includes a fair bit of work. To make things easier, Meson provides scripts to convert other build systems into Meson. At the time of writing, scripts for CMake and autotools exist. It can be found in the `tools` subdirectory in Meson's source tree. @@ -6,4 +10,4 @@ The scripts do not try to do a perfect conversion. This would be extremely diffi cmake2meson.py path/to/CMake/project/root -This command generates a skeleton Meson project definition that tries to mirror CMake's setup as close as possible. Once this is done, you need to go through these files manually and finalise the conversion. To make this task as simple as possible, the converter script will transfer all comments from the CMake definition into Meson definition. +This command generates a skeleton Meson project definition that tries to mirror CMake's setup as close as possible. Once this is done, you need to go through these files manually and finalize the conversion. To make this task as simple as possible, the converter script will transfer all comments from the CMake definition into Meson definition. diff --git a/docs/markdown/Build-targets.md b/docs/markdown/Build-targets.md index b30e33d..4153e97 100644 --- a/docs/markdown/Build-targets.md +++ b/docs/markdown/Build-targets.md @@ -13,7 +13,7 @@ project('shared lib', 'c') shared_library('mylib', 'source.c') ``` -In unix-like operating systems, shared libraries can be versioned. Meson supports this with keyword arguments. +In Unix-like operating systems, shared libraries can be versioned. Meson supports this with keyword arguments. ```meson project('shared lib', 'c') diff --git a/docs/markdown/Comparisons.md b/docs/markdown/Comparisons.md index ede3cf9..4ceb930 100644 --- a/docs/markdown/Comparisons.md +++ b/docs/markdown/Comparisons.md @@ -1,5 +1,5 @@ --- -title: Comparisions +title: Comparisons ... # Comparing Meson with other build systems # @@ -14,7 +14,7 @@ Excellent support for legacy Unix platforms, large selection of existing modules ### Cons ### -Needlessly slow, complicated, hard to use correctly, unreliable, painful to debug, ununderstandable for most people, poor support for non-Unix platforms (especially Windows). +Needlessly slow, complicated, hard to use correctly, unreliable, painful to debug, incomprehensible for most people, poor support for non-Unix platforms (especially Windows). ## CMake ## diff --git a/docs/markdown/Compiler-properties.md b/docs/markdown/Compiler-properties.md index 9d533cd..50615a1 100644 --- a/docs/markdown/Compiler-properties.md +++ b/docs/markdown/Compiler-properties.md @@ -10,7 +10,7 @@ Here we extract the C compiler. We could also have given the argument `cpp` to g ## System information -This is a bit complex and more throughly explained on the page on [cross compilation](Cross compilation). But if you just want to know the operating system your code will run on, issue this command: +This is a bit complex and more thoroughly explained on the page on [cross compilation](Cross compilation). But if you just want to know the operating system your code will run on, issue this command: ```meson host_machine.system() @@ -140,7 +140,7 @@ In older versions (<= 0.30) meson would error out if the size could not be deter Does a function exist? == -Just having a header does say anything about its contents. Sometimes you need to explicitly check if some function exists. This is how we would check whether the function `somefunc` exists in header `someheader.h` +Just having a header doesn't say anything about its contents. Sometimes you need to explicitly check if some function exists. This is how we would check whether the function `somefunc` exists in header `someheader.h` ```meson if compiler.has_function('somefunc', prefix : '#include<someheader.h>') diff --git a/docs/markdown/Conference-presentations.md b/docs/markdown/Conference-presentations.md index b6e725b..15e4396 100644 --- a/docs/markdown/Conference-presentations.md +++ b/docs/markdown/Conference-presentations.md @@ -1,17 +1,17 @@ # Conference presentations on Meson -- Fosdem 2014, [Introducing the Meson build system](http://video.fosdem.org/2014/H2215_Ferrer/Sunday/Introducing_the_Meson_build_system.webm) (jpakkane) +- FOSDEM 2014, [Introducing the Meson build system](https://video.fosdem.org/2014/H2215_Ferrer/Sunday/Introducing_the_Meson_build_system.webm) (jpakkane) - LCA 2015, [Making build systems not suck](https://www.youtube.com/watch?v=KPi0AuVpxLI) (jpakkane) -- Guadec 2015, [Improving the way Gnome apps are built](https://www.youtube.com/watch?v=wTf0NjjNwTU) (jpakkane) +- GUADEC 2015, [Improving the way Gnome apps are built](https://www.youtube.com/watch?v=wTf0NjjNwTU) (jpakkane) - GStreamer conference 2015, [Done in 6.0 seconds](https://gstconf.ubicast.tv/videos/done-in-60-seconds-a-new-build-system-for-gstreamer) (jpakkane) - LCA 2016, [Builds, dependencies and deployment in the modern multiplatform world](https://www.youtube.com/watch?v=CTJtKtQ8R5k&feature=youtu.be) (jpakkane) -- Guadec 2016, [Making your GNOME app compile 2.4x faster](https://media.ccc.de/v/44-making_your_gnome_app_compile_24x_faster) (nirbheek) +- GUADEC 2016, [Making your GNOME app compile 2.4x faster](https://media.ccc.de/v/44-making_your_gnome_app_compile_24x_faster) (nirbheek) - Libre Application Summit 2016, [New world, new tools](https://youtu.be/0-gx1qU2pPo) (jpakkane) -- Gstreamer conference 2016, [GStreamer Development on Windows and faster builds everywhere with Meson](https://gstconf.ubicast.tv/videos/gstreamer-development-on-windows-ans-faster-builds-everywhere-with-meson/) (tpm) +- GStreamer conference 2016, [GStreamer Development on Windows and faster builds everywhere with Meson](https://gstconf.ubicast.tv/videos/gstreamer-development-on-windows-ans-faster-builds-everywhere-with-meson/) (tpm) diff --git a/docs/markdown/Configuration.md b/docs/markdown/Configuration.md index 037bcbd..70649d7 100644 --- a/docs/markdown/Configuration.md +++ b/docs/markdown/Configuration.md @@ -1,3 +1,7 @@ +--- +short-description: Build-time configuration options +... + # Configuration If there are multiple configuration options, passing them through compiler flags becomes very burdensome. It also makes the configuration settings hard to inspect. To make things easier, Meson supports the generation of configure files. This feature is similar to one found in other build systems such as CMake. diff --git a/docs/markdown/Configuring-a-build-directory.md b/docs/markdown/Configuring-a-build-directory.md index e887e9e..c7aa913 100644 --- a/docs/markdown/Configuring-a-build-directory.md +++ b/docs/markdown/Configuring-a-build-directory.md @@ -1,3 +1,7 @@ +--- +short-description: Configuring a pre-generated build directory +... + # Configuring a build directory Often you want to change the settings of your build after it has been generated. For example you might want to change from a debug build into a release build, set custom compiler flags, change the build options provided in your `meson_options.txt` file and so on. diff --git a/docs/markdown/Continuous-Integration.md b/docs/markdown/Continuous-Integration.md index 1dff200..68d6138 100644 --- a/docs/markdown/Continuous-Integration.md +++ b/docs/markdown/Continuous-Integration.md @@ -1,6 +1,6 @@ -# Continous Integration +# Continuous Integration -Here you will find snippets to use Meson with various CI such as Travis and Appveyor. +Here you will find snippets to use Meson with various CI such as Travis and AppVeyor. Please [file an issue](https://github.com/mesonbuild/meson/issues/new) if these instructions don't work for you. @@ -33,8 +33,8 @@ script: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo FROM YOUR/REPO:yakkety > Dockerfile; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo ADD . /root >> Dockerfile; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker build -t withgit .; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true CC=$CC CXX=$CXX meson build && ninja -C build test"; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) meson build && ninja -C build test; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true CC=$CC CXX=$CXX meson builddir && ninja -C builddir test"; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) meson builddir && ninja -C builddir test; fi ``` ## AppVeyor for Windows @@ -67,11 +67,11 @@ install: build_script: - cmd: echo Building on %arch% with %compiler% - - cmd: PATH=%cd%;%MESON_PYTHON_PATH%;%PATH%; && python meson.py --backend=ninja build - - cmd: PATH=%cd%;%MESON_PYTHON_PATH%;%PATH%; && ninja -C build + - cmd: PATH=%cd%;%MESON_PYTHON_PATH%;%PATH%; && python meson.py --backend=ninja builddir + - cmd: PATH=%cd%;%MESON_PYTHON_PATH%;%PATH%; && ninja -C builddir test_script: - - cmd: PATH=%cd%;%MESON_PYTHON_PATH%;%PATH%; && ninja -C build test + - cmd: PATH=%cd%;%MESON_PYTHON_PATH%;%PATH%; && ninja -C builddir test ``` ## Travis without Docker @@ -96,7 +96,7 @@ install: - pip3 install meson script: - - meson build - - ninja -C build - - ninja -C build test + - meson builddir + - ninja -C builddir + - ninja -C builddir test ``` diff --git a/docs/markdown/Creating-Linux-binaries.md b/docs/markdown/Creating-Linux-binaries.md index 2d5da1c..13940b5 100644 --- a/docs/markdown/Creating-Linux-binaries.md +++ b/docs/markdown/Creating-Linux-binaries.md @@ -1,33 +1,37 @@ +--- +short-description: Creating universal Linux binaries +... + # Creating Linux binaries -Creating Linux binaries that can be downloaded and run on any distro (like .dmg packages for OSX or .exe installers for Windows) has traditionally been difficult. This is even more tricky if you want to use modern compilers and features, which is especially desired in game development. There is still no simple turn key solution for this problem but with a bit of setup it can be relatively straightforward. +Creating Linux binaries that can be downloaded and run on any distro (like .dmg packages for OSX or .exe installers for Windows) has traditionally been difficult. This is even more tricky if you want to use modern compilers and features, which is especially desired in game development. There is still no simple turn-key solution for this problem but with a bit of setup it can be relatively straightforward. ## Installing system and GCC First you need to do a fresh operating system install. You can use spare hardware, VirtualBox, cloud or whatever you want. Note that the distro you install must be *at least as old* as the oldest release you wish to support. Debian stable is usually a good choice, though immediately after its release you might want to use Debian oldstable or the previous Ubuntu LTS. The oldest supported version of CentOS is also a good choice. -Once you have installed the system, you need to install build dependencies for GCC. In Debian based distros this can be done with the following commands: +Once you have installed the system, you need to install build-dependencies for GCC. In Debian-based distros this can be done with the following commands: ```console -$ apt get build dep g++ -$ apt get install pkg config libgmp dev libmpfr dev libmpc dev +$ apt-get build-dep g++ +$ apt-get install pkg-config libgmp-dev libmpfr-dev libmpc-dev ``` -Then create a `src` subdirectory in your home directory. Copypaste the following into `install_gcc.sh` and execute it. +Then create a `src` subdirectory in your home directory. Copy-paste the following into `install_gcc.sh` and execute it. ```bash #!/bin/sh -wget ftp://ftp.fu berlin.de/unix/languages/gcc/releases/gcc 4.9.2/gcc 4.9.2.tar.bz2 -tar xf gcc 4.9.2.tar.bz2 +wget ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-4.9.2/gcc-4.9.2.tar.bz2 +tar xf gcc-4.9.2.tar.bz2 mkdir objdir cd objdir -../gcc 4.9.2/configure disable bootstrap prefix=${HOME}/devroot \ - disable multilib enable languages=c,c++ -make j 4 -make install strip -ln s gcc ${HOME}/devroot/bin/cc +../gcc-4.9.2/configure --disable-bootstrap --prefix=${HOME}/devroot \ + --disable-multilib --enable-languages=c,c++ +make -j 4 +make install-strip +ln -s gcc ${HOME}/devroot/bin/cc ``` Then finally add the following lines to your `.bashrc`. @@ -46,22 +50,22 @@ Old distros might have too old versions of some tools. For Meson this could incl ## Adding dependencies -You want to embed and statically link every dependency you can (especially C++ dependencies). Meson's [Wrap package manager might be of use here](Wrap dependency system manual). This is equivalent to what you would do on Windows, OSX, Android etc. Sometimes static linking is not possible. In these cases you need to copy the .so files inside your package. Let's use SDL2 as an example. First we download and install it as usual giving it our custom install prefix (that is, `./configure prefix=${HOME}/devroot`). This makes Meson's dependency detector pick it up automatically. +You want to embed and statically link every dependency you can (especially C++ dependencies). Meson's [Wrap package manager might be of use here](Wrap dependency system manual). This is equivalent to what you would do on Windows, OSX, Android etc. Sometimes static linking is not possible. In these cases you need to copy the .so files inside your package. Let's use SDL2 as an example. First we download and install it as usual giving it our custom install prefix (that is, `./configure --prefix=${HOME}/devroot`). This makes Meson's dependency detector pick it up automatically. ## Building and installing -Building happens in much the same way as normally. There are just two things to note. First, you must tell GCC to link the C++ standard library statically. If you don't then your app is guaranteed to break as different distros have binary incompatible C++ libraries. The second thing is that you need to point your install prefix to some empty staging area. Here's the meson command to do that: +Building happens in much the same way as normally. There are just two things to note. First, you must tell GCC to link the C++ standard library statically. If you don't then your app is guaranteed to break as different distros have binary-incompatible C++ libraries. The second thing is that you need to point your install prefix to some empty staging area. Here's the meson command to do that: ```console -$ LDFLAGS= static libstdc++ meson prefix=/tmp/myapp <other args> +$ LDFLAGS=-static-libstdc++ meson --prefix=/tmp/myapp <other args> ``` -The aim is to put the executable in `/tmp/myapp/bin` and shared libraries to `/tmp/myapp/lib`. The next thing you need is the embedder. It takes your dependencies (in this case only `libSDL2 2.0.so.0`) and copies them in the lib directory. Depending on your use case you can either copy the files by hand or write a script that parses the output of `ldd binary_file`. Be sure not to copy system libraries (`libc`, `libpthread`, `libm` etc). For an example, see the [sample project](https://github.com/jpakkane/meson/tree/master/manual%20tests/4%20standalone%20binaries). +The aim is to put the executable in `/tmp/myapp/bin` and shared libraries to `/tmp/myapp/lib`. The next thing you need is the embedder. It takes your dependencies (in this case only `libSDL2-2.0.so.0`) and copies them in the lib directory. Depending on your use case you can either copy the files by hand or write a script that parses the output of `ldd binary_file`. Be sure not to copy system libraries (`libc`, `libpthread`, `libm` etc). For an example, see the [sample project](https://github.com/jpakkane/meson/tree/master/manual%20tests/4%20standalone%20binaries). Make the script run during install with this: ```meson -meson.set_install_script('linux_bundler.sh') +meson.add_install_script('linux_bundler.sh') ``` ## Final steps diff --git a/docs/markdown/Creating-OSX-packages.md b/docs/markdown/Creating-OSX-packages.md index a2b462a..4a4612e 100644 --- a/docs/markdown/Creating-OSX-packages.md +++ b/docs/markdown/Creating-OSX-packages.md @@ -1,3 +1,7 @@ +--- +short-description: Tools to create OS X packages +... + # Creating OSX packages Meson does not have native support for building OSX packages but it does provide all the tools you need to create one yourself. The reason for this is that it is a very hard task to write a system that provides for all the different ways to do that but it is very easy to write simple scripts for each application. @@ -56,7 +60,7 @@ If you are not using any external libraries, this is all you need to do. You now As an example we are going to use the [SDL2](https://libsdl.org/) framework. In order to bundle it in our app, we first specify an installer script to run. ```meson -meson.set_install_script('install_script.sh') +meson.add_install_script('install_script.sh') ``` The install script does two things. First it copies the whole framework into our bundle. diff --git a/docs/markdown/Cross-compilation.md b/docs/markdown/Cross-compilation.md index b5df8b3..c6817eb 100644 --- a/docs/markdown/Cross-compilation.md +++ b/docs/markdown/Cross-compilation.md @@ -1,3 +1,7 @@ +--- +short-description: Setting up cross-compilation +... + # Cross compilation Meson has full support for cross compilation. Since cross compiling is more complicated than native building, @@ -13,7 +17,7 @@ This might be easier to understand through examples. Let's start with the regula Let's next look at the most common cross-compilation setup. Let's suppose you are on a 64 bit OSX machine and you are cross compiling a binary that will run on a 32 bit ARM Linux board. In this case your *build machine* is 64 bit OSX and both your *host* and *target machines* are 32 bit ARM Linux. This should be quite understandable as well. -It gets a bit trickier when we think about how the cross compiler was generated. It was built and it runs on a specific platform but the output it generates is for a different platfom. In this case *build* and *host machines* are the same, but *target machine* is different. +It gets a bit trickier when we think about how the cross compiler was generated. It was built and it runs on a specific platform but the output it generates is for a different platform. In this case *build* and *host machines* are the same, but *target machine* is different. The most complicated case is when you cross-compile a cross compiler. As an example you can, on a Linux machine, generate a cross compiler that runs on Windows but produces binaries on MIPS Linux. In this case *build machine* is x86 Linux, *host machine* is x86 Windows and *target machine* is MIPS Linux. This setup is known as the [Canadian Cross](https://en.wikipedia.org/wiki/Cross_compiler#Canadian_Cross). As a side note, be careful when reading cross compilation articles on Wikipedia or the net in general. It is very common for them to get build, host and target mixed up, even in consecutive sentences, which can leave you puzzled until you figure it out. diff --git a/docs/markdown/Custom-build-targets.md b/docs/markdown/Custom-build-targets.md index 0c34b1f..a425f8c 100644 --- a/docs/markdown/Custom-build-targets.md +++ b/docs/markdown/Custom-build-targets.md @@ -1,3 +1,7 @@ +--- +short-description: Build targets for custom languages or corner-cases +... + # Custom build targets While Meson tries to support as many languages and tools as possible, there is no possible way for it to cover all corner cases. For these cases it permits you to define custom build targets. Here is how one would use it. diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index c57b9d4..1851233 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -1,6 +1,10 @@ +--- +short-description: Dependencies for external libraries and frameworks +... + # Dependencies -Very few applications are fully self-contained, but rather they use external libraries and frameworks to do their work. Meson makes it very easy to find and use external dependencies. Here is how one would use the Zlib compression library. +Very few applications are fully self-contained, but rather they use external libraries and frameworks to do their work. Meson makes it very easy to find and use external dependencies. Here is how one would use the zlib compression library. ```meson zdep = dependency('zlib', version : '>=1.2.8') diff --git a/docs/markdown/Design-rationale.md b/docs/markdown/Design-rationale.md index 2f6068e..611b7f4 100644 --- a/docs/markdown/Design-rationale.md +++ b/docs/markdown/Design-rationale.md @@ -13,9 +13,9 @@ Those are pretty much universally despised. The most positive statement on build systems you can usually get (and it might require some coaxing) is something along the lines of *well, it's a terrible system, but all other options are even worse*. It is easy to see why this is the case. For starters, commonly used free build systems have obtuse syntaxes. They use for the most part global variables that are set in random locations so you can never really be sure what a given line of code does. They do strange and unpredictable things at every turn. -Let's illustrate this with a simple example. Suppose we want to run a program built with GNU Autotools under gdb. The instinctive thing to do is to just run `gdb programname`. The problem is that this may or may not work. In some cases the executable file is a binary whereas at other times it is a wrapper shell script that invokes the real binary which resides in a hidden subdirectory. Gdb invocation fails if the binary is a script but succeeds if it is not. The user has to remember the type of each one of his executables (which is an implementation detail of the build system) just to be able to debug them. Several other such pain points can be found in [this blog post](http://voices.canonical.com/jussi.pakkanen/2011/09/13/autotools/). +Let's illustrate this with a simple example. Suppose we want to run a program built with GNU Autotools under GDB. The instinctive thing to do is to just run `gdb programname`. The problem is that this may or may not work. In some cases the executable file is a binary whereas at other times it is a wrapper shell script that invokes the real binary which resides in a hidden subdirectory. GDB invocation fails if the binary is a script but succeeds if it is not. The user has to remember the type of each one of his executables (which is an implementation detail of the build system) just to be able to debug them. Several other such pain points can be found in [this blog post](http://voices.canonical.com/jussi.pakkanen/2011/09/13/autotools/). -Given these idiosyncrasies it is no wonder that most people don't want to have anything to do with build systems. They'll just copypaste code that works (somewhat) in one place to another and hope for the best. They actively go out of their way not to understand the system because the mere thought of it is repulsive. Doing this also provides a kind of inverse job security. If you don't know tool X, there's less chance of finding yourself responsible for its use in your organisation. Instead you get to work on more enjoyable things. +Given these idiosyncrasies it is no wonder that most people don't want to have anything to do with build systems. They'll just copy-paste code that works (somewhat) in one place to another and hope for the best. They actively go out of their way not to understand the system because the mere thought of it is repulsive. Doing this also provides a kind of inverse job security. If you don't know tool X, there's less chance of finding yourself responsible for its use in your organisation. Instead you get to work on more enjoyable things. This leads to a vicious circle. Since people avoid the tools and don't want to deal with them, very few work on improving them. The result is apathy and stagnation. @@ -46,7 +46,7 @@ A lot of free software projects can be used on non-free platforms such as Window ###5. Must not add complexity due to obsolete platforms### -Work on this build system started during the Christmas holidays of 2012. This provides a natural hard cutoff line of 2012/12/24. Any platform, tool or library that was not in active use at that time is explicitly not supported. These include unixes such as IRIX, SunOS, OSF-1, Ubuntu versions older than 12/10, GCC versions older than 4.7 and so on. If these old versions happen to work, great. If they don't, not a single line of code will be added to the system to work around their bugs. +Work on this build system started during the Christmas holidays of 2012. This provides a natural hard cutoff line of 2012/12/24. Any platform, tool or library that was not in active use at that time is explicitly not supported. These include Unixes such as IRIX, SunOS, OSF-1, Ubuntu versions older than 12/10, GCC versions older than 4.7 and so on. If these old versions happen to work, great. If they don't, not a single line of code will be added to the system to work around their bugs. ###6. Must be fast### @@ -69,7 +69,7 @@ The difference between the proposed DSL and existing ones is that the new one is A DSL is more work than the approach taken by SCons, which is to provide the system as a Python library. However it allows us to make the syntax more expressive and prevent certain types of bugs by e.g. making certain objects truly immutable. The end result is again the same: less work for the user. -The backend for Unix requires a bit more thought. The default choice would be Make. However it is extremely slow. It is not uncommon on large code bases for Make to take several minutes just to determine that nothing needs to be done. Instead of Make we use [Ninja](http://martine.github.com/ninja/), which is extremely fast. The backend code is abstracted away from the core, so other backends can be added with relatively little effort. +The backend for Unix requires a bit more thought. The default choice would be Make. However it is extremely slow. It is not uncommon on large code bases for Make to take several minutes just to determine that nothing needs to be done. Instead of Make we use [Ninja](https://ninja-build.org/), which is extremely fast. The backend code is abstracted away from the core, so other backends can be added with relatively little effort. Sample code -- @@ -93,7 +93,7 @@ sources = ['main.c', 'file1.c', 'file2.c', 'file3.c'] executable('program', sources : sourcelist) ``` -External depencencies are simple to use. +External dependencies are simple to use. ```meson project('external lib', 'c') diff --git a/docs/markdown/External-commands.md b/docs/markdown/External-commands.md index af19794..f597b0c 100644 --- a/docs/markdown/External-commands.md +++ b/docs/markdown/External-commands.md @@ -1,3 +1,7 @@ +--- +short-description: Running external commands +... + # External commands As a part of the software configuration, you may want to get extra data by running external commands. The basic syntax is the following. diff --git a/docs/markdown/FAQ.md b/docs/markdown/FAQ.md index 7c27ee3..cc13756 100644 --- a/docs/markdown/FAQ.md +++ b/docs/markdown/FAQ.md @@ -9,7 +9,7 @@ See also [How do I do X in Meson](howtox.md). When the name was originally chosen, there were two main limitations: there must not exist either a Debian package or a Sourceforge project of the given name. This ruled out tens of potential project names. At some point the name Gluon was considered. Gluons are elementary particles that hold protons and neutrons together, much like a build system's job is to take pieces of source code and a compiler and bind them to a complete whole. -Unfortunately this name was taken, too. Then the rest of physical elementary particles were examined and Meson was found to be available. +Unfortunately this name was taken, too. Then the rest of subatomic particles were examined and Meson was found to be available. ## What is the correct way to use threads (such as pthreads)? @@ -27,7 +27,7 @@ Starting from version 0.29.0, Meson is available from the [Python Package Index] $ pip3 install <your options here> meson ``` -If you don't have access to PyPi, that is not a problem either. Meson has been designed to be easily runnable from an extracted source tarball or even a git checkout. First you need to download Meson. Then use this command to set up you build instead of plain `meson`. +If you don't have access to PyPI, that is not a problem either. Meson has been designed to be easily runnable from an extracted source tarball or even a git checkout. First you need to download Meson. Then use this command to set up you build instead of plain `meson`. ```console $ /path/to/meson.py <options> @@ -102,17 +102,17 @@ Just use Ninja, you'll be happier that way. I guarantee it. A related question to this is *Why is Meson's configuration language not Turing-complete?* -There are many good reasons for this, most of which are summarized on this web page: [Against The Use Of Programming Languages in Configuration Files](http://taint.org/2011/02/18/001527a.html). +There are many good reasons for this, most of which are summarized on this web page: [Against The Use Of Programming Languages in Configuration Files](https://taint.org/2011/02/18/001527a.html). -In addition to those reasons, not exposing Python or any other "real" programming language makes it possible to port Meson's implementation to a different language. This might become necessary if, for example, Python turns out to be a performance bottleneck. This is an actual problem that has caused complications for GNU Autotools and Scons. +In addition to those reasons, not exposing Python or any other "real" programming language makes it possible to port Meson's implementation to a different language. This might become necessary if, for example, Python turns out to be a performance bottleneck. This is an actual problem that has caused complications for GNU Autotools and SCons. ## How do I do the equivalent of Libtools export-symbol and export-regex? -Either by using [gcc symbol visibility](https://gcc.gnu.org/wiki/Visibility) or by writing a [linker script](http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html). This has the added benefit that your symbol definitions are in a standalone file instead of being buried inside your build definitions. An example can be found [here](https://github.com/jpakkane/meson/tree/master/test%20cases/linuxlike/3%20linker%20script). +Either by using [GCC symbol visibility](https://gcc.gnu.org/wiki/Visibility) or by writing a [linker script](https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html). This has the added benefit that your symbol definitions are in a standalone file instead of being buried inside your build definitions. An example can be found [here](https://github.com/jpakkane/meson/tree/master/test%20cases/linuxlike/3%20linker%20script). ## My project works fine on Linux and MinGW but fails with MSVC due to a missing .lib file -With gcc, all symbols on shared libraries are exported automatically unless you specify otherwise. With MSVC no symbols are exported by default. If your shared library exports no symbols, MSVC will silently not produce an import library file leading to failures. The solution is to add symbol visibility definitions [as specified in GCC wiki](https://gcc.gnu.org/wiki/Visibility). +With GCC, all symbols on shared libraries are exported automatically unless you specify otherwise. With MSVC no symbols are exported by default. If your shared library exports no symbols, MSVC will silently not produce an import library file leading to failures. The solution is to add symbol visibility definitions [as specified in GCC wiki](https://gcc.gnu.org/wiki/Visibility). ## I added some compiler flags and now the build fails with weird errors. What is happening? @@ -138,7 +138,7 @@ You probably had a project that looked something like this: project('foobar', 'cpp') ``` -This defaults to `c++11` on Gcc compilers. Suppose you want to use `c++14` instead, so you change the definition to this: +This defaults to `c++11` on GCC compilers. Suppose you want to use `c++14` instead, so you change the definition to this: ```meson project('foobar', 'cpp', default_options : ['cpp_std=c++14']) diff --git a/docs/markdown/Feature-autodetection.md b/docs/markdown/Feature-autodetection.md index b6a4f41..65318ec 100644 --- a/docs/markdown/Feature-autodetection.md +++ b/docs/markdown/Feature-autodetection.md @@ -1,3 +1,7 @@ +--- +short-description: Auto-detection of features like ccache and code coverage +... + # Feature autodetection Meson is designed for high productivity. It tries to do as many things automatically as it possibly can. @@ -5,11 +9,11 @@ Meson is designed for high productivity. It tries to do as many things automatic CCache -- -[CCache](http://ccache.samba.org/) is a cache system designed to make compiling faster. When you run Meson for the first time for a given project, it checks if CCache is installed. If it is, Meson will use it automatically. +[CCache](https://ccache.samba.org/) is a cache system designed to make compiling faster. When you run Meson for the first time for a given project, it checks if CCache is installed. If it is, Meson will use it automatically. If you do not wish to use CCache for some reason, just specify your compiler with environment variables `CC` and/or `CXX` when first running Meson (remember that once specified the compiler can not be changed). Meson will then use the specified compiler without CCache. Coverage -- -When doing a code coverage build, Meson will check the existance of binaries `gcovr`, `lcov` and `genhtml`. If the first one is found, it will create targets called *coverage-text* and *coverage-xml*. If the latter two are found, it generates the target *coverage-html*. You can then generate coverage reports just by calling e.g. `ninja coverage-xml`. +When doing a code coverage build, Meson will check the existence of binaries `gcovr`, `lcov` and `genhtml`. If the first one is found, it will create targets called *coverage-text* and *coverage-xml*. If the latter two are found, it generates the target *coverage-html*. You can then generate coverage reports just by calling e.g. `ninja coverage-xml`. diff --git a/docs/markdown/Generating-sources.md b/docs/markdown/Generating-sources.md index 19213af..630b7e9 100644 --- a/docs/markdown/Generating-sources.md +++ b/docs/markdown/Generating-sources.md @@ -1,3 +1,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). @@ -19,7 +23,7 @@ mycomp = find_program('mycompiler') Custom targets can take zero or more input files and use them to generate one or more output files. Using a custom target, you can run this compiler at build time to generate the sources: ```meson -gen_src = custom_target('gen-output, +gen_src = custom_target('gen-output', input : ['somefile1.c', 'file2.c'] output : ['out.c', 'out.h'] command : [mycomp, '@INPUT@', diff --git a/docs/markdown/Getting-meson.md b/docs/markdown/Getting-meson.md index f28a7e2..c01a947 100644 --- a/docs/markdown/Getting-meson.md +++ b/docs/markdown/Getting-meson.md @@ -2,7 +2,7 @@ ## Downloading Meson -Meson releases can be downloaded from the [Github release page]. +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>. @@ -20,9 +20,9 @@ Depending on your platform and backend you wish to use, you might need the [Ninja executable]. Again, use your distro-provided version if possible. Otherwise download it from Ninja project's web site. - [Github release page]: https://github.com/jpakkane/meson/releases + [GitHub release page]: https://github.com/mesonbuild/meson/releases [Python Package Index]: https://pypi.python.org/pypi/meson/ - [Git]: https://github.com/jpakkane/meson + [Git]: https://github.com/mesonbuild/meson [Python's home page]: https://www.python.org/downloads/ [Ninja executable]: https://ninja-build.org/ diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md index af1e059..079dfcb 100644 --- a/docs/markdown/Gnome-module.md +++ b/docs/markdown/Gnome-module.md @@ -12,13 +12,19 @@ To use this module, just do: **`gnome = import('gnome')`**. The following functi ### gnome.compile_resources() -This function compiles resources specified in an XML file into code that can be embedded inside the main binary. Similar a build target it takes two positional arguments. The first one is the name of the resource and the second is the xml file containing the resource definitions. If the name is `foobar`, Meson will generate a header file called `foobar.h`, which you can then include in your sources. There are two keyword arguments. +This function compiles resources specified in an XML file into code that can be embedded inside the main binary. Similar a build target it takes two positional arguments. The first one is the name of the resource and the second is the XML file containing the resource definitions. If the name is `foobar`, Meson will generate a header file called `foobar.h`, which you can then include in your sources. -* `source_dir`: a list of subdirectories where the resource compiler should look up the files, relative to the location of the xml file +* `source_dir`: a list of subdirectories where the resource compiler should look up the files, relative to the location of the XML file * `c_name`: passed to the resource compiler as an argument after `--c-name` +* `dependencies`: extra targets to depend upon for building +* `export`: (*Added 0.37.0*) if true, export the symbols of the generated sources +* `gresource_bundle`: (*Added 0.37.0*) if true, output a `.gresource` file instead of source +* `install_header`: (*Added 0.37.0*) if true, install the header file +* `install`: (*Added 0.37.0*) if true, install the gresource file +* `install_dir`: (*Added 0.37.0*) location to install the header or bundle depending on previous options * `extra_args`: extra command line arguments to pass to the resource compiler -Returns an array of two elements which are: `[c_source, header_file]` +Returns an array containing: `[c_source, header_file]` or `[gresource_bundle]` ### gnome.generate_gir() @@ -97,17 +103,17 @@ Compiles the given XML schema into gdbus source code. Takes two positional argum Returns an opaque object containing the source files. Add it to a top level target's source list. -### gnome.compile_vapi() +### gnome.generate_vapi() -Creates a vapi file from gir. The first argument is the name of the library. +Creates a VAPI file from gir. The first argument is the name of the library. -* `sources`: the gir source to generate the vapi from -* `packages`: vapi packages that are depended upon +* `sources`: the gir source to generate the VAPI from +* `packages`: VAPI packages that are depended upon * `metadata_dirs`: extra directories to include for metadata files * `gir_dirs`: extra directories to include for gir files -* `vapi_dirs`: extra directories to include for vapi files +* `vapi_dirs`: extra directories to include for VAPI files -Returns a custom dependency that can be included when building other vapi or vala binaries. +Returns a custom dependency that can be included when building other VAPI or Vala binaries. *Added 0.36.0* @@ -128,7 +134,7 @@ This also creates two targets for translations `help-$project-update-po` and `he Compiles and installs gtkdoc documentation. Takes one positional arguments; The name of the module. -* `main_xml`: specifies the main xml file +* `main_xml`: specifies the main XML file * `main_sgml`: equal to `main_xml` * `src_dir`: include_directories to include * `dependencies`: a list of dependencies @@ -139,7 +145,7 @@ Compiles and installs gtkdoc documentation. Takes one positional arguments; The * `gobject_typesfile`: a list of type files * `fixxref_args`: a list of arguments to pass to `gtkdoc-fixxref` * `html_args` a list of arguments to pass to `gtkdoc-mkhtml` -* `html_assets`: a list of assets for the html pages +* `html_assets`: a list of assets for the HTML pages * `content_files`: a list of content files ### gnome.gtkdoc_html_dir() diff --git a/docs/markdown/IDE-integration.md b/docs/markdown/IDE-integration.md index 7e046c6..d2a3e9c 100644 --- a/docs/markdown/IDE-integration.md +++ b/docs/markdown/IDE-integration.md @@ -1,3 +1,7 @@ +--- +short-description: Meson's API to integrate Meson support into an IDE +... + # IDE integration Meson has exporters for Visual Studio and XCode, but writing a custom backend for every IDE out there is not a scalable approach. To solve this problem, Meson provides an API that makes it easy for any IDE or build tool to integrate Meson builds and provide an experience comparable to a solution native to the IDE. @@ -6,7 +10,7 @@ The basic tool for this is a script called `mesonintrospect.py`. Some distro pac The first thing to do when setting up a Meson project in an IDE is to select the source and build directories. For this example we assume that the source resides in an Eclipse-like directory called `workspace/project` and the build tree is nested inside it as `workspace/project/build`. First we initialise Meson by running the following command in the source directory. - meson build + meson builddir For the remainder of the document we assume that all commands are executed inside the build directory unless otherwise specified. @@ -24,7 +28,7 @@ In order to make code completion work, you need the compiler flags for each comp ninja -t commands foo -Note that if the target has dependencies (such as generated sources), then the commands for those show up in this list as well, so you need to do some filtering. Alternatively you can grab every command invocation in the [clang tools db](http://clang.llvm.org/docs/JSONCompilationDatabase.html) format that is written to a file called `compile_commands.json` in the build directory. +Note that if the target has dependencies (such as generated sources), then the commands for those show up in this list as well, so you need to do some filtering. Alternatively you can grab every command invocation in the [Clang tools db](https://clang.llvm.org/docs/JSONCompilationDatabase.html) format that is written to a file called `compile_commands.json` in the build directory. The next thing to display is the list of options that can be set. These include build type and so on. Here's how to extract them. @@ -32,7 +36,7 @@ The next thing to display is the list of options that can be set. These include To set the options, use the `mesonconf.py` binary. -Compilation and unit tests are done as usual by running the `ninja` and `ninja test` commands. A JSON formatted result log can be found in `workspace/project/build/meson-logs/testlog.json`. +Compilation and unit tests are done as usual by running the `ninja` and `ninja test` commands. A JSON formatted result log can be found in `workspace/project/builddir/meson-logs/testlog.json`. When these tests fail, the user probably wants to run the failing test in a debugger. To make this as integrated as possible, extract the test test setups with this command. diff --git a/docs/markdown/In-the-press.md b/docs/markdown/In-the-press.md index 6f6df46..aa6f2a8 100644 --- a/docs/markdown/In-the-press.md +++ b/docs/markdown/In-the-press.md @@ -4,5 +4,5 @@ This page lists cases where Meson has been presented in the press. * [Linux Magazin](http://www.linux-magazin.de/Ausgaben/2014/08/), in German, August 2014, and also later in [Linux Magazine](http://www.linux-magazine.com/Issues/2014/166/Meson-Build-System) in English * [Admin Magazine](http://www.admin-magazine.com/HPC/Articles/The-Meson-Build-System) -* [Phoronix](http://www.phoronix.com/scan.php?page=news_item&px=MTc1MDc) regarding compilation of Mesa3D +* [Phoronix](https://www.phoronix.com/scan.php?page=news_item&px=MTc1MDc) regarding compilation of Mesa3D * [CppCast](http://cppcast.com/2015/12/jussi-pakkanen/) interviewed Jussi about Meson for C++ development in 12/2015 diff --git a/docs/markdown/Include-directories.md b/docs/markdown/Include-directories.md index 949bf2c..c1d4ac1 100644 --- a/docs/markdown/Include-directories.md +++ b/docs/markdown/Include-directories.md @@ -1,3 +1,7 @@ +--- +short-description: Instructions on handling include directories +... + # Include directories Most `C`/`C++` projects have headers in different directories than sources. Thus you need to specify include directories. Let's assume that we are at some subdirectory and wish to add its `include` subdirectory to some target's search path. To create a include directory object we do this: diff --git a/docs/markdown/IndepthTutorial.md b/docs/markdown/IndepthTutorial.md index d67adf7..dd93f82 100644 --- a/docs/markdown/IndepthTutorial.md +++ b/docs/markdown/IndepthTutorial.md @@ -78,7 +78,7 @@ At this point we can return to the pkg-config generator line. All shared librari With these four files we are done. To configure, build and run the test suite, we just need to execute the following commands (starting at source tree root directory). ```console -$ meson build && cd build +$ meson builddir && cd builddir $ ninja $ ninja test ``` diff --git a/docs/markdown/Installing.md b/docs/markdown/Installing.md index 37590c1..3454d49 100644 --- a/docs/markdown/Installing.md +++ b/docs/markdown/Installing.md @@ -1,3 +1,7 @@ +--- +short-description: Installing targets +... + # Installing By default Meson will not install anything. Build targets can be installed by tagging them as installable in the definition. @@ -40,7 +44,7 @@ giving an absolute install path. install_data(sources : 'foo.dat', install_dir : '/etc') # -> /etc/foo.dat ``` -## Custom install behaviour ## +## Custom install behavior ## Sometimes you need to do more than just install basic targets. Meson makes this easy by allowing you to specify a custom script to execute at install time. As an example, here is a script that generates an empty file in a custom directory. @@ -56,7 +60,7 @@ As you can see, Meson sets up some environment variables to help you write your Telling Meson to run this script at install time is a one-liner. ```meson -meson.set_install_script('myscript.sh') +meson.add_install_script('myscript.sh') ``` The argument is the name of the script file relative to the current subdirectory. diff --git a/docs/markdown/Java.md b/docs/markdown/Java.md index 8501bdf..9b89304 100644 --- a/docs/markdown/Java.md +++ b/docs/markdown/Java.md @@ -1,5 +1,6 @@ --- title: Java +short-description: Compiling Java programs ... # Compiling Java applications diff --git a/docs/markdown/Localisation.md b/docs/markdown/Localisation.md index 9fde970..27181e5 100644 --- a/docs/markdown/Localisation.md +++ b/docs/markdown/Localisation.md @@ -1,8 +1,12 @@ +--- +short-description: Localization with GNU Gettext +... + # Localisation -Localising your application with GNU Gettext takes a little effort but is quite straightforward. This documentation assumes that you have a `po` subdirectory at your project root directory that contains all the localisation info. +Localising your application with GNU gettext takes a little effort but is quite straightforward. This documentation assumes that you have a `po` subdirectory at your project root directory that contains all the localisation info. -The first thing you need is a file called `POTFILES`. It lists all the source files that Gettext should scan in order to find strings to translate. The syntax of the file is one line per source file and the line must contain the relative path from source root. A sample POTFILES might look like this. +The first thing you need is a file called `POTFILES`. It lists all the source files that gettext should scan in order to find strings to translate. The syntax of the file is one line per source file and the line must contain the relative path from source root. A sample POTFILES might look like this. src/file1.c src/file2.c @@ -15,9 +19,9 @@ We also need to define an array of strings containing all the locales we want to langs = ['fi', 'de'] ``` -Then we need to generate the main pot file. Usually this is generated manually or exists already. If not, see later on how to generate it using Meson. The potfile can have any name but is usually the name of the Gettext package. Let's say the project is called *intltest*. In this case the corresponding pot file would be called `inltest.pot`. +Then we need to generate the main pot file. Usually this is generated manually or exists already. If not, see later on how to generate it using Meson. The potfile can have any name but is usually the name of the gettext package. Let's say the project is called *intltest*. In this case the corresponding pot file would be called `intltest.pot`. -For each language listed in the array above we need a corresponding `.po` file. This has to be generated manually, see the Gettext manual for details. Once we have all this, we can define the localisation to Meson with these lines. +For each language listed in the array above we need a corresponding `.po` file. This has to be generated manually, see the gettext manual for details. Once we have all this, we can define the localisation to Meson with these lines. ```meson i18n = import('i18n') @@ -25,7 +29,7 @@ langs = ['fi', 'de'] i18n.gettext('intltest', languages : langs) ``` -The first command imports the `i18n` module that provides Gettext features. The second line does the actual invocation. The first argument to the is the Gettext package name. This causes two things to happen. The first is that Meson will generate binary mo files and put them to their proper locations when doing an install. The second is that it creates a build rule to regenerate the main pot file. If you are using the Ninja backend, this is how you would invoke the rebuild. +The first command imports the `i18n` module that provides gettext features. The second line does the actual invocation. The first argument to the is the gettext package name. This causes two things to happen. The first is that Meson will generate binary mo files and put them to their proper locations when doing an install. The second is that it creates a build rule to regenerate the main pot file. If you are using the Ninja backend, this is how you would invoke the rebuild. ```console $ ninja intltest-pot diff --git a/docs/markdown/Meson-design-rationale:-A-proposal-for-a-better-cross-platform-build-system.md b/docs/markdown/Meson-design-rationale:-A-proposal-for-a-better-cross-platform-build-system.md deleted file mode 100644 index 9636238..0000000 --- a/docs/markdown/Meson-design-rationale:-A-proposal-for-a-better-cross-platform-build-system.md +++ /dev/null @@ -1,122 +0,0 @@ -# Meson design rationale: A proposal for a better cross platform build system - -_This document is the original design description for Meson. The syntax listed here does not necessarily correspond to the current status of Meson._ - --------- - -A software developer's most important tool is the editor. If you talk to coders about the editors they use, you are usually met with massive enthusiasm and praise. You will hear how Emacs is the greatest thing ever or how vi is so elegant or how Eclipse's integration features make you so much more productive. You can sense the enthusiasm and affection that the people feel towards these programs. - -The second most important tool, even more important than the compiler, is the build system. - -Those are pretty much universally despised. - -The most positive statement on build systems you can usually get (and it might require some coaxing) is something along the lines of *well, it's a terrible system, but all other options are even worse*. It is easy to see why this is the case. For starters, commonly used free build systems have obtuse syntaxes. They use for the most part global variables that are set in random locations so you can never really be sure what a given line of code does. They do strange and unpredictable things at every turn. - -Let's illustrate this with a simple example. Suppose we want to run a program built with GNU Autotools under gdb. The instinctive thing to do is to just run `gdb programname`. The problem is that this may or may not work. In some cases the executable file is a binary whereas at other times it is a wrapper shell script that invokes the real binary which resides in a hidden subdirectory. Gdb invocation fails if the binary is a script but succeeds if it is not. The user has to remember the type of each one of his executables (which is an implementation detail of the build system) just to be able to debug them. Several other such pain points can be found in [this blog post](http://voices.canonical.com/jussi.pakkanen/2011/09/13/autotools/). - -Given these idiosyncrasies it is no wonder that most people don't want to have anything to do with build systems. They'll just copypaste code that works (somewhat) in one place to another and hope for the best. They actively go out of their way not to understand the system because the mere thought of it is repulsive. Doing this also provides a kind of inverse job security. If you don't know tool X, there's less chance of finding yourself responsible for its use in your organisation. Instead you get to work on more enjoyable things. - -This leads to a vicious circle. Since people avoid the tools and don't want to deal with them, very few work on improving them. The result is apathy and stagnation. - -Can we do better? --- - -At its core, building C and C++ code is not a terribly difficult task. In fact, writing a text editor is a lot more complicated and takes more effort. Yet we have lots of very high quality editors but only few build systems with questionable quality and usability. - -So, in the grand tradition of own-itch-scratching, I decided to run a scientific experiment. The purpose of this experiment was to explore what would it take to build a "good" build system. What kind of syntax would suit this problem? What sort of problems would this application need to solve? What sort of solutions would be the most appropriate? - -To get things started, here is a list of requirements any modern cross-platform build system needs to provide. - -###1. Must be simple to use### - -One of the great virtues of Python is the fact that it is very readable. It is easy to see what a given block of code does. It is concise, clear and easy to understand. The proposed build system must be syntactically and semantically clean. Side effects, global state and interrelations must be kept at a minimum or, if possible, eliminated entirely. - -###2. Must do the right thing by default### - -Most builds are done by developers working on the code. Therefore the defaults must be tailored towards that use case. As an example the system shall build objects without optimization and with debug information. It shall make binaries that can be run directly from the build directory without linker tricks, shell scripts or magic environment variables. - -###3. Must enforce established best practices### - -There really is no reason to compile source code without the equivalent of `-Wall`. So enable it by default. A different kind of best practice is the total separation of source and build directories. All build artifacts must be stored in the build directory. Writing stray files in the source directory is not permitted under any circumstances. - -###4. Must have native support for platforms that are in common use### - -A lot of free software projects can be used on non-free platforms such as Windows or OSX. The system must provide native support for the tools of choice on those platforms. In practice this means native support for Visual Studio and XCode. Having said IDEs invoke external builder binaries does not count as native support. - -###5. Must not add complexity due to obsolete platforms### - -Work on this build system started during the Christmas holidays of 2012. This provides a natural hard cutoff line of 2012/12/24. Any platform, tool or library that was not in active use at that time is explicitly not supported. These include unixes such as IRIX, SunOS, OSF-1, Ubuntu versions older than 12/10, GCC versions older than 4.7 and so on. If these old versions happen to work, great. If they don't, not a single line of code will be added to the system to work around their bugs. - -###6. Must be fast### - -Running the configuration step on a moderate sized project must not take more than five seconds. Running the compile command on a fully up to date tree of 1000 source files must not take more than 0.1 seconds. - -###7. Must provide easy to use support for modern sw development features### - -An example is precompiled headers. Currently no free software build system provides native support for them. Other examples could include easy integration of Valgrind and unit tests, test coverage reporting and so on. - -###8. Must allow override of default values### - -Sometimes you just have to compile files with only given compiler flags and no others, or install files in weird places. The system must allow the user to do this if he really wants to. - -Overview of the solution --- - -Going over these requirements it becomes quite apparent that the only viable approach is roughly the same as taken by CMake: having a domain specific language to declare the build system. Out of this declaration a configuration is generated for the backend build system. This can be a Makefile, Visual Studio or XCode project or anything else. - -The difference between the proposed DSL and existing ones is that the new one is declarative. It also tries to work on a higher level of abstraction than existing systems. As an example, using external libraries in current build systems means manually extracting and passing around compiler flags and linker flags. In the proposed system the user just declares that a given build target uses a given external dependency. The build system then takes care of passing all flags and settings to their proper locations. This means that the user can focus on his own code rather than marshalling command line arguments from one place to another. - -A DSL is more work than the approach taken by SCons, which is to provide the system as a Python library. However it allows us to make the syntax more expressive and prevent certain types of bugs by e.g. making certain objects truly immutable. The end result is again the same: less work for the user. - -The backend for Unix requires a bit more thought. The default choice would be Make. However it is extremely slow. It is not uncommon on large code bases for Make to take several minutes just to determine that nothing needs to be done. Instead of Make we use [Ninja](http://martine.github.com/ninja/), which is extremely fast. The backend code is abstracted away from the core, so other backends can be added with relatively little effort. - -Sample code --- - -Enough design talk, let's get to the code. Before looking at the examples we would like to emphasize that this is not in any way the final code. It is proof of concept code that works in the system as it currently exists (February 2013), but may change at any time. - -Let's start simple. Here is the code to compile a single executable binary. - - project('compile one', 'c') - executable('program', 'prog.c')< - -This is about as simple as one can get. First you declare the project name and the languages it uses. Then you specify the binary to build and its sources. The build system will do all the rest. It will add proper suffixes (e.g. '.exe' on Windows), set the default compiler flags and so on. - -Usually programs have more than one source file. Listing them all in the function call can become unwieldy. That is why the system supports keyword arguments. They look like this. - - project('compile several', 'c') - sources = ['main.c', 'file1.c', 'file2.c', 'file3.c'] - executable('program', sources : sourcelist) - -External depencencies are simple to use. - -`project('external lib', 'c') -libdep = find_dep('extlibrary', required : true) -sources = ['main.c', 'file1.c', 'file2.c', 'file3.c'] -executable('program', sources : sourcelist, dep : libdep)` - -In other build systems you have to manually add the compile and link flags from external dependencies to targets. In this system you just declare that extlibrary is mandatory and that the generated program uses that. The build system does all the plumbing for you. - -Here's a slightly more complicated definition. It should still be understandable. - -`project('build library', 'c') -foolib = shared_library('foobar', sources : 'foobar.c',\ - install : true) -exe = executable('testfoobar', 'tester.c', link : foolib) -add_test('test library', exe)` - -First we build a shared library named foobar. It is marked installable, so running `ninja install` installs it to the library directory (the system knows which one so the user does not have to care). Then we build a test executable which is linked against the library. It will no tbe installed, but instead it is added to the list of unit tests, which can be run with the command `ninja test`. - -Above we mentioned precompiled headers as a feature not supported by other build systems. Here's how you would use them. - - project('pch demo', 'cxx') - executable('myapp', 'myapp.cpp', pch : 'pch/myapp.hh') - -The main reason other build systems can not provide pch support this easily is because they don't enforce certain best practices. Due to the way include paths work, it is impossible to provide pch support that always works with both in-source and out-of-source builds. Mandating separate build and source directories makes this and many other problems a lot easier. - -Get the code --- - -The code for this experiment can be found at [the Meson repository](https://sourceforge.net/p/meson/code/). It should be noted that it is not a build system. It is only a proposal for one. It does not work reliably yet. You probably should not use it as the build system of your project. - -All that said I hope that this experiment will eventually turn into a full blown build system. For that I need your help. Comments and especially patches are more than welcome. diff --git a/docs/markdown/Modules.md b/docs/markdown/Modules.md index e594383..c354169 100644 --- a/docs/markdown/Modules.md +++ b/docs/markdown/Modules.md @@ -1,3 +1,7 @@ +--- +short-description: Meson modules for common build operations +... + # Modules In addition to core language features, Meson also provides a module system aimed at providing helper methods for common build operations. Using modules is simple, first you import them: diff --git a/docs/markdown/Overview.md b/docs/markdown/Overview.md index b469d9a..537aa8f 100644 --- a/docs/markdown/Overview.md +++ b/docs/markdown/Overview.md @@ -17,6 +17,6 @@ Meson follows the overall structure of other popular build systems, such as CMak The directory that contains the source code is called the *source directory*. Correspondingly the directory where the output is written is called the *build directory*. In other build systems it is common to have these two be the same directory. This is called an *in-source build*. The case where the build directory is separate is called an *out-of-source build*. -What sets Meson apart from most build systems is that it enforces a separate build directory. All files created by the build system are put in the build directory. It is actually impossible to do an in-source build. For people used to building inside their source tree, this may seem like a needles complication. However there are several benefits to doing only out-of-source builds. These will be explained in the next chapter. +What sets Meson apart from most build systems is that it enforces a separate build directory. All files created by the build system are put in the build directory. It is actually impossible to do an in-source build. For people used to building inside their source tree, this may seem like a needless complication. However there are several benefits to doing only out-of-source builds. These will be explained in the next chapter. When the source code is built, a set of *unit tests* is usually run. They ensure that the program is working as it should. If it does, the build result can be *installed* after which it is ready for use. diff --git a/docs/markdown/Pkg-config-files.md b/docs/markdown/Pkg-config-files.md index bac90bc..dde4ac9 100644 --- a/docs/markdown/Pkg-config-files.md +++ b/docs/markdown/Pkg-config-files.md @@ -1,6 +1,6 @@ # Pkg config files -[Pkg-config](https://en.wikipedia.org/wiki/Pkg-config) is a way for shared libraries to declare the compiler flags needed to use them. There are two different ways of generating Pkg-config files in Meson. The first way is to build them manually with the `configure_files` command. The second way is to use Meson's built in Pkg-config file generator. The difference between the two is that the latter is very simple and meant for basic use cases. The former should be used when you need to provide a more customised solution. +[Pkg-config](https://en.wikipedia.org/wiki/Pkg-config) is a way for shared libraries to declare the compiler flags needed to use them. There are two different ways of generating Pkg-config files in Meson. The first way is to build them manually with the `configure_files` command. The second way is to use Meson's built in Pkg-config file generator. The difference between the two is that the latter is very simple and meant for basic use cases. The former should be used when you need to provide a more customized solution. In this document we describe the simple generator approach. It is used in the following way. diff --git a/docs/markdown/Pkgconfig-module.md b/docs/markdown/Pkgconfig-module.md index 81ca020..51fe6b2 100644 --- a/docs/markdown/Pkgconfig-module.md +++ b/docs/markdown/Pkgconfig-module.md @@ -1,6 +1,6 @@ # Pkgconfig module -This module is a simple generator for [pkg-config](http://pkg-config.freedesktop.org/) files. +This module is a simple generator for [pkg-config](https://pkg-config.freedesktop.org/) files. ## Usage diff --git a/docs/markdown/Porting-from-autotools.md b/docs/markdown/Porting-from-autotools.md index 7bd9efd..f9c9ad8 100644 --- a/docs/markdown/Porting-from-autotools.md +++ b/docs/markdown/Porting-from-autotools.md @@ -1,6 +1,6 @@ -# Porting from autotools +# Porting from Autotools -This page uses [appstream-glib](https://github.com/hughsie/appstream-glib/) as an example project. Appstream-Glib contains some libraries, gobject-introspection, tests, man pages, i18n, bash-completion with optional flags to build/notbuild support for some things. +This page uses [AppStream-glib](https://github.com/hughsie/appstream-glib/) as an example project. AppStream-Glib contains some libraries, GObject Introspection data, tests, man pages, i18n, bash-completion with optional flags to build/not build support for some things. Meson comes with a helper script `ac_converter` that you can use to convert the basic autoconf checks for your project. @@ -99,7 +99,7 @@ if gperf.found() endif ``` -### Finding pkgconfig modules +### Finding pkg-config modules `configure.ac`: diff --git a/docs/markdown/Precompiled-headers.md b/docs/markdown/Precompiled-headers.md index a7bcbf8..8498612 100644 --- a/docs/markdown/Precompiled-headers.md +++ b/docs/markdown/Precompiled-headers.md @@ -1,3 +1,7 @@ +--- +short-description: Using precompiled headers to reduce compilation time +... + # Precompiled headers Parsing header files of system libraries is surprisingly expensive. A typical source file has less than one thousand lines of code. In contrast the headers of large libraries can be tens of thousands of lines. This is especially problematic with C++, where header-only libraries are common and they may contain extremely complex code. This makes them slow to compile. @@ -17,7 +21,7 @@ In Meson, precompiled header files are always per-target. That is, the given pre Toggling the usage of precompiled headers -- -If you wish to compile your project without precompiled headers, you can configure it by running Meson with the `--disable-pch` flag. You can also toggle the use of pch in a configured build directory with the gui tool. You don't have to do any changes to the source code. Typically this is done to test whether your project compiles cleanly without pch (that is, checking that its #includes are in order) and working around compiler bugs. +If you wish to compile your project without precompiled headers, you can configure it by running Meson with the `--disable-pch` flag. You can also toggle the use of pch in a configured build directory with the GUI tool. You don't have to do any changes to the source code. Typically this is done to test whether your project compiles cleanly without pch (that is, checking that its #includes are in order) and working around compiler bugs. Using precompiled headers with GCC and derivatives -- @@ -40,7 +44,7 @@ executable('multilang', sources : srclist, Using precompiled headers with MSVC -- -MSVC is a bit trickier, because in addition to the header file, it also requires a correspongind source file. If your header is called `foo_pch.h`, the corresponding source file is usually called `foo_pch.cpp` and it resides in the same `pch` subdirectory as the header. Its contents are this: +MSVC is a bit trickier, because in addition to the header file, it also requires a corresponding source file. If your header is called `foo_pch.h`, the corresponding source file is usually called `foo_pch.cpp` and it resides in the same `pch` subdirectory as the header. Its contents are this: ```cpp #if !defined(_MSC_VER) @@ -57,6 +61,6 @@ executable('myexe', sources : srclist, cpp_pch : ['pch/foo_pch.h', 'pch/foo_pch.cpp']) ``` -This form will work with both gcc and msvc, because Meson knows that gcc does not need a `.cpp` file and thus just ignores it. +This form will work with both GCC and msvc, because Meson knows that GCC does not need a `.cpp` file and thus just ignores it. It should be noted that due to implementation details of the MSVC compiler, having precompiled headers for multiple languages in the same target is not guaranteed to work. diff --git a/docs/markdown/Quick-guide.md b/docs/markdown/Quick-guide.md index 3966084..5feccbc 100644 --- a/docs/markdown/Quick-guide.md +++ b/docs/markdown/Quick-guide.md @@ -12,7 +12,7 @@ Requirements Meson has two main dependencies. -* [Python 3](http://python.org) +* [Python 3](https://python.org) * [Ninja](https://github.com/ninja-build/ninja/) Ninja is only needed if you use the Ninja backend. Meson can also generate native VS and XCode project files. @@ -40,7 +40,7 @@ The most common use case of Meson is compiling code on a code base you are worki ```console $ cd /path/to/source/root -$ meson build && cd build +$ meson builddir && cd builddir $ ninja $ ninja test ``` @@ -58,10 +58,10 @@ Distro packagers usually want total control on the build flags used. Meson suppo ```console $ cd /path/to/source/root -$ CFLAGS=... CXXFLAGS=... LDFLAGS=.. meson --prefix /usr --buildtype=plain build -$ ninja -v -C build -$ ninja -C build test -$ DESTDIR=/path/to/staging/root ninja -C build install +$ CFLAGS=... CXXFLAGS=... LDFLAGS=.. meson --prefix /usr --buildtype=plain builddir +$ ninja -v -C builddir +$ ninja -C builddir test +$ DESTDIR=/path/to/staging/root ninja -C builddir install ```` The command line switch `--buildtype=plain` tells Meson not to add its own flags to the command line. This gives the packager total control on used flags. diff --git a/docs/markdown/RPM-module.md b/docs/markdown/RPM-module.md index f32b9ad..3939937 100644 --- a/docs/markdown/RPM-module.md +++ b/docs/markdown/RPM-module.md @@ -1,6 +1,6 @@ # RPM module -The RPM module can be used to create a sample rpm spec file for a Meson project. It autodetects installed files, dependencies and so on. Using it is very simple. At the very end of your Meson project (that is, the end of your toplevel `meson.build` file) add these two lines. +The RPM module can be used to create a sample rpm spec file for a Meson project. It autodetects installed files, dependencies and so on. Using it is very simple. At the very end of your Meson project (that is, the end of your top level `meson.build` file) add these two lines. ```meson rpm = import('rpm') diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index dd99bde..9c4df7e 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -83,7 +83,7 @@ Note that all these options are also available while running the `mesontest` scr void benchmark(name, executable, ...) ``` -Creates a benchmark item that will be run when the benchmark target is run. The behaviour of this function is identical to `test` with the exception that there is no `is_parallel` keyword, because benchmarks are never run in parallel. +Creates a benchmark item that will be run when the benchmark target is run. The behavior of this function is identical to `test` with the exception that there is no `is_parallel` keyword, because benchmarks are never run in parallel. ### build_target() @@ -145,14 +145,14 @@ Create a custom top level build target. The only positional argument is the name - `build_always` if `true` this target is always considered out of date and is rebuilt every time, useful for things such as build timestamps or revision control tags - `capture`, there are some compilers that can't be told to write their output to a file but instead write it to standard output. When this argument is set to true, Meson captures `stdout` and writes it to the target file. Note that your command argument list may not contain `@OUTPUT@` when capture mode is active. - `depends` specifies that this target depends on the specified target(s), even though it does not take any of them as a command line argument. This is meant for cases where you have a tool that e.g. does globbing internally. Usually you should just put the generated sources as inputs and Meson will set up all dependencies automatically. -- `depend_files` files ([`string`](#string-object), [`files()`](#files), or [`configure_file()`](#configure_file)) that this target depends on but are not listed in the `command` kwarg. Useful for adding regen dependencies. +- `depend_files` files ([`string`](#string-object), [`files()`](#files), or [`configure_file()`](#configure_file)) that this target depends on but are not listed in the `command` keyword argument. Useful for adding regen dependencies. - `depfile` is a dependency file that the command can write listing all the additional files this target depends on, for example a C compiler would list all the header files it included, and a change in any one of these files triggers a recompilation - `build_by_default` *(added 0.38.0)* causes, when set to true, to have this target be built by default, that is, when invoking plain `ninja`; the default value is false -The list of strings passed to the `command` kwarg accept the following special string substitutions: +The list of strings passed to the `command` keyword argument accept the following special string substitutions: - `@INPUT@` the full path to the input passed to `input`. If more than one input is specified, all of them will be substituted as separate arguments only if the command uses `'@INPUT@'` as a standalone-argument. For instance, this would not work: `command : ['cp', './@INPUT@']`, but this would: `command : ['cp', '@INPUT@']`. -- `@OUTPUT@` the full path to the output passed to `output`. If more than one outputs are specified, the behaviour is the same as `@INPUT@`. +- `@OUTPUT@` the full path to the output passed to `output`. If more than one outputs are specified, the behavior is the same as `@INPUT@`. - `@INPUT0@` `@INPUT1@` `...` the full path to the input with the specified array index in `input` - `@OUTPUT0@` `@OUTPUT1@` `...` the full path to the output with the specified array index in `output` - `@OUTDIR@` the full path to the directory where the output(s) must be written @@ -172,7 +172,7 @@ This function returns a [dependency object](#dependency-object) that behaves lik - `dependencies`, other dependencies needed to use this dependency - `compile_args`, compile arguments to use - `link_args`, link arguments to use - - `version`, the version of this depency, such as `1.2.3` + - `version`, the version of this dependency, such as `1.2.3` ### dependency() @@ -184,7 +184,7 @@ Finds an external dependency with the given name with `pkg-config` if possible a - `modules` specifies submodules to use for dependencies such as Qt5 or Boost. - `required`, when set to false, Meson will proceed with the build even if the dependency is not found -- `version`, specifies the required version, a string containing a comparison operator followed by the version string, examples include `>1.0.0`, `<=2.3.5` or `3.1.4` for exact matching. (*Added 0.37.0*) You can also specify multiple restrictions by passing a list to this kwarg, such as: `['>=3.14.0', '<=4.1.0']`. +- `version`, specifies the required version, a string containing a comparison operator followed by the version string, examples include `>1.0.0`, `<=2.3.5` or `3.1.4` for exact matching. (*Added 0.37.0*) You can also specify multiple restrictions by passing a list to this keyword argument, such as: `['>=3.14.0', '<=4.1.0']`. - `native` if set to `true`, causes Meson to find the dependency on the build machine system rather than the host system (i.e. where the cross compiled binary will run on), usually only needed if you build a tool to be used during compilation. - `static` tells the dependency provider to try to get static libraries instead of dynamic ones (note that this is not supported by all dependency backends) - `fallback` specifies a subproject fallback to use in case the dependency is not found in the system. The value is an array `['subproj_name', 'subproj_dep']` where the first value is the name of the subproject and the second is the variable name in that subproject that contains the value of [`declare_dependency`](#declare_dependency). @@ -224,7 +224,7 @@ Creates a new executable. The first argument specifies its name and the remainin These input files can be sources, objects, libraries, or any other file. Meson will automatically categorize them based on the extension and use them accordingly. For instance, sources (`.c`, `.cpp`, `.vala`, `.rs`, etc) will be compiled, objects (`.o`, `.obj`) and libraries (`.so`, `.dll`, etc) will be linked, and all other files (headers, unknown extensions, etc) will be ignored. -With the Ninja backend, Meson will create a build-time [order-only dependency](https://ninja-build.org/manual.html#ref_dependencies) on all generated input files, including unknown files. For all input files (generated and non-generated), Meson uses the [dependency file](https://ninja-build.org/manual.html#ref_headers) generated by your compiler to determine when to rebuild sources. The behaviour is similar for other backends. +With the Ninja backend, Meson will create a build-time [order-only dependency](https://ninja-build.org/manual.html#ref_dependencies) on all generated input files, including unknown files. For all input files (generated and non-generated), Meson uses the [dependency file](https://ninja-build.org/manual.html#ref_headers) generated by your compiler to determine when to rebuild sources. The behavior is similar for other backends. Executable supports the following keyword arguments. Note that just like the positional arguments above, these keyword arguments can also be passed to [shared and static libraries](#library). @@ -232,7 +232,7 @@ Executable supports the following keyword arguments. Note that just like the pos - `link_whole` links all contents of the given static libraries whether they are used by not, equivalent to the `-Wl,--whole-archive` argument flag of GCC, available since 0.40.0 - `<languagename>_pch` precompiled header file to use for the given language - `<languagename>_args` compiler flags to use for the given language; eg: `cpp_args` for C++ -- `link_args` flags to use during linking. You can use unix-style flags here for all platforms. +- `link_args` flags to use during linking. You can use UNIX-style flags here for all platforms. - `link_depends` an extra file in the source tree that the link step depends on such as a symbol visibility map. The purpose is to automatically trigger a re-link (but not a re-compile) of the target when this file changes. - `include_directories` one or more objects created with the `include_directories` function - `dependencies` one or more objects created with [`dependency`](#dependency) or [`find_library`](#compiler-object) (for external deps) or [`declare_dependency`](#declare_dependency) (for deps built by the project) @@ -246,7 +246,7 @@ Executable supports the following keyword arguments. Note that just like the pos - `build_by_default` causes, when set to true, to have this target be built by default, that is, when invoking plain `ninja`, the default value is true for all built target types, since 0.38.0 - `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 -The list of `sources`, `objects`, and `dependencies` is always flattened, which means you can freely nest and add lists while creating the final list. As a corollary, the best way to handle a 'disabled dependency' is by assigning an empty list `[]` to it and passing it like any other dependency to the `dependencies:` kwarg. +The list of `sources`, `objects`, and `dependencies` is always flattened, which means you can freely nest and add lists while creating the final list. As a corollary, the best way to handle a 'disabled dependency' is by assigning an empty list `[]` to it and passing it like any other dependency to the `dependencies:` keyword argument. The returned object also has methods that are documented in the [object methods section](#build-target-object) below. @@ -262,7 +262,7 @@ This function is deprecated and in the 0.31.0 release it was moved to [the compi `program_name1` here is a string that can be an executable or script to be searched for in `PATH`, or a script in the current source directory. -Meson will also autodetect scripts with a shebang line and run them with the executable/interpreter specified in it both on Windows (because the command invocator will reject the command otherwise) and UNIXes (if the script file does not have the executable bit set). Hence, you *must not* manually add the interpreter while using this script as part of a list of commands. +Meson will also autodetect scripts with a shebang line and run them with the executable/interpreter specified in it both on Windows (because the command invocator will reject the command otherwise) and Unixes (if the script file does not have the executable bit set). Hence, you *must not* manually add the interpreter while using this script as part of a list of commands. `program_name2` and later positional arguments are used as fallback strings to search for. This is meant to be used for cases where the program may have many alternative names, such as `foo` and `foo.py`. The function will check for the arguments one by one and the first one that is found is returned. Meson versions earlier than 0.37.0 only accept one argument. @@ -306,14 +306,14 @@ This function creates a [generator object](#generator-object) that can be used t The returned object also has methods that are documented in the [object methods section](#generator-object) below. -The template strings passed to all the above kwargs accept the following special substitutions: +The template strings passed to all the above keyword arguments accept the following special substitutions: - `@PLAINNAME@`: the complete input file name, e.g: `foo.c` becomes `foo.c` (unchanged) - `@BASENAME@`: the base of the input filename, e.g.: `foo.c.y` becomes `foo.c` (extension is removed) -Each string passed to the `outputs` kwarg *must* be constructed using one or both of these two substitutions. +Each string passed to the `outputs` keyword argument *must* be constructed using one or both of these two substitutions. -In addition to the above substitutions, the `arguments` kwarg also accepts the following: +In addition to the above substitutions, the `arguments` keyword argument also accepts the following: - `@OUTPUT@`: the full path to the output file - `@INPUT@`: the full path to the input file @@ -458,7 +458,7 @@ Installs the specified man files from the source tree into system's man director void install_subdir(subdir_name) ``` -Installs the entire given subdirectory and its contents from the source tree to the location specified by the keyword argument `install_dir`. Note that due to implementation issues this command deletes the entire target dir before copying the files, so you should never use `install_subdir` to install into two overlapping directories (such as `foo` and `foo/bar`) because if you do the behaviour is undefined. +Installs the entire given subdirectory and its contents from the source tree to the location specified by the keyword argument `install_dir`. Note that due to implementation issues this command deletes the entire target dir before copying the files, so you should never use `install_subdir` to install into two overlapping directories (such as `foo` and `foo/bar`) because if you do the behavior is undefined. ### is_variable() @@ -474,7 +474,7 @@ Returns true if a variable of the given name exists and false otherwise. jar_object jar(name, list_of_sources, ...) ``` -Build a jar from the specified Java source files. Keyword arguments are the same as executable's, with the addition of `main_class` which specifies the main class to execute when running the jar with `java -jar file.jar`. +Build a jar from the specified Java source files. Keyword arguments are the same as [`executable`](#executable)'s, with the addition of `main_class` which specifies the main class to execute when running the jar with `java -jar file.jar`. ### join_paths() @@ -567,7 +567,7 @@ Builds a shared library with the given sources. Positional and keyword arguments - `version` a string specifying the version of this shared library, such as `1.1.0`. On Linux and OS X, this is used to set the shared library version in the filename, such as `libfoo.so.1.1.0` and `libfoo.1.1.0.dylib`. If this is not specified, `soversion` is used instead (see below). - `soversion` a string specifying the soversion of this shared library, such as `0`. On Linux and Windows this is used to set the soversion (or equivalent) in the filename. For example, if `soversion` is `4`, a Windows DLL will be called `foo-4.dll` and one of the aliases of the Linux shared library would be `libfoo.so.4`. If this is not specified, the first part of `version` is used instead. For example, if `version` is `3.6.0` and `soversion` is not defined, it is set to `3`. -- `vs_module_defs` a string pointing to a file that contains Visual Studio symbol export definitions. +- `vs_module_defs` a string pointing to a file or a File object that contains Visual Studio symbol export definitions. ### shared_module() @@ -635,13 +635,15 @@ Defined tests can be run in a backend-agnostic way by calling `mesontest` inside ctarget vcs_tag(...) ``` -This command detects revision control commit information at build time and places it in the specified output file. This file is guaranteed to be up to date on every build. Keywords are similar to `custom_target` and all of them are mandatory. +This command detects revision control commit information at build time and places it in the specified output file. This file is guaranteed to be up to date on every build. Keywords are similar to `custom_target`. -- `input` file to modify (e.g. `version.c.in`) -- `output` file to write the results to (e.g. `version.c`) -- `fallback` version number to use when no revision control information is present, such as when building from a release tarball +- `input` file to modify (e.g. `version.c.in`) (required) +- `output` file to write the results to (e.g. `version.c`) (required) +- `fallback` version number to use when no revision control information is present, such as when building from a release tarball (defaults to `meson.project_version()`) +- `command` string list with the command to execute, see [`custom_target`](#custom_target) for details on how this command must be specified +- `replace_string` string in the input file to substitute with the commit information (defaults to `@VCS_TAG@`) -Meson will read the contents of `input`, replace the string `@VCS_TAG@` with the detected revision number and write the result to `output`. This method returns an opaque [`custom_target`](#custom_target) object that you should put in your main program. If you desire more specific behavior than what this command provides, you should use `custom_target`. +Meson will read the contents of `input`, substitute the `replace_string` with the detected revision number, and write the result to `output`. This method returns an opaque [`custom_target`](#custom_target) object that can be used as source. If you desire more specific behavior than what this command provides, you should use `custom_target`. ## Built-in objects @@ -696,7 +698,7 @@ Provides information about the build machine — the machine that is doing the a - `system()` returns the operating system name, such as `windows` (all versions of Windows), `linux` (all Linux distros), `darwin` (all versions of OS X), etc. - `endian()` returns `big` on big-endian systems and `little` on little-endian systems. -Currently, these values are populated using the [`platform.system()`](https://docs.python.org/3.4/library/platform.html#platform.system) and [`platform.machine()`](https://docs.python.org/3.4/library/platform.html#platform.machine). If you think the returned values for any of these are incorrect for your system or CPU, please file [a bug report](/mesonbuild/meson/issues/new). +Currently, these values are populated using the [`platform.system()`](https://docs.python.org/3.4/library/platform.html#platform.system) and [`platform.machine()`](https://docs.python.org/3.4/library/platform.html#platform.machine). If you think the returned values for any of these are incorrect for your system or CPU, please file [a bug report](https://github.com/mesonbuild/meson/issues/new). ### `host_machine` object @@ -757,7 +759,7 @@ This object is returned by [`meson.get_compiler(lang)`](#meson-object). It repre The following keyword arguments can be used: -- `name` the name to use for printing a message about the compiler check. Supported by the methods `compiles()`, `links()`, and `run()`. If this kwarg is not passed to those methods, no message will be printed about the check. +- `name` the name to use for printing a message about the compiler check. Supported by the methods `compiles()`, `links()`, and `run()`. If this keyword argument is not passed to those methods, no message will be printed about the check. - `prefix` can be used to add #includes and other things that are required for the symbol to be declared. System definitions should be passed via compiler args (eg: `_GNU_SOURCE` is often required for some symbols to be exposed on Linux, and it should be passed via `args` keyword argument, see below). Supported by the methods `sizeof`, `has_type`, `has_function`, `has_member`, `has_members`, `has_header_symbol`. @@ -765,7 +767,7 @@ The following keyword arguments can be used: - `args` can be used to pass a list of compiler arguments that are required to find the header or symbol. For example, you might need to pass the include path `-Isome/path/to/header` if a header is not in the default include path. In versions newer than 0.38.0 you should use the `include_directories` keyword described above. You may also want to pass a library name `-lfoo` for `has_function` to check for a function. Supported by all methods except `get_id`, `version`, and `find_library`. -Note that if you have a single prefix with all your dependencies, you might find it easier to append to the environment variables `C_INCLUDE_PATH` with gcc/clang and `INCLUDE` with msvc to expand the default include path, and `LIBRARY_PATH` with gcc/clang and `LIB` with msvc to expand the default library search path. +Note that if you have a single prefix with all your dependencies, you might find it easier to append to the environment variables `C_INCLUDE_PATH` with GCC/Clang and `INCLUDE` with MSVC to expand the default include path, and `LIBRARY_PATH` with GCC/Clang and `LIB` with MSVC to expand the default library search path. However, with GCC, these variables will be ignored when cross-compiling. In that case you need to use a specs file. See: <http://www.mingw.org/wiki/SpecsFileHOWTO> diff --git a/docs/markdown/Release-notes-for-0.37.0.md b/docs/markdown/Release-notes-for-0.37.0.md index 07fbda2..32845bb 100644 --- a/docs/markdown/Release-notes-for-0.37.0.md +++ b/docs/markdown/Release-notes-for-0.37.0.md @@ -15,13 +15,13 @@ or with an arbitrary wrapper executable: mesontest --wrap='valgrind --tool=helgrind' a_test -or under gdb, 1000 times in a row. This is handy for tests that fail spuriously, as when the crash happens you are given the full GDB command line: +or under `gdb`, 1000 times in a row. This is handy for tests that fail spuriously, as when the crash happens you are given the full GDB command line: mesontest --repeat=1000 --gdb a_test ## Mesonrewriter -Mesonrewrite is an experimental tool to manipulate your build definitions programmatically. It is not installed by default yet but those interested can run it from the source repository. +Mesonrewriter is an experimental tool to manipulate your build definitions programmatically. It is not installed by default yet but those interested can run it from the source repository. As an example, here is how you would add a source file to a build target: @@ -37,21 +37,21 @@ The new `shared_module` function allows the creation of shared modules, that is, ### gtkdoc -- Allow passing a list of directories to `src_dir` kwarg -- Add `namespace` kwarg -- Add `mode` kwarg +- Allow passing a list of directories to `src_dir` keyword argument +- Add `namespace` keyword argument +- Add `mode` keyword argument - Fix `gtkdoc-scangobj` finding local libraries ### compile_resources -- Add `gresource_bundle` kwarg to output `.gresource` files -- Add `export` and `install_header` kwargs +- Add `gresource_bundle` keyword argument to output `.gresource` files +- Add `export` and `install_header` keyword arguments - Use depfile support available in GLib >= 2.52.0 ## i18n module - Add `merge_file()` function for creating translated files -- Add `preset` kwarg to included common gettext flags +- Add `preset` keyword argument to included common gettext flags - Read languages from `LINGUAS` file ## LLVM IR compilation @@ -111,11 +111,11 @@ if cc.symbols_have_underscore_prefix() endif ``` -C symbol mangling is platform and architecture dependent, and a helper function is needed to detect it. Eg: Windows 32-bit prefixes underscore, but 64-bit does not. Linux does not prefix an underscore but OS X does. +C symbol mangling is platform and architecture dependent, and a helper function is needed to detect it. For example, Windows 32-bit prefixes underscore, but 64-bit does not. Linux does not prefix an underscore but OS X does. ## Vala -Glib Resources compiled with [`gnome.compile_resources`](Gnome-module.md#compile_resources) that are added to the sources of a Vala build target will now cause the appropriate `--gresources` flag to be passed to the Vala compiler so you don't need to add that yourself to `vala_args:`. +GLib Resources compiled with [`gnome.compile_resources`](Gnome-module.md#compile_resources) that are added to the sources of a Vala build target will now cause the appropriate `--gresources` flag to be passed to the Vala compiler so you don't need to add that yourself to `vala_args:`. ## Improvements to install scripts diff --git a/docs/markdown/Release-notes-for-0.38.0.md b/docs/markdown/Release-notes-for-0.38.0.md index 4c19a91..ca6602e 100644 --- a/docs/markdown/Release-notes-for-0.38.0.md +++ b/docs/markdown/Release-notes-for-0.38.0.md @@ -66,7 +66,7 @@ Build targets got a new keyword `build_by_default` which tells whether the targe # Add option to mesonconf to wipe cached data. -Meson caches the results of depencency lookups. Sometimes these may get out of sync with the system state. Mesonconf now has a `--clearcache` option to clear these values so they will be re-searched from the system upon next compile. +Meson caches the results of dependency lookups. Sometimes these may get out of sync with the system state. Mesonconf now has a `--clearcache` option to clear these values so they will be re-searched from the system upon next compile. # Can specify file permissions and owner when installing data diff --git a/docs/markdown/Release-notes-for-0.40.0.md b/docs/markdown/Release-notes-for-0.40.0.md index 6ecc1ea..a480788 100644 --- a/docs/markdown/Release-notes-for-0.40.0.md +++ b/docs/markdown/Release-notes-for-0.40.0.md @@ -67,7 +67,7 @@ custom_target('two_out', For backwards compatibility and for conciseness, if you only specify one directory all outputs will be installed into it. -The same feature is also available for Vala build targets. For instance, to install a shared library built by valac, the generated header, and the generated vapi (respectively) into the default locations, you can do: +The same feature is also available for Vala build targets. For instance, to install a shared library built by valac, the generated header, and the generated VAPI (respectively) into the default locations, you can do: ```meson shared_library('valalib', 'mylib.vala', @@ -87,7 +87,7 @@ qt5_dep = dependency('qt5', modules : 'core', method : 'qmake') ## Link whole contents of static libraries -The default behaviour of static libraries is to discard all symbols that are not not directly referenced. This may lead to exported symbols being lost. Most compilers support "whole archive" linking that includes all symbols and code of a given static library. This is exposed with the `link_whole` keyword. +The default behavior of static libraries is to discard all symbols that are not not directly referenced. This may lead to exported symbols being lost. Most compilers support "whole archive" linking that includes all symbols and code of a given static library. This is exposed with the `link_whole` keyword. ```meson shared_library('foo', 'foo.c', link_whole : some_static_library) diff --git a/docs/markdown/Release-notes-for-0.41.0.md b/docs/markdown/Release-notes-for-0.41.0.md index a3ef384..a2a64de 100644 --- a/docs/markdown/Release-notes-for-0.41.0.md +++ b/docs/markdown/Release-notes-for-0.41.0.md @@ -8,3 +8,19 @@ short-description: Release notes for 0.41 (preliminary) # New features Add features here as code is merged to master. + +## Dependency Handler for LLVM + +Native support for linking against LLVM using the `dependency` function. + +## vcs_tag keyword fallback is is now optional + +The `fallback` keyword in `vcs_tag` is now optional. If not given, its value +defaults to the return value of `meson.project_version()`. + +## Better quoting of special characters in ninja command invocations + +The ninja backend now quotes special characters that may be interpreted by +ninja itself, providing better interoperability with custom commands. This +support may not be perfect; please report any issues found with special +characters to the issue tracker. diff --git a/docs/markdown/Run-targets.md b/docs/markdown/Run-targets.md index 86639ab..38129a6 100644 --- a/docs/markdown/Run-targets.md +++ b/docs/markdown/Run-targets.md @@ -1,3 +1,7 @@ +--- +short-description: Targets to run external commands +... + # Run targets Sometimes you need to have a target that just runs an external command. As an example you might have a build target that reformats your source code, runs `cppcheck` or something similar. In Meson this is accomplished with a so called *run target*. diff --git a/docs/markdown/Running-Meson.md b/docs/markdown/Running-Meson.md index 5ae407e..2dbb755 100644 --- a/docs/markdown/Running-Meson.md +++ b/docs/markdown/Running-Meson.md @@ -15,8 +15,8 @@ Let us assume that we have a source tree that has a Meson build system. This mea cd /path/to/source/root - mkdir build - cd build + mkdir builddir + cd builddir meson .. First we create a directory to hold all files generated during the build. Then we go into it and invoke Meson, giving it the location of the source root. @@ -54,7 +54,7 @@ You can then open the generated solution with Visual Studio and compile it in th Building the source == -If you are not using an IDE, Meson uses the [Ninja build system](http://martine.github.com/ninja/) to actually build the code. To start the build, simply type the following command. +If you are not using an IDE, Meson uses the [Ninja build system](https://ninja-build.org/) to actually build the code. To start the build, simply type the following command. ninja diff --git a/docs/markdown/Subprojects.md b/docs/markdown/Subprojects.md index 0318e79..b91366d 100644 --- a/docs/markdown/Subprojects.md +++ b/docs/markdown/Subprojects.md @@ -1,3 +1,7 @@ +--- +short-description: Using meson projects as subprojects within other meson projects +... + # Subprojects Some platforms do not provide a native packaging system. In these cases it is common to bundle all third party libraries in your source tree. This is usually frowned upon because it makes it hard to add these kinds of projects into e.g. those Linux distributions that forbid bundled libraries. @@ -14,7 +18,7 @@ else endif ``` -All Meson features of the subproject, such as project options keep working and can be set in the master project. There are a few limitations, the most imporant being that global compiler arguments must be set in the main project before calling subproject. Subprojects must not set global arguments because there is no way to do that reliably over multiple subprojects. To check whether you are running as a subproject, use the `is_subproject` function. +All Meson features of the subproject, such as project options keep working and can be set in the master project. There are a few limitations, the most important being that global compiler arguments must be set in the main project before calling subproject. Subprojects must not set global arguments because there is no way to do that reliably over multiple subprojects. To check whether you are running as a subproject, use the `is_subproject` function. As an example, suppose we have a simple project that provides a shared library. diff --git a/docs/markdown/Threads.md b/docs/markdown/Threads.md index d4f1bca..1bf9f83 100644 --- a/docs/markdown/Threads.md +++ b/docs/markdown/Threads.md @@ -1,3 +1,7 @@ +--- +short-description: Enabling thread support +... + # Threads Meson has a very simple notational shorthand for enabling thread support on your build targets. First you obtain the thread dependency object like this: diff --git a/docs/markdown/Trial-conversions.md b/docs/markdown/Trial-conversions.md index 64d5a0a..4d89b9a 100644 --- a/docs/markdown/Trial-conversions.md +++ b/docs/markdown/Trial-conversions.md @@ -11,12 +11,12 @@ Here is a list of projects that have had a build system port done. * [Python 3](https://mail.python.org/pipermail/python-dev/2013-June/126748.html) * [Glib](https://mail.gnome.org/archives/gtk-devel-list/2013-August/msg00001.html) * [QtCreator](http://lists.qt-project.org/pipermail/qt-creator/2014-May/003584.html), and a [followup](http://lists.qt-project.org/pipermail/qt-creator/2014-May/003598.html) on unity builds -* [SDL 2](http://forums.libsdl.org/viewtopic.php?t=10093&sid=8cf1d6c83d4d73fe6cfbb7cbb16b3d28) -* [Mesa3D](http://lists.freedesktop.org/archives/mesa-dev/2014-July/064160.html) +* [SDL 2](https://forums.libsdl.org/viewtopic.php?t=10093&sid=8cf1d6c83d4d73fe6cfbb7cbb16b3d28) +* [Mesa3D](https://lists.freedesktop.org/archives/mesa-dev/2014-July/064160.html) * [Mame](http://www.mameworld.info/ubbthreads/showthreaded.php?Cat=&Number=332119&page=0&view=expanded&sb=5&o=&fpart=1&vc=1) * [Firefox NSPR](https://groups.google.com/forum/#!topic/mozilla.dev.builds/daS3DK2F1MQ) -* [Wayland](http://lists.freedesktop.org/archives/wayland-devel/2015-February/020124.html) +* [Wayland](https://lists.freedesktop.org/archives/wayland-devel/2015-February/020124.html) -## More from Wrapdb +## More from WrapDB -The [Meson Wrap database](http://wrapdb.mesonbuild.com) contains several projects that have been converted into Meson and are ready to use. +The [Meson Wrap database](https://wrapdb.mesonbuild.com) contains several projects that have been converted into Meson and are ready to use. diff --git a/docs/markdown/Tutorial.md b/docs/markdown/Tutorial.md index 524861d..b8e268e 100644 --- a/docs/markdown/Tutorial.md +++ b/docs/markdown/Tutorial.md @@ -27,20 +27,20 @@ project('tutorial', 'c') executable('demo', 'main.c') ``` -That is all. We are now ready to build our application. First we need to initialise the build by going into the source directory and issuing the following commands. +That is all. We are now ready to build our application. First we need to initialize the build by going into the source directory and issuing the following commands. ```console -$ meson build +$ meson builddir ``` -We create a separate build directory to hold all of the compiler output. Meson is different from some other build systems in that it does not permit in-source builds. You must always create a separate build directory. Common convention is to put the default build directory in a subdirectory of your toplevel source directory. +We create a separate build directory to hold all of the compiler output. Meson is different from some other build systems in that it does not permit in-source builds. You must always create a separate build directory. Common convention is to put the default build directory in a subdirectory of your top level source directory. When Meson is run it prints the following output. The Meson build system version: 0.13.0-research Source dir: /home/jpakkane/mesontutorial - Build dir: /home/jpakkane/mesontutorial/build + Build dir: /home/jpakkane/mesontutorial/builddir Build type: native build Project name is "tutorial". Using native c compiler "ccache cc". (gcc 4.8.2) @@ -49,7 +49,7 @@ When Meson is run it prints the following output. Now we are ready to build our code. ``` -$ cd build +$ cd builddir $ ninja ``` @@ -66,7 +66,7 @@ This produces the expected output. Adding dependencies ----- -Just printing text is a bit old fashioned. Let's update our program to create a graphical window instead. We'll use the [GTK+](https://gtk.org) widget toolkit. First we edit the main file to use Gtk. The new version looks like this. +Just printing text is a bit old fashioned. Let's update our program to create a graphical window instead. We'll use the [GTK+](https://gtk.org) widget toolkit. First we edit the main file to use GTK+. The new version looks like this. ```c #include<gtk/gtk.h> @@ -82,7 +82,7 @@ int main(int argc, char **argv) { } ``` -Then we edit the Meson file, instructing it to find and use the Gtk libraries. +Then we edit the Meson file, instructing it to find and use the GTK+ libraries. ```meson project('tutorial', 'c') @@ -102,7 +102,7 @@ Once you have set up your build directory the first time, you don't ever need to The Meson build system version: 0.13.0-research Source dir: /home/jpakkane/mesontutorial - Build dir: /home/jpakkane/mesontutorial/build + Build dir: /home/jpakkane/mesontutorial/builddir Build type: native build Project name is "tutorial". Using native c compiler "ccache cc". (gcc 4.8.2) @@ -120,4 +120,4 @@ $ ./demo This creates the following GUI application. - + diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md index d5ef77e..1aa7806 100644 --- a/docs/markdown/Unit-tests.md +++ b/docs/markdown/Unit-tests.md @@ -1,3 +1,7 @@ +--- +short-description: Meson's own unit-test system +... + # Unit tests Meson comes with a fully functional unit test system. To use it simply build an executable and then use it in a test. @@ -26,14 +30,14 @@ Note how you need to specify multiple values as an array. Coverage -- -If you enable coverage measurements by giving Meson the command line flag `-Db_coverage=true`, you can generate coverage reports. Meson will autodetect what coverage generator tools you have installed and will generate the corresponding targets. These targets are `coverage-xml` and `coverage-text` which are both provided by [Gcovr](https://software.sandia.gov/trac/fast/wiki/gcovr) and `coverage-html`, which requires [Lcov](http://ltp.sourceforge.net/coverage/lcov.php) and [GenHTML](http://linux.die.net/man/1/genhtml). +If you enable coverage measurements by giving Meson the command line flag `-Db_coverage=true`, you can generate coverage reports. Meson will autodetect what coverage generator tools you have installed and will generate the corresponding targets. These targets are `coverage-xml` and `coverage-text` which are both provided by [Gcovr](https://software.sandia.gov/trac/fast/wiki/gcovr) and `coverage-html`, which requires [Lcov](https://ltp.sourceforge.io/coverage/lcov.php) and [GenHTML](https://linux.die.net/man/1/genhtml). The the output of these commands is written to the log directory `meson-logs` in your build directory. Parallelism -- -To reduce test times, Meson will by default run multiple unit tests in parallel. It is common to have some tests which can not be run in parallel because they require unique hold on some resource such as a file or a dbus name. You have to specify these tests with a keyword argument. +To reduce test times, Meson will by default run multiple unit tests in parallel. It is common to have some tests which can not be run in parallel because they require unique hold on some resource such as a file or a D-Bus name. You have to specify these tests with a keyword argument. ```meson test('unique test', t, is_parallel : false) @@ -49,7 +53,7 @@ $ MESON_TESTTHREADS=5 ninja test ## Skipped tests -Sometimes a test can only determine at runtime that it can not be run. The GNU standard approach in this case is to exit the program with error code 77. Meson will detect this and report these tests as skipped rather than failed. This behaviour was added in version 0.37.0. +Sometimes a test can only determine at runtime that it can not be run. The GNU standard approach in this case is to exit the program with error code 77. Meson will detect this and report these tests as skipped rather than failed. This behavior was added in version 0.37.0. ## Testing tool @@ -85,13 +89,13 @@ Arguments to the wrapper binary can be given like this: $ mesontest --wrap='valgrind --tool=helgrind' testname ``` -Meson also supports running the tests under gdb. Just doing this: +Meson also supports running the tests under GDB. Just doing this: ```console $ mesontest --gdb testname ``` -Mesontest will launch gdb all set up to run the test. Just type `run` in the gdb command prompt to start the program. +Mesontest will launch `gdb` all set up to run the test. Just type `run` in the GDB command prompt to start the program. The second use case is a test that segfaults only rarely. In this case you can invoke the following command: @@ -99,6 +103,6 @@ The second use case is a test that segfaults only rarely. In this case you can i $ mesontest --gdb --repeat=10000 testname ``` -This runs the test up to 10 000 times under gdb automatically. If the program crashes, gdb will halt and the user can debug the application. Note that testing timeouts are disabled in this case so mesontest will not kill gdb while the developer is still debugging it. The downside is that if the test binary freezes, the test runner will wait forever. +This runs the test up to 10 000 times under GDB automatically. If the program crashes, GDB will halt and the user can debug the application. Note that testing timeouts are disabled in this case so mesontest will not kill `gdb` while the developer is still debugging it. The downside is that if the test binary freezes, the test runner will wait forever. For further information see the command line help of Mesontest by running `mesontest -h`. diff --git a/docs/markdown/Unity-builds.md b/docs/markdown/Unity-builds.md index f1f718e..9f939f5 100644 --- a/docs/markdown/Unity-builds.md +++ b/docs/markdown/Unity-builds.md @@ -1,3 +1,7 @@ +--- +short-description: Unity builds are a technique for reducing build times +... + # Unity builds Unity builds are a technique for cutting down build times. The way it works is relatively straightforward. Suppose we have source files `src1.c`, `src2.c` and `src3.c`. Normally we would run the compiler three times, once for each file. In a unity build we instead compile all these sources in a single unit. The simplest approach is to create a new source file that looks like this. diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 1796c7c..574df27 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -8,14 +8,14 @@ If you have a project that uses Meson that you want to add to this list, let us - [AQEMU](https://github.com/tobimensch/aqemu), a Qt GUI for QEMU virtual machines, since version 0.9.3 - [Arduino sample project](https://github.com/jpakkane/mesonarduino) - - [Emeus](https://github.com/ebassi/emeus), Constraint based layout manager for Gtk + - [Emeus](https://github.com/ebassi/emeus), Constraint based layout manager for GTK+ - [GLib](https://github.com/centricular/glib/), cross-platform C library used by GTK+ (not merged yet) - [Gnome Builder](https://git.gnome.org/browse/gnome-builder/), an IDE for the Gnome platform - [Gnome MPV](https://github.com/gnome-mpv/gnome-mpv), Gnome frontend to the mpv video player - [Gnome Recipes](https://github.com/matthiasclasen/gr), application for cooking recipes - [Gnome Software](https://git.gnome.org//browse/gnome-software), an app store for Gnome - [Gnome Twitch](https://github.com/vinszent/gnome-twitch), an app for viewing Twitch streams on Gnome desktop - - [Graphene](http://ebassi.github.io/graphene/), a thin type library for graphics + - [Graphene](https://ebassi.github.io/graphene/), a thin type library for graphics - [Grilo](https://mail.gnome.org/archives/grilo-list/2017-February/msg00000.html) and [Grilo plugins](https://git.gnome.org/browse/grilo-plugins/commit/?id=ea047c4fb63e90268eb795ed91a09a2be5068a4c), the Grilo multimedia framework - [GStreamer](https://cgit.freedesktop.org/gstreamer/gstreamer/), multimedia framework (not the default yet) - [GTK+](https://git.gnome.org/browse/gtk+/log/?h=wip/meson), the multi-platform toolkit used by GNOME (not merged yet) diff --git a/docs/markdown/Using-multiple-build-directories.md b/docs/markdown/Using-multiple-build-directories.md index cabd64f..c07b39c 100644 --- a/docs/markdown/Using-multiple-build-directories.md +++ b/docs/markdown/Using-multiple-build-directories.md @@ -14,20 +14,20 @@ Since a build directory is fully self contained and treats the source tree as a The first thing to do is to set up the default build, that is, the one we are going to use over 90% of the time. In this we use the system compiler and build with debug enabled and no optimizations so it builds as fast as possible. This is the default project type for Meson, so setting it up is simple. - mkdir build - meson build + mkdir builddir + meson builddir Another common setup is to build with debug and optimizations to, for example, run performance tests. Setting this up is just as simple. mkdir buildopt - meson --buildtype=debugoptimized + meson --buildtype=debugoptimized buildopt For systems where the default compiler is GCC, we would like to compile with Clang, too. So let's do that. mkdir buildclang CC=clang CXX=clang++ meson buildclang -You can add cross builds, too. As an example, let's set up a Linux -> Windows cross compilation build using mingw. +You can add cross builds, too. As an example, let's set up a Linux -> Windows cross compilation build using MinGW. mkdir buildwine meson --cross-file=mingw-cross.txt buildwine @@ -36,7 +36,7 @@ The cross compilation file sets up Wine so that not only can you compile your ap To compile any of these build types, just cd into the corresponding build directory and run `ninja` or instruct your IDE to do the same. Note that once you have set up your build directory once, you can just run Ninja and Meson will ensure that the resulting build is fully up to date according to the source. Even if you have not touched one of the directories in weeks and have done major changes to your build configuration, Meson will detect this and bring the build directory up to date (or print an error if it can't do that). This allows you to do most of your work in the default directory and use the others every now and then without having to babysit your build directories. -## Specialised uses ## +## Specialized uses ## Separate build directories allows easy integration for various different kinds of tools. As an example, Clang comes with a static analyzer. It is meant to be run from scratch on a given source tree. The steps to run it with Meson are very simple. diff --git a/docs/markdown/Using-the-WrapDB.md b/docs/markdown/Using-the-WrapDB.md index b6f1e11..5e626ef 100644 --- a/docs/markdown/Using-the-WrapDB.md +++ b/docs/markdown/Using-the-WrapDB.md @@ -1,10 +1,10 @@ -# Using the wrapDB +# Using the WrapDB -The Wrap database is a web service that provides Meson build definitions to projects that do not have it natively. Using it is simple. The service can be found [here](http://wrapdb.mesonbuild.com). +The Wrap database is a web service that provides Meson build definitions to projects that do not have it natively. Using it is simple. The service can be found [here](https://wrapdb.mesonbuild.com). The front page lists all projects that are on the service. Select the one you want and click it. The detail page lists available versions by branch and revision id. The branch names come from upstream releases and revision ids are version numbers internal to the database. Whenever the packaging is updated a new revision is released to the service a new revision with a bigger revision id is added. Usually you want to select the newest branch with the highest revision id. -You can get the actual wrap file which tells Meson how to fetch the project by clicking on the download link on the page. As an example, the wrap file for [zlib-1.2.8, revision 4](http://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/4/get_wrap) looks like this. You can find detailed documentation about it in [the Wrap manual](Wrap-dependency-system-manual.md). +You can get the actual wrap file which tells Meson how to fetch the project by clicking on the download link on the page. As an example, the wrap file for [zlib-1.2.8, revision 4](https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/4/get_wrap) looks like this. You can find detailed documentation about it in [the Wrap manual](Wrap-dependency-system-manual.md). [wrap-file] directory = zlib-1.2.8 @@ -13,7 +13,7 @@ You can get the actual wrap file which tells Meson how to fetch the project by c source_filename = zlib-1.2.8.tar.gz source_hash = 36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d - patch_url = http://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/4/get_zip + patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/4/get_zip patch_filename = zlib-1.2.8-4-wrap.zip patch_hash = 2327a42c8f73a4289ee8c9cd4abc43b324d0decc28d6e609e927f0a50321af4a diff --git a/docs/markdown/Using-with-Visual-Studio.md b/docs/markdown/Using-with-Visual-Studio.md index 2768ea4..339fda3 100644 --- a/docs/markdown/Using-with-Visual-Studio.md +++ b/docs/markdown/Using-with-Visual-Studio.md @@ -8,8 +8,8 @@ In order to generate Visual Studio projects, Meson needs to know the settings of 1. Click on start menu and select "Visual Studio 2015 Command Prompt" 1. cd into your source directory -1. mkdir build -1. python3 path/to/meson.py build --backend vs2015 +1. mkdir builddir +1. python3 path/to/meson.py builddir --backend vs2015 If you wish to use the Ninja backend instead of vs2015, pass `--backend ninja`. At the time of writing the Ninja backend is more mature than the VS backend so you might want to use it for serious work. diff --git a/docs/markdown/Using-wraptool.md b/docs/markdown/Using-wraptool.md index 4e5eb05..e000695 100644 --- a/docs/markdown/Using-wraptool.md +++ b/docs/markdown/Using-wraptool.md @@ -1,14 +1,14 @@ # Using wraptool -Wraptool is a helper tool that allows you to manage your source dependencies using the Wrapdb database. It gives you all things you would expect, such as installing and updating dependencies. The wrap tool works on all platforms, the only limitation is that the wrap definition works on your target platform. If you find some Wraps that don't work, please file bugs or, even better, patches. +Wraptool is a helper tool that allows you to manage your source dependencies using the WrapDB database. It gives you all things you would expect, such as installing and updating dependencies. The wrap tool works on all platforms, the only limitation is that the wrap definition works on your target platform. If you find some Wraps that don't work, please file bugs or, even better, patches. -All code examples here assume that you are running the commands in your top level source directory. Lines that start with the `#` mark are commands to type. +All code examples here assume that you are running the commands in your top level source directory. Lines that start with the `$` mark are commands to type. ## Simple querying The simplest operation to do is to query the list of packages available. To list them all issue the following command: - # wraptool list + $ wraptool list box2d enet gtest @@ -24,12 +24,12 @@ The simplest operation to do is to query the list of packages available. To list Usually you want to search for a specific package. This can be done with the `search` command: - # wraptool search jpeg + $ wraptool search jpeg libjpeg To determine which versions of libjpeg are available to install, issue the `info` command: - # wraptool info libjpeg + $ wraptool info libjpeg Available versions of libjpeg: 9a 2 @@ -39,21 +39,21 @@ The first number is the upstream release version, in this case `9a`. The second Installing dependencies is just as straightforward. First just create the `subprojects` directory at the top of your source tree and issue the install command. - # wraptool install libjpeg + $ wraptool install libjpeg Installed libjpeg branch 9a revision 2 Now you can issue a `subproject('libjpeg')` in your `meson.build` file to use it. To check if your projects are up to date you can issue the `status` command. - # wraptool status + $ wraptool status Subproject status libjpeg up to date. Branch 9a, revision 2. zlib not up to date. Have 1.2.8 2, but 1.2.8 4 is available. In this case `zlib` has a newer release available. Updating it is straightforward: - # wraptool.py update zlib + $ wraptool.py update zlib Updated zlib to branch 1.2.8 revision 4 Wraptool can do other things besides these. Documentation for these can be found in the command line help, which can be accessed by `wraptool --help`. diff --git a/docs/markdown/Vala.md b/docs/markdown/Vala.md index 0a6bc81..259ebd1 100644 --- a/docs/markdown/Vala.md +++ b/docs/markdown/Vala.md @@ -1,5 +1,6 @@ --- title: Vala +short-description: Compiling Vala programs ... # Compiling Vala applications diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md index 13765fc..fc41b61 100644 --- a/docs/markdown/Wrap-dependency-system-manual.md +++ b/docs/markdown/Wrap-dependency-system-manual.md @@ -16,20 +16,20 @@ To use this kind of a project as a dependency you could just copy and extract it [wrap-file] directory = libfoobar-1.0 -source_url = http://example.com/foobar-1.0.tar.gz +source_url = https://example.com/foobar-1.0.tar.gz source_filename = foobar-1.0.tar.gz source_hash = 5ebeea0dfb75d090ea0e7ff84799b2a7a1550db3fe61eb5f6f61c2e971e57663 ``` If you then use this subproject in your build, Meson will automatically download and extract it during build. This makes subproject embedding extremely easy. -Unfortunately most software projects in the world do not build with Meson. Because of this Meson allows you to specify a patch url. This works in much the same way as Debian's distro patches. That is, they are downloaded and automatically applied to the subproject. These files contain a Meson build definition for the given subproject. A wrap file with an additional patch url would look like this. +Unfortunately most software projects in the world do not build with Meson. Because of this Meson allows you to specify a patch URL. This works in much the same way as Debian's distro patches. That is, they are downloaded and automatically applied to the subproject. These files contain a Meson build definition for the given subproject. A wrap file with an additional patch URL would look like this. ``` [wrap-file] directory = libfoobar-1.0 -source_url = http://upstream.example.com/foobar-1.0.tar.gz +source_url = https://upstream.example.com/foobar-1.0.tar.gz source_filename = foobar-1.0.tar.gz source_hash = 5ebeea0dfb75d090ea0e7ff84799b2a7a1550db3fe61eb5f6f61c2e971e57663 @@ -57,7 +57,7 @@ The format is straightforward. The only thing to note is the revision element th Note that in this case you cannot specify an extra patch file to use. The git repo must contain all necessary Meson build definitions. -Usually you would use subprojects as read only. However in some cases you want to do commits to subprojects and push them upstream. For these cases you can specify the upload url by adding the following at the end of your wrap file: +Usually you would use subprojects as read only. However in some cases you want to do commits to subprojects and push them upstream. For these cases you can specify the upload URL by adding the following at the end of your wrap file: ```ini push-url=git@git.example.com:projects/someproject.git # Supported since version 0.37.0 @@ -69,6 +69,7 @@ To use a subproject simply do this in your top level `meson.build`. ```meson foobar_sp = subproject('foobar') +``` Usually dependencies consist of some header files plus a library to link against. To do this you would declare this internal dependency like this: diff --git a/docs/markdown/Wrap-review-guidelines.md b/docs/markdown/Wrap-review-guidelines.md index b211d91..beda0c2 100644 --- a/docs/markdown/Wrap-review-guidelines.md +++ b/docs/markdown/Wrap-review-guidelines.md @@ -4,7 +4,7 @@ In order to get a package in the Wrap database it must be reviewed and accepted ## Checklist ## -Reviewer: copypaste this to MR discussion box and tick all boxes that apply. +Reviewer: copy-paste this to MR discussion box and tick all boxes that apply. - [ ] project() has version string - [ ] project() has license string diff --git a/docs/markdown/fallback-wraptool.md b/docs/markdown/fallback-wraptool.md index fc3cc02..2754022 100644 --- a/docs/markdown/fallback-wraptool.md +++ b/docs/markdown/fallback-wraptool.md @@ -4,7 +4,7 @@ title: fallback wraptool # In case of emergency -In case wraptool is down we have created a backup script that you can use to download wraps directly from the Github repos. It is not as slick and may have bugs but at least it will allow you to use wraps. +In case wraptool is down we have created a backup script that you can use to download wraps directly from the GitHub repos. It is not as slick and may have bugs but at least it will allow you to use wraps. ## Using it @@ -26,6 +26,6 @@ Nuke the contents of `subprojects` and start again. ## Known issues -Some repositories show up in the list but are not installable. They would not show up in the real wrapdb because they are works in progress. +Some repositories show up in the list but are not installable. They would not show up in the real WrapDB because they are works in progress. -Github web API limits the amount of queries you can do to 60/hour. If you exceed that you need to wait for the timer to reset. +GitHub web API limits the amount of queries you can do to 60/hour. If you exceed that you need to wait for the timer to reset. diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md index c765853..f95dfb9 100644 --- a/docs/markdown/howtox.md +++ b/docs/markdown/howtox.md @@ -19,7 +19,7 @@ project('myproj', 'c', 'cpp', ## Enable threads -Lots of people seem to do this manually with `find_library('phtread')` or something similar. Do not do that. It is not portable. Instead do this. +Lots of people seem to do this manually with `find_library('pthread')` or something similar. Do not do that. It is not portable. Instead do this. ```meson thread_dep = dependency('threads') @@ -28,7 +28,7 @@ executable(..., dependencies : thread_dep) ## Set extra compiler and linker flags from the outside (when e.g. building distro packages) -The behaviour is the same as with other build systems, with environment variables during first invocation. +The behavior is the same as with other build systems, with environment variables during first invocation. ```console $ CFLAGS=-fsomething LDFLAGS=-Wl,--linker-flag meson <options> @@ -75,7 +75,7 @@ configure_file(...) ## Producing a coverage report -First initialise the build directory with this command. +First initialize the build directory with this command. ```console $ meson <other flags> -Db_coverage=true @@ -93,7 +93,7 @@ The coverage report can be found in the meson-logs subdirectory. ## Add some optimization to debug builds ## -By default the debug build does not use any optimizations. This is the desired approach most of the time. However some projects benefit from having some minor optimizations enabled. Gcc even has a specific compiler flag `-Og` for this. To enable its use, just issue the following command. +By default the debug build does not use any optimizations. This is the desired approach most of the time. However some projects benefit from having some minor optimizations enabled. GCC even has a specific compiler flag `-Og` for this. To enable its use, just issue the following command. ```console $ mesonconf -Dc_args=-Og @@ -103,7 +103,7 @@ This causes all subsequent builds to use this command line argument. ## Use address sanitizer -Clang comes with a selection of analysis tools such as the [address sanitizer](http://clang.llvm.org/docs/AddressSanitizer.html). Meson has native support for these with the `b_sanitize` option. +Clang comes with a selection of analysis tools such as the [address sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html). Meson has native support for these with the `b_sanitize` option. ```console $ meson <other options> -Db_sanitize=address diff --git a/docs/markdown/i18n-module.md b/docs/markdown/i18n-module.md index b4e40d7..9388be8 100644 --- a/docs/markdown/i18n-module.md +++ b/docs/markdown/i18n-module.md @@ -25,6 +25,7 @@ This function also defines targets for maintainers to use: This merges translations into a text file using `msgfmt`. See [custom_target](https://github.com/mesonbuild/meson/wiki/Reference%20manual#custom_target) for normal keywords. In addition it accepts these keywords: * `po_dir`: directory containing translations, relative to current directory +* `data_dirs`: (*Added 0.41.0*) list of directories for its files (See also `i18n.gettext()`) * `type`: type of file, valid options are `'xml'` (default) and `'desktop'` *Added 0.37.0* diff --git a/docs/markdown/index.md b/docs/markdown/index.md index 63bfd55..8e35a4d 100644 --- a/docs/markdown/index.md +++ b/docs/markdown/index.md @@ -12,9 +12,9 @@ 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 +* multiplatform support for Linux, OSX, Windows, GCC, Clang, Visual Studio and others * supported languages include C, C++, Fortran, Java, Rust -* build definitions in a very readable and user friendly non-turing complete DSL +* 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 * built-in multiplatform dependency provider that works together with distro packages @@ -28,6 +28,6 @@ The second way is via IRC. The channel to use is <tt>#mesonbuild</tt> at [Freeno ## 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 <tt>contributing.txt</tt> 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 aa43651..c4bb0d4 100644 --- a/docs/sitemap.txt +++ b/docs/sitemap.txt @@ -62,7 +62,7 @@ index.md Release-notes-for-0.39.0.md Release-notes-for-0.38.0.md Release-notes-for-0.37.0.md - Additionnal.md + Additional.md Release-procedure.md Performance-comparison.md ARM-performance-test.md @@ -74,7 +74,6 @@ index.md Design-rationale.md IndepthTutorial.md In-the-press.md - Meson-design-rationale:-A-proposal-for-a-better-cross-platform-build-system.md Pkg-config-files.md Playground.md Porting-from-autotools.md @@ -85,7 +85,7 @@ def install(sproj): return unpack(sproj, branch, sproj_dir) def run(args): - if len(args) == 0 or args[0] == '-h' or args[0] == '--help': + if not args or args[0] == '-h' or args[0] == '--help': print(sys.argv[0], 'list/install', 'package_name') return 1 command = args[0] diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 389e759..5bb58f5 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -220,7 +220,7 @@ class Backend: raise MesonException('Unknown data type in object list.') return obj_list - def serialise_executable(self, exe, cmd_args, workdir, env={}, + def serialize_executable(self, exe, cmd_args, workdir, env={}, capture=None): import hashlib # Can't just use exe.name here; it will likely be run more than once @@ -265,7 +265,7 @@ class Backend: pickle.dump(es, f) return exe_data - def serialise_tests(self): + def serialize_tests(self): test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat') with open(test_data, 'wb') as datafile: self.write_test_file(datafile) @@ -313,7 +313,9 @@ class Backend: # 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) 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) return [objpath] for osrc in extobj.srclist: @@ -328,7 +330,7 @@ class Backend: includeargs = compiler.get_include_args(pchpath, False) for lang in ['c', 'cpp']: p = target.get_pch(lang) - if len(p) == 0: + if not p: continue if compiler.can_compile(p[-1]): header = p[0] diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 2c3880b..dad752b 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -38,27 +38,13 @@ else: rmfile_prefix = 'rm -f {} &&' def ninja_quote(text): - return text.replace(' ', '$ ').replace(':', '$:') + for char in ('$', ' ', ':'): + text = text.replace(char, '$' + char) + if '\n' in text: + raise MesonException('Ninja does not support newlines in rules. ' + 'Please report this error with a test case to the Meson bug tracker.') + return text -class RawFilename: - """ - Used when a filename is already relative to the root build directory, so - that we know not to add the target's private build directory to it. - """ - def __init__(self, fname): - self.fname = fname - - def __str__(self): - return self.fname - - def __repr__(self): - return '<RawFilename: {0}>'.format(self.fname) - - def split(self, c): - return self.fname.split(c) - - def startswith(self, s): - return self.fname.startswith(s) class NinjaBuildElement: def __init__(self, all_outputs, outfilenames, rule, infilenames): @@ -112,11 +98,12 @@ class NinjaBuildElement: line = line.replace('\\', '/') outfile.write(line) + # All the entries that should remain unquoted + raw_names = {'DEPFILE', 'DESC', 'pool', 'description'} + for e in self.elems: (name, elems) = e - should_quote = True - if name == 'DEPFILE' or name == 'DESC' or name == 'pool': - should_quote = False + should_quote = name not in raw_names line = ' %s = ' % name q_templ = quote_char + "%s" + quote_char noq_templ = "%s" @@ -376,7 +363,8 @@ int dummy; # same time, also deal with generated sources that need to be compiled. generated_source_files = [] for rel_src, gensrc in generated_sources.items(): - raw_src = RawFilename(rel_src) + dirpart, fnamepart = os.path.split(rel_src) + raw_src = File(True, dirpart, fnamepart) if self.environment.is_source(rel_src) and not self.environment.is_header(rel_src): if is_unity and self.get_target_source_can_unity(target, rel_src): unity_deps.append(raw_src) @@ -409,7 +397,8 @@ int dummy; # necessary. This needs to be separate for at least Vala vala_generated_source_files = [] for src in vala_generated_sources: - raw_src = RawFilename(src) + dirpart, fnamepart = os.path.split(src) + raw_src = File(True, dirpart, fnamepart) if is_unity: unity_src.append(os.path.join(self.environment.get_build_dir(), src)) header_deps.append(raw_src) @@ -496,13 +485,17 @@ int dummy; # If the target requires capturing stdout, then use the serialized # executable wrapper to capture that output and save it to a file. # + # If the command line requires a newline, also use the wrapper, as + # ninja does not support them in its build rule syntax. + # # Windows doesn't have -rpath, so for EXEs that need DLLs built within # the project, we need to set PATH so the DLLs are found. We use # a serialized executable wrapper for that and check if the # CustomTarget command needs extra paths first. - if target.capture or ((mesonlib.is_windows() or mesonlib.is_cygwin()) and - self.determine_windows_extra_paths(target.command[0])): - exe_data = self.serialise_executable(target.command[0], cmd[1:], + if (target.capture or any('\n' in c for c in cmd) or + ((mesonlib.is_windows() or mesonlib.is_cygwin()) and + self.determine_windows_extra_paths(target.command[0]))): + exe_data = self.serialize_executable(target.command[0], cmd[1:], # All targets are built from the build dir self.environment.get_build_dir(), capture=ofilenames[0] if target.capture else None) @@ -800,7 +793,7 @@ int dummy; d.install_subdirs.append([src_dir, inst_dir, dst_dir, sd.install_mode]) def generate_tests(self, outfile): - self.serialise_tests() + self.serialize_tests() test_exe = get_meson_script(self.environment, 'mesontest') cmd = [sys.executable, test_exe, '--no-rebuild'] if not self.environment.coredata.get_builtin_option('stdsplit'): @@ -851,7 +844,7 @@ int dummy; quote_char + ninja_quote(self.environment.get_source_dir()) + quote_char, quote_char + ninja_quote(self.environment.get_build_dir()) + quote_char) outfile.write(" command = %s %s %s %s %s %s --backend ninja\n" % c) - outfile.write(' description = Regenerating build files\n') + outfile.write(' description = Regenerating build files.\n') outfile.write(' generator = 1\n\n') outfile.write('\n') @@ -966,7 +959,7 @@ int dummy; def generate_java_link(self, outfile): rule = 'rule java_LINKER\n' command = ' command = jar $ARGS\n' - description = ' description = Creating jar $out.\n' + description = ' description = Creating JAR $out.\n' outfile.write(rule) outfile.write(command) outfile.write(description) @@ -1048,7 +1041,7 @@ int dummy; """Vala is compiled into C. Set up all necessary build steps here.""" (vala_src, vapi_src, other_src) = self.split_vala_sources(target) extra_dep_files = [] - if len(vala_src) == 0: + if not vala_src: msg = 'Vala library {!r} has no Vala source files.' raise InvalidArguments(msg.format(target.name)) @@ -1351,7 +1344,7 @@ int dummy; command = command_template.format( executable=' '.join(cmdlist), output_args=' '.join(static_linker.get_output_args('$out'))) - description = ' description = Static linking library $out\n\n' + description = ' description = Linking static target $out.\n\n' outfile.write(rule) outfile.write(command) outfile.write(description) @@ -1394,7 +1387,7 @@ int dummy; cross_args=' '.join(cross_args), output_args=' '.join(compiler.get_linker_output_args('$out')) ) - description = ' description = Linking target $out' + description = ' description = Linking target $out.' outfile.write(rule) outfile.write(command) outfile.write(description) @@ -1429,7 +1422,7 @@ int dummy; rule = 'rule %s_COMPILER\n' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) command = ' command = %s $ARGS $in\n' % invoc - description = ' description = Compiling cs target $out.\n' + description = ' description = Compiling C Sharp target $out.\n' outfile.write(rule) outfile.write(command) outfile.write(description) @@ -1464,12 +1457,13 @@ int dummy; def generate_swift_compile_rules(self, compiler, outfile): rule = 'rule %s_COMPILER\n' % compiler.get_language() - full_exe = [sys.executable, - self.environment.get_build_command(), + full_exe = [ninja_quote(sys.executable), + ninja_quote(self.environment.get_build_command()), '--internal', 'dirchanger', - '$RUNDIR'] + compiler.get_exelist() - invoc = ' '.join([ninja_quote(i) for i in full_exe]) + '$RUNDIR'] + invoc = (' '.join(full_exe) + ' ' + + ' '.join(ninja_quote(i) for i in compiler.get_exelist())) command = ' command = %s $ARGS $in\n' % invoc description = ' description = Compiling Swift source $in.\n' outfile.write(rule) @@ -1573,7 +1567,7 @@ rule FORTRAN_DEP_HACK output_args=' '.join(compiler.get_output_args('$out')), compile_only_args=' '.join(compiler.get_compile_only_args()) ) - description = ' description = Compiling %s object $out\n' % langname + description = ' description = Compiling %s object $out.\n' % langname.title() if compiler.get_id() == 'msvc': deps = ' deps = msvc\n' else: @@ -1617,7 +1611,7 @@ rule FORTRAN_DEP_HACK output_args=output, compile_only_args=' '.join(compiler.get_compile_only_args()) ) - description = ' description = Precompiling header %s\n' % '$in' + description = ' description = Precompiling header %s.\n' % '$in' if compiler.get_id() == 'msvc': deps = ' deps = msvc\n' else: @@ -1846,8 +1840,11 @@ rule FORTRAN_DEP_HACK # Compiler args for compiling this target commands += compilers.get_base_compile_args(self.environment.coredata.base_options, compiler) - if isinstance(src, (RawFilename, File)): - src_filename = src.fname + if isinstance(src, File): + if src.is_built: + src_filename = os.path.join(src.subdir, src.fname) + else: + src_filename = src.fname elif os.path.isabs(src): src_filename = os.path.basename(src) else: @@ -1856,7 +1853,7 @@ rule FORTRAN_DEP_HACK rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) rel_obj += '.' + self.environment.get_object_suffix() commands += self.get_compile_debugfile_args(compiler, target, rel_obj) - if isinstance(src, RawFilename): + if isinstance(src, File) and src.is_built: rel_src = src.fname elif isinstance(src, File): rel_src = src.rel_to_builddir(self.build_to_src) @@ -1978,13 +1975,7 @@ rule FORTRAN_DEP_HACK """ if isinstance(src, str) and src.endswith('.h'): raise AssertionError('BUG: sources should not contain headers {!r}'.format(src)) - if isinstance(src, RawFilename) and src.fname.endswith('.h'): - raise AssertionError('BUG: sources should not contain headers {!r}'.format(src.fname)) - if isinstance(src, str) and src.endswith('.h'): - raise AssertionError('BUG: sources should not contain headers {!r}'.format(src)) - if isinstance(src, RawFilename) and src.fname.endswith('.h'): - raise AssertionError('BUG: sources should not contain headers {!r}'.format(src.fname)) compiler = get_compiler_for_source(target.compilers.values(), src) key = (target, compiler, is_generated) if key in self.target_arg_cache: @@ -1994,14 +1985,12 @@ rule FORTRAN_DEP_HACK self.target_arg_cache[key] = commands commands = CompilerArgs(commands.compiler, commands) - # FIXME: This file handling is atrocious and broken. We need to - # replace it with File objects used consistently everywhere. - if isinstance(src, RawFilename): - rel_src = src.fname - if os.path.isabs(src.fname): - abs_src = src.fname - else: - abs_src = os.path.join(self.environment.get_build_dir(), src.fname) + 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): rel_src = src.rel_to_builddir(self.build_to_src) abs_src = src.absolute_path(self.environment.get_source_dir(), @@ -2014,8 +2003,14 @@ rule FORTRAN_DEP_HACK else: raise InvalidArguments('Invalid source type: {!r}'.format(src)) abs_src = os.path.join(self.environment.get_build_dir(), rel_src) - if isinstance(src, (RawFilename, File)): - src_filename = src.fname + 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: @@ -2034,7 +2029,7 @@ rule FORTRAN_DEP_HACK pchlist = target.get_pch(compiler.language) else: pchlist = [] - if len(pchlist) == 0: + if not pchlist: pch_dep = [] elif compiler.id == 'intel': pch_dep = [] @@ -2068,16 +2063,16 @@ rule FORTRAN_DEP_HACK element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) for d in header_deps: - if isinstance(d, RawFilename): - d = d.fname + if isinstance(d, File): + d = d.rel_to_builddir(self.build_to_src) elif not self.has_dir_part(d): d = os.path.join(self.get_target_private_dir(target), d) element.add_dep(d) for d in extra_deps: element.add_dep(d) for d in order_deps: - if isinstance(d, RawFilename): - d = d.fname + if isinstance(d, File): + d = d.rel_to_builddir(self.build_to_src) elif not self.has_dir_part(d): d = os.path.join(self.get_target_private_dir(target), d) element.add_orderdep(d) @@ -2094,6 +2089,8 @@ rule FORTRAN_DEP_HACK def has_dir_part(self, fname): # FIXME FIXME: The usage of this is a terrible and unreliable hack + if isinstance(fname, File): + return fname.subdir != '' return '/' in fname or '\\' in fname # Fortran is a bit weird (again). When you link against a library, just compiling a source file @@ -2139,7 +2136,7 @@ rule FORTRAN_DEP_HACK cstr = '_CROSS' for lang in ['c', 'cpp']: pch = target.get_pch(lang) - if len(pch) == 0: + if not pch: continue if '/' not in pch[0] or '/' not in pch[-1]: msg = 'Precompiled header of {!r} must not be in the same ' \ @@ -2360,7 +2357,7 @@ rule FORTRAN_DEP_HACK e.add_item('COMMAND', [sys.executable, self.environment.get_build_command(), '--internal', 'cleantrees', d_file]) - e.add_item('description', 'Cleaning CustomTarget directories') + e.add_item('description', 'Cleaning custom target directories.') e.write(outfile) # Write out the data file passed to the script with open(d_file, 'wb') as ofile: @@ -2372,14 +2369,14 @@ rule FORTRAN_DEP_HACK script_root = self.environment.get_script_dir() clean_script = os.path.join(script_root, 'delwithsuffix.py') gcno_elem.add_item('COMMAND', [sys.executable, clean_script, '.', 'gcno']) - gcno_elem.add_item('description', 'Deleting gcno files') + gcno_elem.add_item('description', 'Deleting gcno files.') gcno_elem.write(outfile) gcda_elem = NinjaBuildElement(self.all_outputs, 'clean-gcda', 'CUSTOM_COMMAND', 'PHONY') script_root = self.environment.get_script_dir() clean_script = os.path.join(script_root, 'delwithsuffix.py') gcda_elem.add_item('COMMAND', [sys.executable, clean_script, '.', 'gcda']) - gcda_elem.add_item('description', 'Deleting gcda files') + gcda_elem.add_item('description', 'Deleting gcda files.') gcda_elem.write(outfile) def get_user_option_args(self): @@ -2388,7 +2385,7 @@ rule FORTRAN_DEP_HACK cmds.append('-D' + k + '=' + (v.value if isinstance(v.value, str) else str(v.value).lower())) # The order of these arguments must be the same between runs of Meson # to ensure reproducible output. The order we pass them shouldn't - # affect behaviour in any other way. + # affect behavior in any other way. return sorted(cmds) # For things like scan-build and other helper tools we might have. @@ -2425,7 +2422,7 @@ rule FORTRAN_DEP_HACK raise MesonException('Could not detect Ninja v1.6 or newer') elem = NinjaBuildElement(self.all_outputs, 'clean', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', [ninja_command, '-t', 'clean']) - elem.add_item('description', 'Cleaning') + elem.add_item('description', 'Cleaning.') # If we have custom targets in this project, add all their outputs to # the list that is passed to the `cleantrees.py` script. The script diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 432bdd0..e910a03 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -443,7 +443,7 @@ class Vs2010Backend(backends.Backend): # Always use a wrapper because MSBuild eats random characters when # there are many arguments. tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) - exe_data = self.serialise_executable(target.command[0], cmd[1:], + exe_data = self.serialize_executable(target.command[0], cmd[1:], # All targets run from the target dir tdir_abs, capture=ofilenames[0] if target.capture else None) @@ -865,7 +865,7 @@ class Vs2010Backend(backends.Backend): pch_sources = {} for lang in ['c', 'cpp']: pch = target.get_pch(lang) - if len(pch) == 0: + if not pch: continue pch_node.text = 'Use' pch_sources[lang] = [pch[0], pch[1], lang] @@ -980,7 +980,7 @@ class Vs2010Backend(backends.Backend): for h in gen_hdrs: ET.SubElement(inc_hdrs, 'CLInclude', Include=h) for h in target.extra_files: - relpath = os.path.join(proj_to_src_dir, h) + relpath = os.path.join(down, h.rel_to_builddir(self.build_to_src)) ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath) if len(sources) + len(gen_src) + len(pch_sources) > 0: @@ -1182,7 +1182,7 @@ endlocal & call :cmErrorLevel %%errorlevel%% & goto :cmDone exit /b %%1 :cmDone if %%errorlevel%% neq 0 goto :VCEnd''' - self.serialise_tests() + self.serialize_tests() ET.SubElement(postbuild, 'Command').text =\ cmd_templ % ('" "'.join(test_command)) ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets') diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 622c802..16c0daf 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -66,7 +66,7 @@ class XCodeBackend(backends.Backend): def generate(self, interp): self.interpreter = interp - test_data = self.serialise_tests()[0] + test_data = self.serialize_tests()[0] self.generate_filemap() self.generate_buildmap() self.generate_buildstylemap() diff --git a/mesonbuild/build.py b/mesonbuild/build.py index a5ebc34..06e6156 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -115,7 +115,7 @@ class Build: self.compilers[lang] = compiler def add_cross_compiler(self, compiler): - if len(self.cross_compilers) == 0: + if not self.cross_compilers: self.static_cross_linker = self.environment.detect_static_linker(compiler) lang = compiler.get_language() if lang not in self.cross_compilers: @@ -340,9 +340,7 @@ class BuildTarget(Target): self.process_objectlist(objects) self.process_kwargs(kwargs, environment) self.check_unknown_kwargs(kwargs) - if len(self.sources) == 0 \ - and len(self.generated) == 0 \ - and len(self.objects) == 0: + 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() @@ -433,7 +431,7 @@ class BuildTarget(Target): We also add compilers that were used by extracted objects to simplify dynamic linker determination. ''' - if len(self.sources) + len(self.generated) + len(self.objects) == 0: + if not self.sources and not self.generated and not self.objects: return # Populate list of compilers if self.is_cross: @@ -488,7 +486,7 @@ class BuildTarget(Target): self.compilers['c'] = compilers['c'] def validate_sources(self): - if len(self.sources) == 0: + if not self.sources: return for lang in ('cs', 'java'): if lang in self.compilers: @@ -650,12 +648,11 @@ class BuildTarget(Target): elif 'gui_app' in kwargs: raise InvalidArguments('Argument gui_app can only be used on executables.') extra_files = kwargs.get('extra_files', []) - if isinstance(extra_files, str): + if not isinstance(extra_files, list): extra_files = [extra_files] for i in extra_files: - if not isinstance(i, str): - raise InvalidArguments('Arguments to extra_files must be strings.') - trial = os.path.join(environment.get_source_dir(), self.subdir, i) + assert(isinstance(i, File)) + trial = os.path.join(environment.get_source_dir(), i.subdir, i.fname) if not(os.path.isfile(trial)): raise InvalidArguments('Tried to add non-existing extra file %s.' % i) self.extra_files = extra_files @@ -675,7 +672,7 @@ class BuildTarget(Target): if 'name_prefix' in kwargs: name_prefix = kwargs['name_prefix'] if isinstance(name_prefix, list): - if len(name_prefix) != 0: + if name_prefix: raise InvalidArguments('name_prefix array must be empty to signify null.') elif not isinstance(name_prefix, str): raise InvalidArguments('name_prefix must be a string.') @@ -684,7 +681,7 @@ class BuildTarget(Target): if 'name_suffix' in kwargs: name_suffix = kwargs['name_suffix'] if isinstance(name_suffix, list): - if len(name_suffix) != 0: + if name_suffix: raise InvalidArguments('name_suffix array must be empty to signify null.') else: if not isinstance(name_suffix, str): @@ -825,7 +822,7 @@ You probably should put it in link_with instead.''') self.link_whole_targets.append(t) def add_pch(self, language, pchlist): - if len(pchlist) == 0: + if not pchlist: return elif len(pchlist) == 1: if not environment.is_header(pchlist[0]): @@ -911,7 +908,14 @@ You probably should put it in link_with instead.''') # Pick a compiler based on the language priority-order for l in clike_langs: if l in self.compilers or l in dep_langs: - return all_compilers[l] + try: + return all_compilers[l] + except KeyError: + raise MesonException( + 'Could not get a dynamic linker for build target {!r}. ' + 'Requires a linker for language "{}", but that is not ' + 'a project language.'.format(self.name, l)) + m = 'Could not get a dynamic linker for build target {!r}' raise AssertionError(m.format(self.name)) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 188bd8f..406c719 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -317,12 +317,12 @@ def get_base_link_args(options, linker, is_shared_module): return args def build_unix_rpath_args(build_dir, rpath_paths, install_rpath): - if len(rpath_paths) == 0 and len(install_rpath) == 0: + if not rpath_paths and not install_rpath: return [] paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) if len(paths) < len(install_rpath): padding = 'X' * (len(install_rpath) - len(paths)) - if len(paths) == 0: + if not paths: paths = padding else: paths = paths + ':' + padding @@ -388,7 +388,7 @@ class CompilerArgs(list): if len(args) > 2: raise TypeError("CompilerArgs() only accepts at most 2 arguments: " "The compiler, and optionally an initial list") - elif len(args) == 0: + elif not args: return cargs elif len(args) == 1: if isinstance(args[0], (Compiler, StaticLinker)): @@ -708,7 +708,7 @@ class Compiler: return self.get_std_shared_lib_link_args() def get_link_whole_for(self, args): - if isinstance(args, list) and len(args) == 0: + if isinstance(args, list) and not args: return [] raise EnvironmentException('Language %s does not support linking whole archives.' % self.language) @@ -761,7 +761,7 @@ class CCompiler(Compiler): def split_shlib_to_parts(self, fname): return None, fname - # The default behaviour is this, override in + # The default behavior is this, override in # OSX and MSVC. def build_rpath_args(self, build_dir, rpath_paths, install_rpath): return build_unix_rpath_args(build_dir, rpath_paths, install_rpath) @@ -782,7 +782,7 @@ class CCompiler(Compiler): return self.exelist[:] def get_preprocess_only_args(self): - return ['-E'] + return ['-E', '-P'] def get_compile_only_args(self): return ['-c'] @@ -1139,10 +1139,10 @@ class CCompiler(Compiler): delim = '"MESON_GET_DEFINE_DELIMITER"' fargs = {'prefix': prefix, 'define': dname, 'delim': delim} code = ''' + {prefix} #ifndef {define} # define {define} #endif - {prefix} {delim}\n{define}''' args = self._get_compiler_check_args(env, extra_args, dependencies, mode='preprocess').to_native() @@ -1360,7 +1360,7 @@ class CCompiler(Compiler): extra_dirs = [extra_dirs] # Gcc + co seem to prefer builtin lib dirs to -L dirs. # Only try to find std libs if no extra dirs specified. - if len(extra_dirs) == 0: + if not extra_dirs: args = ['-l' + libname] if self.links(code, env, extra_args=args): return args @@ -1700,7 +1700,7 @@ class ValaCompiler(Compiler): extra_dirs = [extra_dirs] # Valac always looks in the default vapi dir, so only search there if # no extra dirs are specified. - if len(extra_dirs) == 0: + if not extra_dirs: code = 'class MesonFindLibrary : Object { }' vapi_args = ['--pkg', libname] args = self.get_cross_extra_flags(env, link=False) @@ -1892,12 +1892,12 @@ class DCompiler(Compiler): def build_rpath_args(self, build_dir, rpath_paths, install_rpath): # This method is to be used by LDC and DMD. # GDC can deal with the verbatim flags. - if len(rpath_paths) == 0 and len(install_rpath) == 0: + if not rpath_paths and not install_rpath: return [] paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) if len(paths) < len(install_rpath): padding = 'X' * (len(install_rpath) - len(paths)) - if len(paths) == 0: + if not paths: paths = padding else: paths = paths + ':' + padding @@ -2135,7 +2135,7 @@ class VisualStudioCCompiler(CCompiler): return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)] def get_preprocess_only_args(self): - return ['/E'] + return ['/EP'] def get_compile_only_args(self): return ['/c'] diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py index eb7a5e4..ef7be3a 100644 --- a/mesonbuild/dependencies.py +++ b/mesonbuild/dependencies.py @@ -22,6 +22,7 @@ import re import sys import os, stat, glob, shutil +import shlex import subprocess import sysconfig from enum import Enum @@ -356,13 +357,16 @@ class WxDependency(Dependency): def __init__(self, environment, kwargs): Dependency.__init__(self, 'wx', kwargs) self.is_found = False + # FIXME: use version instead of modversion self.modversion = 'none' if WxDependency.wx_found is None: self.check_wxconfig() if not WxDependency.wx_found: + # FIXME: this message could be printed after Dependncy found mlog.log("Neither wx-config-3.0 nor wx-config found; can't detect dependency") return + # FIXME: This should print stdout and stderr using mlog.debug p, out = Popen_safe([self.wxc, '--version'])[0:2] if p.returncode != 0: mlog.log('Dependency wxwidgets found:', mlog.red('NO')) @@ -382,10 +386,12 @@ class WxDependency(Dependency): # wx-config seems to have a cflags as well but since it requires C++, # this should be good, at least for now. p, out = Popen_safe([self.wxc, '--cxxflags'])[0:2] + # FIXME: this error should only be raised if required is true if p.returncode != 0: raise DependencyException('Could not generate cargs for wxwidgets.') self.cargs = out.split() + # FIXME: this error should only be raised if required is true p, out = Popen_safe([self.wxc, '--libs'] + self.requested_modules)[0:2] if p.returncode != 0: raise DependencyException('Could not generate libs for wxwidgets.') @@ -777,7 +783,7 @@ class BoostDependency(Dependency): else: libdir = [] # Can't find libdir, bail - if len(libdir) == 0: + if not libdir: return libdir = libdir[0] self.libdir = libdir @@ -1021,7 +1027,7 @@ class QtBaseDependency(Dependency): self.is_found = False if isinstance(mods, str): mods = [mods] - if len(mods) == 0: + if not mods: raise DependencyException('No ' + self.qtname + ' modules specified.') type_text = 'cross' if env.is_cross_build() else 'native' found_msg = '{} {} {{}} dependency (modules: {}) found:' \ @@ -1332,7 +1338,7 @@ class AppleFrameworks(Dependency): modules = kwargs.get('modules', []) if isinstance(modules, str): modules = [modules] - if len(modules) == 0: + if not modules: raise DependencyException("AppleFrameworks dependency requires at least one module.") self.frameworks = modules @@ -1607,6 +1613,131 @@ class ValgrindDependency(PkgConfigDependency): def get_link_args(self): return [] +class LLVMDependency(Dependency): + """LLVM dependency. + + LLVM uses a special tool, llvm-config, which has arguments for getting + c args, cxx args, and ldargs as well as version. + """ + + # Ordered list of llvm-config binaries to try. Start with base, then try + # newest back to oldest (3.5 is abitrary), and finally the devel version. + llvm_config_bins = [ + 'llvm-config', 'llvm-config-4.0', 'llvm-config-3.9', 'llvm-config39', + 'llvm-config-3.8', 'llvm-config38', 'llvm-config-3.7', 'llvm-config37', + 'llvm-config-3.6', 'llvm-config36', 'llvm-config-3.5', 'llvm-config35', + 'llvm-config-devel', + ] + llvmconfig = None + _llvmconfig_found = False + __best_found = None + + def __init__(self, environment, kwargs): + super().__init__('llvm-config', kwargs) + # It's necessary for LLVM <= 3.8 to use the C++ linker. For 3.9 and 4.0 + # the C linker works fine if only using the C API. + self.language = 'cpp' + self.cargs = [] + self.libs = [] + self.modules = [] + + required = kwargs.get('required', True) + req_version = kwargs.get('version', None) + if self.llvmconfig is None: + self.check_llvmconfig(req_version) + if not self._llvmconfig_found: + if self.__best_found is not None: + mlog.log('found {!r} but need:'.format(self.version), + req_version) + else: + mlog.log("No llvm-config found; can't detect dependency") + mlog.log('Dependency LLVM found:', mlog.red('NO')) + if required: + raise DependencyException('Dependency LLVM not found') + return + + p, out, err = Popen_safe([self.llvmconfig, '--version']) + if p.returncode != 0: + mlog.debug('stdout: {}\nstderr: {}'.format(out, err)) + if required: + raise DependencyException('Dependency LLVM not found') + return + else: + self.version = out.strip() + mlog.log('Dependency LLVM found:', mlog.green('YES')) + self.is_found = True + + p, out = Popen_safe( + [self.llvmconfig, '--libs', '--ldflags', '--system-libs'])[:2] + if p.returncode != 0: + raise DependencyException('Could not generate libs for LLVM.') + self.libs = shlex.split(out) + + p, out = Popen_safe([self.llvmconfig, '--cppflags'])[:2] + if p.returncode != 0: + raise DependencyException('Could not generate includedir for LLVM.') + self.cargs = shlex.split(out) + + p, out = Popen_safe([self.llvmconfig, '--components'])[:2] + if p.returncode != 0: + raise DependencyException('Could not generate modules for LLVM.') + self.modules = shlex.split(out) + + modules = mesonlib.stringlistify(kwargs.get('modules', [])) + for mod in modules: + if mod not in self.modules: + mlog.log('LLVM module', mod, 'found:', mlog.red('NO')) + self.is_found = False + if required: + raise DependencyException( + 'Could not find required LLVM Component: {}'.format(mod)) + else: + mlog.log('LLVM module', mod, 'found:', mlog.green('YES')) + + def get_version(self): + return self.version + + def get_compile_args(self): + return self.cargs + + def get_link_args(self): + return self.libs + + @classmethod + def check_llvmconfig(cls, version_req): + """Try to find the highest version of llvm-config.""" + for llvmconfig in cls.llvm_config_bins: + try: + p, out = Popen_safe([llvmconfig, '--version'])[0:2] + out = out.strip() + if p.returncode != 0: + continue + if version_req: + if version_compare(out, version_req, strict=True): + if cls.__best_found and version_compare(out, '<={}'.format(cls.__best_found), strict=True): + continue + cls.__best_found = out + cls.llvmconfig = llvmconfig + else: + # If no specific version is requested use the first version + # found, since that should be the best. + cls.__best_found = out + cls.llvmconfig = llvmconfig + break + except (FileNotFoundError, PermissionError): + pass + if cls.__best_found: + mlog.log('Found llvm-config:', + mlog.bold(shutil.which(cls.llvmconfig)), + '({})'.format(out.strip())) + cls._llvmconfig_found = True + else: + cls.llvmconfig = False + + def need_threads(self): + return True + + def get_dep_identifier(name, kwargs): elements = [name] modlist = kwargs.get('modules', []) @@ -1671,4 +1802,5 @@ packages = {'boost': BoostDependency, 'threads': ThreadDependency, 'python3': Python3Dependency, 'valgrind': ValgrindDependency, + 'llvm': LLVMDependency, } diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index b0ba78d..13bbe62 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -872,7 +872,7 @@ class CrossBuildInfo: if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry: raise EnvironmentException('Malformed variable name %s in cross file..' % entry) try: - res = eval(value, {'true': True, 'false': False}) + res = eval(value, {'__builtins__': None}, {'true': True, 'false': False}) except Exception: raise EnvironmentException('Malformed value in cross file variable %s.' % entry) if self.ok_type(res): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index eaaea73..7eb1f26 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1581,7 +1581,7 @@ class Interpreter(InterpreterBase): @noKwargs def func_configuration_data(self, node, args, kwargs): - if len(args) != 0: + if args: raise InterpreterException('configuration_data takes no arguments') return ConfigurationDataHolder() @@ -1818,7 +1818,7 @@ class Interpreter(InterpreterBase): self.coredata.base_options[optname] = oobj def func_find_program(self, node, args, kwargs): - if len(args) == 0: + if not args: raise InterpreterException('No program name specified.') required = kwargs.get('required', True) if not isinstance(required, bool): @@ -2022,9 +2022,11 @@ class Interpreter(InterpreterBase): raise InterpreterException('Unknown target_type.') def func_vcs_tag(self, node, args, kwargs): - fallback = kwargs.pop('fallback', None) + if 'input' not in kwargs or 'output' not in kwargs: + raise InterpreterException('Keyword arguments input and output must exist') + fallback = kwargs.pop('fallback', self.project_version) if not isinstance(fallback, str): - raise InterpreterException('Keyword argument fallback must exist and be a string.') + raise InterpreterException('Keyword argument fallback must be a string.') replace_string = kwargs.pop('replace_string', '@VCS_TAG@') regex_selector = '(.*)' # default regex selector for custom command: use complete output vcs_cmd = kwargs.get('command', None) @@ -2215,10 +2217,12 @@ class Interpreter(InterpreterBase): subdir = os.path.join(prev_subdir, args[0]) if os.path.isabs(subdir): raise InvalidArguments('Subdir argument must be a relative path.') - if subdir in self.visited_subdirs: + absdir = os.path.join(self.environment.get_source_dir(), subdir) + symlinkless_dir = os.path.realpath(absdir) + if symlinkless_dir in self.visited_subdirs: raise InvalidArguments('Tried to enter directory "%s", which has already been visited.' % subdir) - self.visited_subdirs[subdir] = True + self.visited_subdirs[symlinkless_dir] = True self.subdir = subdir os.makedirs(os.path.join(self.environment.build_dir, subdir), exist_ok=True) buildfilename = os.path.join(self.subdir, environment.build_filename) @@ -2533,7 +2537,7 @@ different subdirectory. self.coredata.target_guids[idname] = str(uuid.uuid4()).upper() def build_target(self, node, args, kwargs, targetholder): - if len(args) == 0: + if not args: raise InterpreterException('Target does not have a name.') name = args[0] sources = args[1:] @@ -2554,6 +2558,11 @@ different subdirectory. sources = self.source_strings_to_files(sources) objs = self.flatten(kwargs.get('objects', [])) kwargs['dependencies'] = self.flatten(kwargs.get('dependencies', [])) + if 'extra_files' in kwargs: + ef = kwargs['extra_files'] + if not isinstance(ef, list): + ef = [ef] + kwargs['extra_files'] = self.source_strings_to_files(ef) if not isinstance(objs, list): objs = [objs] self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources) diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index e59557a..86a6b47 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -34,7 +34,7 @@ def check_stringlist(a, msg='Arguments must be strings.'): def noPosargs(f): @wraps(f) def wrapped(self, node, args, kwargs): - if len(args) != 0: + if args: raise InvalidArguments('Function does not take positional arguments.') return f(self, node, args, kwargs) return wrapped @@ -42,7 +42,7 @@ def noPosargs(f): def noKwargs(f): @wraps(f) def wrapped(self, node, args, kwargs): - if len(kwargs) != 0: + if kwargs: raise InvalidArguments('Function does not take keyword arguments.') return f(self, node, args, kwargs) return wrapped @@ -94,7 +94,7 @@ class InterpreterBase: raise InvalidArguments('Missing Meson file in %s' % mesonfile) with open(mesonfile, encoding='utf8') as mf: code = mf.read() - if len(code.strip()) == 0: + if code.isspace(): raise InvalidCode('Builder file is empty.') assert(isinstance(code, str)) try: @@ -113,7 +113,7 @@ class InterpreterBase: def sanity_check_ast(self): if not isinstance(self.ast, mparser.CodeBlockNode): raise InvalidCode('AST is of invalid type. Possibly a bug in the parser.') - if len(self.ast.lines) == 0: + if not self.ast.lines: raise InvalidCode('No statements in code.') first = self.ast.lines[0] if not isinstance(first, mparser.FunctionNode) or first.func_name != 'project': @@ -405,7 +405,7 @@ class InterpreterBase: obj = self.to_native(obj) (posargs, _) = self.reduce_arguments(args) if method_name == 'to_string': - if len(posargs) == 0: + if not posargs: if obj: return 'true' else: @@ -429,12 +429,12 @@ class InterpreterBase: obj = self.to_native(obj) (posargs, _) = self.reduce_arguments(args) if method_name == 'is_even': - if len(posargs) == 0: + if not posargs: return obj % 2 == 0 else: raise InterpreterException('int.is_even() must have no arguments.') elif method_name == 'is_odd': - if len(posargs) == 0: + if not posargs: return obj % 2 != 0 else: raise InterpreterException('int.is_odd() must have no arguments.') diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 2ab5f92..b4add65 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -56,7 +56,7 @@ class Conf: # Ninja is run. def print_aligned(self, arr): - if len(arr) == 0: + if not arr: return titles = ['Option', 'Description', 'Current Value', ''] longest_name = len(titles[0]) @@ -139,7 +139,7 @@ class Conf: print('') print('Base options:') okeys = sorted(self.coredata.base_options.keys()) - if len(okeys) == 0: + if not okeys: print(' No base options\n') else: coarr = [] @@ -158,7 +158,7 @@ class Conf: print('') print('Compiler options:') okeys = sorted(self.coredata.compiler_options.keys()) - if len(okeys) == 0: + if not okeys: print(' No compiler options\n') else: coarr = [] @@ -188,7 +188,7 @@ class Conf: self.print_aligned(parr) print('') print('Project options:') - if len(self.coredata.user_options) == 0: + if not self.coredata.user_options: print(' This project does not have any options') else: options = self.coredata.user_options @@ -197,7 +197,7 @@ class Conf: optarr = [] for key in keys: opt = options[key] - if (opt.choices is None) or (len(opt.choices) == 0): + if (opt.choices is None) or (not opt.choices): # Zero length list or string choices = '' else: @@ -222,7 +222,7 @@ def run(args): print('%s <build directory>' % args[0]) print('If you omit the build directory, the current directory is substituted.') return 1 - if len(options.directory) == 0: + if not options.directory: builddir = os.getcwd() else: builddir = options.directory[0] diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 7e4be7f..bce0965 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -87,8 +87,8 @@ class MesonApp: return os.path.exists(fname) def validate_core_dirs(self, dir1, dir2): - ndir1 = os.path.abspath(dir1) - ndir2 = os.path.abspath(dir2) + ndir1 = os.path.abspath(os.path.realpath(dir1)) + ndir2 = os.path.abspath(os.path.realpath(dir2)) if not os.path.exists(ndir1): os.makedirs(ndir1) if not os.path.exists(ndir2): @@ -222,6 +222,9 @@ def run_script_command(args): elif cmdname == 'gtkdoc': import mesonbuild.scripts.gtkdochelper as abc cmdfunc = abc.run + elif cmdname == 'msgfmthelper': + import mesonbuild.scripts.msgfmthelper as abc + cmdfunc = abc.run elif cmdname == 'regencheck': import mesonbuild.scripts.regen_checker as abc cmdfunc = abc.run @@ -269,10 +272,10 @@ def run(mainfile, args): args = mesonlib.expand_arguments(args) options = parser.parse_args(args) args = options.directories - if len(args) == 0 or len(args) > 2: + if not args or len(args) > 2: # if there's a meson.build in the dir above, and not in the current # directory, assume we're in the build directory - if len(args) == 0 and not os.path.exists('meson.build') and os.path.exists('../meson.build'): + if not args and not os.path.exists('meson.build') and os.path.exists('../meson.build'): dir1 = '..' dir2 = '.' else: diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index b4dfd12..134060f 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -566,7 +566,7 @@ class GnomeModule(ExtensionModule): return ModuleReturnValue(rv, rv) def compile_schemas(self, state, args, kwargs): - if len(args) != 0: + if args: raise MesonException('Compile_schemas does not take positional arguments.') srcdir = os.path.join(state.build_to_src, state.subdir) outdir = state.subdir diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index 5738cb3..c4e29cf 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -49,6 +49,12 @@ PRESET_ARGS = { class I18nModule(ExtensionModule): + @staticmethod + def _get_data_dirs(state, dirs): + """Returns source directories of relative paths""" + src_dir = path.join(state.environment.get_source_dir(), state.subdir) + return [path.join(src_dir, d) for d in dirs] + def merge_file(self, state, args, kwargs): podir = kwargs.pop('po_dir', None) if not podir: @@ -60,8 +66,15 @@ class I18nModule(ExtensionModule): if file_type not in VALID_TYPES: raise MesonException('i18n: "{}" is not a valid type {}'.format(file_type, VALID_TYPES)) - kwargs['command'] = ['msgfmt', '--' + file_type, - '--template', '@INPUT@', '-d', podir, '-o', '@OUTPUT@'] + datadirs = self._get_data_dirs(state, mesonlib.stringlistify(kwargs.pop('data_dirs', []))) + datadirs = '--datadirs=' + ':'.join(datadirs) if datadirs else None + + command = [state.environment.get_build_command(), '--internal', 'msgfmthelper', + '@INPUT@', '@OUTPUT@', file_type, podir] + if datadirs: + command.append(datadirs) + + kwargs['command'] = command ct = build.CustomTarget(kwargs['output'] + '_merge', state.subdir, kwargs) return ModuleReturnValue(ct, [ct]) @@ -72,7 +85,7 @@ class I18nModule(ExtensionModule): raise coredata.MesonException('Can not do gettext because xgettext is not installed.') packagename = args[0] languages = mesonlib.stringlistify(kwargs.get('languages', [])) - datadirs = mesonlib.stringlistify(kwargs.get('data_dirs', [])) + datadirs = self._get_data_dirs(state, mesonlib.stringlistify(kwargs.get('data_dirs', []))) extra_args = mesonlib.stringlistify(kwargs.get('args', [])) preset = kwargs.pop('preset', None) diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py index 16050d7..2de50ba 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -303,9 +303,9 @@ class Elf(DataSizes): # completely unrelated. This has already happened once with X.org. # Thus we want to keep this change as small as possible to minimize # the chance of obliterating other strings. It might still happen - # but our behaviour is identical to what chrpath does and it has + # but our behavior is identical to what chrpath does and it has # been in use for ages so based on that this should be rare. - if len(new_rpath) == 0: + if not new_rpath: self.remove_rpath_entry(entrynum) else: self.bf.seek(rp_off) diff --git a/mesonbuild/scripts/msgfmthelper.py b/mesonbuild/scripts/msgfmthelper.py new file mode 100644 index 0000000..d4deb00 --- /dev/null +++ b/mesonbuild/scripts/msgfmthelper.py @@ -0,0 +1,35 @@ +# Copyright 2016 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. + +import argparse +import subprocess +import os + +parser = argparse.ArgumentParser() +parser.add_argument('input') +parser.add_argument('output') +parser.add_argument('type') +parser.add_argument('podir') +parser.add_argument('--datadirs', default='') + + +def run(args): + options = parser.parse_args(args) + env = None + if options.datadirs: + env = os.environ.copy() + env.update({'GETTEXTDATADIRS': options.datadirs}) + return subprocess.call(['msgfmt', '--' + options.type, '-d', options.podir, + '--template', options.input, '-o', options.output], + env=env) diff --git a/mesonbuild/scripts/uninstall.py b/mesonbuild/scripts/uninstall.py index 85c4bba..1480921 100644 --- a/mesonbuild/scripts/uninstall.py +++ b/mesonbuild/scripts/uninstall.py @@ -36,7 +36,7 @@ def do_uninstall(log): print('\nRemember that files created by custom scripts have not been removed.') def run(args): - if len(args) != 0: + if args: print('Weird error.') return 1 if not os.path.exists(logfile): diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py index 79bd5df..79b00e0 100644 --- a/mesonbuild/wrap/wraptool.py +++ b/mesonbuild/wrap/wraptool.py @@ -135,7 +135,7 @@ def update(name): def info(name): jd = get_result(API_ROOT + 'projects/' + name) versions = jd['versions'] - if len(versions) == 0: + if not versions: print('No available versions of', name) sys.exit(0) print('Available versions of %s:' % name) @@ -162,7 +162,7 @@ def status(): print('', name, 'not up to date. Have %s %d, but %s %d is available.' % (current_branch, current_revision, latest_branch, latest_revision)) def run(args): - if len(args) == 0 or args[0] == '-h' or args[0] == '--help': + if not args or args[0] == '-h' or args[0] == '--help': print_help() return 0 command = args[0] diff --git a/mesontest.py b/mesontest.py index b59d1ed..101ce5f 100755 --- a/mesontest.py +++ b/mesontest.py @@ -364,7 +364,7 @@ TIMEOUT: %4d return False def test_suitable(self, test): - return (len(self.options.include_suites) == 0 or TestHarness.test_in_suites(test, self.options.include_suites)) \ + return (not self.options.include_suites or TestHarness.test_in_suites(test, self.options.include_suites)) \ and not TestHarness.test_in_suites(test, self.options.exclude_suites) def load_suites(self): @@ -610,7 +610,7 @@ def run(args): if options.list: list_tests(th) return 0 - if len(options.args) == 0: + if not options.args: return th.doit() return th.run_special() diff --git a/run_project_tests.py b/run_project_tests.py index bcb375d..1abc199 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -15,6 +15,7 @@ # limitations under the License. from glob import glob +import itertools import os, subprocess, shutil, sys, signal from io import StringIO from ast import literal_eval @@ -282,14 +283,19 @@ def run_test_inprocess(testdir): sys.stderr = mystderr = StringIO() old_cwd = os.getcwd() os.chdir(testdir) + test_log_fname = 'meson-logs/testlog.txt' try: returncode_test = mesontest.run(['--no-rebuild']) + if os.path.exists(test_log_fname): + test_log = open(test_log_fname, errors='ignore').read() + else: + test_log = '' returncode_benchmark = mesontest.run(['--no-rebuild', '--benchmark', '--logbase', 'benchmarklog']) finally: sys.stdout = old_stdout sys.stderr = old_stderr os.chdir(old_cwd) - return max(returncode_test, returncode_benchmark), mystdout.getvalue(), mystderr.getvalue() + return max(returncode_test, returncode_benchmark), mystdout.getvalue(), mystderr.getvalue(), test_log def parse_test_args(testdir): args = [] @@ -356,10 +362,11 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen os.utime(os.path.join(testdir, 'meson.build')) test_start = time.time() # Test in-process - (returncode, tstdo, tstde) = run_test_inprocess(test_build_dir) + (returncode, tstdo, tstde, test_log) = run_test_inprocess(test_build_dir) test_time = time.time() - test_start stdo += tstdo stde += tstde + mesonlog += test_log if should_fail == 'test': if returncode != 0: return TestResult('', BuildStep.test, stdo, stde, mesonlog, gen_time) @@ -367,7 +374,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen if returncode != 0: return TestResult('Running unit tests failed.', BuildStep.test, stdo, stde, mesonlog, gen_time, build_time, test_time) # Do installation, if the backend supports it - if len(install_commands) != 0: + if install_commands: env = os.environ.copy() env['DESTDIR'] = install_dir # Install with subprocess @@ -383,7 +390,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen stde += e if pi.returncode != 0: return TestResult('Running clean failed.', BuildStep.clean, stdo, stde, mesonlog, gen_time, build_time, test_time) - if len(install_commands) == 0: + if not install_commands: return TestResult('', BuildStep.install, '', '', mesonlog, gen_time, build_time, test_time) return TestResult(validate_install(testdir, install_dir, compiler), BuildStep.validate, stdo, stde, mesonlog, gen_time, build_time, test_time) @@ -411,27 +418,30 @@ def have_java(): return False def detect_tests_to_run(): - all_tests = [] - all_tests.append(('common', gather_tests('test cases/common'), False)) - all_tests.append(('failing-meson', gather_tests('test cases/failing'), False)) - all_tests.append(('failing-build', gather_tests('test cases/failing build'), False)) - all_tests.append(('failing-tests', gather_tests('test cases/failing tests'), False)) - all_tests.append(('prebuilt', gather_tests('test cases/prebuilt'), False)) - - all_tests.append(('platform-osx', gather_tests('test cases/osx'), False if mesonlib.is_osx() else True)) - all_tests.append(('platform-windows', gather_tests('test cases/windows'), False if mesonlib.is_windows() or mesonlib.is_cygwin() else True)) - all_tests.append(('platform-linux', gather_tests('test cases/linuxlike'), False if not (mesonlib.is_osx() or mesonlib.is_windows()) else True)) - all_tests.append(('framework', gather_tests('test cases/frameworks'), False if not mesonlib.is_osx() and not mesonlib.is_windows() and not mesonlib.is_cygwin() else True)) - all_tests.append(('java', gather_tests('test cases/java'), False if backend is Backend.ninja and not mesonlib.is_osx() and have_java() else True)) - all_tests.append(('C#', gather_tests('test cases/csharp'), False if backend is Backend.ninja and shutil.which('mcs') else True)) - all_tests.append(('vala', gather_tests('test cases/vala'), False if backend is Backend.ninja and shutil.which('valac') else True)) - all_tests.append(('rust', gather_tests('test cases/rust'), False if backend is Backend.ninja and shutil.which('rustc') else True)) - all_tests.append(('d', gather_tests('test cases/d'), False if backend is Backend.ninja and have_d_compiler() else True)) - all_tests.append(('objective c', gather_tests('test cases/objc'), False if backend in (Backend.ninja, Backend.xcode) and not mesonlib.is_windows() else True)) - all_tests.append(('fortran', gather_tests('test cases/fortran'), False if backend is Backend.ninja and shutil.which('gfortran') else True)) - all_tests.append(('swift', gather_tests('test cases/swift'), False if backend in (Backend.ninja, Backend.xcode) and shutil.which('swiftc') else True)) - all_tests.append(('python3', gather_tests('test cases/python3'), False if backend is Backend.ninja and shutil.which('python3') else True)) - return all_tests + # Name, subdirectory, skip condition. + all_tests = [ + ('common', 'common', False), + ('failing-meson', 'failing', False), + ('failing-build', 'failing build', False), + ('failing-tests', 'failing tests', False), + ('prebuilt', 'prebuilt', False), + + ('platform-osx', 'osx', not mesonlib.is_osx()), + ('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()), + ('platform-linux', 'linuxlike', mesonlib.is_osx() or mesonlib.is_windows()), + + ('framework', 'frameworks', mesonlib.is_osx() or mesonlib.is_windows() or mesonlib.is_cygwin()), + ('java', 'java', backend is not Backend.ninja or mesonlib.is_osx() or not have_java()), + ('C#', 'csharp', backend is not Backend.ninja or not shutil.which('mcs')), + ('vala', 'vala', backend is not Backend.ninja or not shutil.which('valac')), + ('rust', 'rust', backend is not Backend.ninja or not shutil.which('rustc')), + ('d', 'd', backend is not Backend.ninja or not have_d_compiler()), + ('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or mesonlib.is_windows()), + ('fortran', 'fortran', backend is not Backend.ninja or not shutil.which('gfortran')), + ('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')), + ('python3', 'python3', backend is not Backend.ninja or not shutil.which('python3')), + ] + return [(name, gather_tests('test cases/' + subdir), skip) for name, subdir, skip in all_tests] def run_tests(all_tests, log_name_base, extra_args): global stop, executor, futures @@ -642,4 +652,10 @@ if __name__ == '__main__': print('\nMesonlogs of failing tests\n') for l in failing_logs: print(l, '\n') + for name, dirs, skip in all_tests: + dirs = (os.path.basename(x) for x in dirs) + for k, g in itertools.groupby(dirs, key=lambda x: x.split()[0]): + tests = list(g) + if len(tests) != 1: + print('WARNING: The %s suite contains duplicate "%s" tests: "%s"' % (name, k, '", "'.join(tests))) sys.exit(failing_tests) diff --git a/run_unittests.py b/run_unittests.py index 1d80aac..d285e6a 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1246,7 +1246,7 @@ class LinuxlikeTests(BasePlatformTests): raise unittest.SkipTest('QMake not found') # For some inexplicable reason qmake --version gives different # results when run from the command line vs invoked by Python. - # Check for both cases in case this behaviour changes in the future. + # Check for both cases in case this behavior changes in the future. output = subprocess.getoutput(['qmake', '--version']) if 'Qt version 5' not in output and 'qt5' not in output: raise unittest.SkipTest('Qmake found, but it is not for Qt 5.') diff --git a/test cases/common/140 get define/meson.build b/test cases/common/140 get define/meson.build index 339e37a..9342340 100644 --- a/test cases/common/140 get define/meson.build +++ b/test cases/common/140 get define/meson.build @@ -20,6 +20,15 @@ foreach lang : ['c', 'cpp'] error('Please report a bug and help us improve support for this platform') endif + if cc.find_library('z', required : false).found() + # When a C file containing #include <foo.h> is pre-processed and foo.h is + # found in the compiler's default search path, GCC inserts an extra comment + # between the delimiter and the define which causes a parsing error. + # https://github.com/mesonbuild/meson/issues/1726 + ver = cc.get_define('ZLIB_VER_MAJOR', prefix : '#include <zlib.h>') + assert(ver == '1', 'ZLIB_VER_MAJOR value is "@0@" instead of "1"'.format(ver)) + endif + # Check that an undefined value is empty. have = cc.get_define('MESON_FAIL_VALUE') assert(have == '', 'MESON_FAIL_VALUE value is "@0@" instead of ""'.format(have)) diff --git a/test cases/common/141 mesonintrospect from scripts/check_env.py b/test cases/common/147 mesonintrospect from scripts/check_env.py index dc8ad63..dc8ad63 100644 --- a/test cases/common/141 mesonintrospect from scripts/check_env.py +++ b/test cases/common/147 mesonintrospect from scripts/check_env.py diff --git a/test cases/common/141 mesonintrospect from scripts/meson.build b/test cases/common/147 mesonintrospect from scripts/meson.build index f78710b..f78710b 100644 --- a/test cases/common/141 mesonintrospect from scripts/meson.build +++ b/test cases/common/147 mesonintrospect from scripts/meson.build diff --git a/test cases/common/139 custom target multiple outputs/generator.py b/test cases/common/148 custom target multiple outputs/generator.py index 39dbd11..39dbd11 100755 --- a/test cases/common/139 custom target multiple outputs/generator.py +++ b/test cases/common/148 custom target multiple outputs/generator.py diff --git a/test cases/common/139 custom target multiple outputs/installed_files.txt b/test cases/common/148 custom target multiple outputs/installed_files.txt index 21e1249..21e1249 100644 --- a/test cases/common/139 custom target multiple outputs/installed_files.txt +++ b/test cases/common/148 custom target multiple outputs/installed_files.txt diff --git a/test cases/common/139 custom target multiple outputs/meson.build b/test cases/common/148 custom target multiple outputs/meson.build index 6412864..6412864 100644 --- a/test cases/common/139 custom target multiple outputs/meson.build +++ b/test cases/common/148 custom target multiple outputs/meson.build diff --git a/test cases/common/149 special characters/check_quoting.py b/test cases/common/149 special characters/check_quoting.py new file mode 100644 index 0000000..d6e50ea --- /dev/null +++ b/test cases/common/149 special characters/check_quoting.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import sys + +expected = { + 'newline': '\n', + 'dollar': '$', + 'colon': ':', + 'space': ' ', + 'multi1': ' ::$$ ::$$', + 'multi2': ' ::$$\n\n \n\n::$$', +} + +output = None + +for arg in sys.argv[1:]: + try: + name, value = arg.split('=', 1) + except ValueError: + output = arg + continue + + if expected[name] != value: + raise RuntimeError('{!r} is {!r} but should be {!r}'.format(name, value, expected[name])) + +if output is not None: + with open(output, 'w') as f: + f.write('Success!') diff --git a/test cases/common/149 special characters/installed_files.txt b/test cases/common/149 special characters/installed_files.txt new file mode 100644 index 0000000..f677881 --- /dev/null +++ b/test cases/common/149 special characters/installed_files.txt @@ -0,0 +1,2 @@ +usr/share/result +usr/share/result2 diff --git a/test cases/common/149 special characters/meson.build b/test cases/common/149 special characters/meson.build new file mode 100644 index 0000000..ecba650 --- /dev/null +++ b/test cases/common/149 special characters/meson.build @@ -0,0 +1,37 @@ +project('ninja special characters' ,'c') + +python = import('python3').find_python() + +# Without newlines, this should appear directly in build.ninja. +gen = custom_target('gen', + command : [ + python, + files('check_quoting.py'), + 'dollar=$', + 'colon=:', + 'space= ', + '''multi1= ::$$ ::$$''', + '@OUTPUT@'], + output : 'result', + install : true, + install_dir : get_option('datadir')) + +# With newlines, this should go through the exe wrapper. +gen2 = custom_target('gen2', + command : [ + python, + files('check_quoting.py'), + '''newline= +''', + 'dollar=$', + 'colon=:', + 'space= ', + '''multi2= ::$$ + + + +::$$''', + '@OUTPUT@'], + output : 'result2', + install : true, + install_dir : get_option('datadir')) diff --git a/test cases/common/73 vcstag/meson.build b/test cases/common/73 vcstag/meson.build index 001b42d..7e5983a 100644 --- a/test cases/common/73 vcstag/meson.build +++ b/test cases/common/73 vcstag/meson.build @@ -9,6 +9,10 @@ output : 'vcstag-custom.c', command : ['git', 'show-ref', '-s', 'refs/heads/master'], fallback : '1.0.0') +version_src_fallback = vcs_tag(input : 'vcstag.c.in', +output : 'vcstag-fallback.c') + executable('tagprog', 'tagprog.c', version_src) executable('tagprog-custom', 'tagprog.c', version_src_custom) +executable('tagprog-fallback', 'tagprog.c', version_src_fallback) diff --git a/test cases/failing/42 abs subdir/bob/meson.build b/test cases/failing/45 abs subdir/bob/meson.build index 7bbf4b2..7bbf4b2 100644 --- a/test cases/failing/42 abs subdir/bob/meson.build +++ b/test cases/failing/45 abs subdir/bob/meson.build diff --git a/test cases/failing/42 abs subdir/meson.build b/test cases/failing/45 abs subdir/meson.build index 8c23224..8c23224 100644 --- a/test cases/failing/42 abs subdir/meson.build +++ b/test cases/failing/45 abs subdir/meson.build diff --git a/test cases/failing/42 abspath to srcdir/meson.build b/test cases/failing/46 abspath to srcdir/meson.build index 964a19b..964a19b 100644 --- a/test cases/failing/42 abspath to srcdir/meson.build +++ b/test cases/failing/46 abspath to srcdir/meson.build diff --git a/test cases/frameworks/15 llvm/meson.build b/test cases/frameworks/15 llvm/meson.build new file mode 100644 index 0000000..582ff37 --- /dev/null +++ b/test cases/frameworks/15 llvm/meson.build @@ -0,0 +1,10 @@ +project('llvmtest', ['c', 'cpp'], default_options : ['c_std=c99']) + +llvm_dep = dependency( + 'llvm', + modules : ['bitwriter', 'asmprinter', 'executionengine', 'target', + 'mcjit', 'nativecodegen'], + required : true, +) + +executable('sum', 'sum.c', dependencies : llvm_dep) diff --git a/test cases/frameworks/15 llvm/sum.c b/test cases/frameworks/15 llvm/sum.c new file mode 100644 index 0000000..a93588e --- /dev/null +++ b/test cases/frameworks/15 llvm/sum.c @@ -0,0 +1,76 @@ +/** This code is public domain, and taken from + * https://github.com/paulsmith/getting-started-llvm-c-api/blob/master/sum.c + */ +/** + * LLVM equivalent of: + * + * int sum(int a, int b) { + * return a + b; + * } + */ + +#include <llvm-c/Core.h> +#include <llvm-c/ExecutionEngine.h> +#include <llvm-c/Target.h> +#include <llvm-c/Analysis.h> +#include <llvm-c/BitWriter.h> + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> + +int main(int argc, char const *argv[]) { + LLVMModuleRef mod = LLVMModuleCreateWithName("my_module"); + + LLVMTypeRef param_types[] = { LLVMInt32Type(), LLVMInt32Type() }; + LLVMTypeRef ret_type = LLVMFunctionType(LLVMInt32Type(), param_types, 2, 0); + LLVMValueRef sum = LLVMAddFunction(mod, "sum", ret_type); + + LLVMBasicBlockRef entry = LLVMAppendBasicBlock(sum, "entry"); + + LLVMBuilderRef builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(builder, entry); + LLVMValueRef tmp = LLVMBuildAdd(builder, LLVMGetParam(sum, 0), LLVMGetParam(sum, 1), "tmp"); + LLVMBuildRet(builder, tmp); + + char *error = NULL; + LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); + LLVMDisposeMessage(error); + + LLVMExecutionEngineRef engine; + error = NULL; + LLVMLinkInMCJIT(); + LLVMInitializeNativeAsmPrinter(); + LLVMInitializeNativeTarget(); + if (LLVMCreateExecutionEngineForModule(&engine, mod, &error) != 0) { + fprintf(stderr, "failed to create execution engine\n"); + abort(); + } + if (error) { + fprintf(stderr, "error: %s\n", error); + LLVMDisposeMessage(error); + exit(EXIT_FAILURE); + } + + if (argc < 3) { + fprintf(stderr, "usage: %s x y\n", argv[0]); + exit(EXIT_FAILURE); + } + long long x = strtoll(argv[1], NULL, 10); + long long y = strtoll(argv[2], NULL, 10); + + LLVMGenericValueRef args[] = { + LLVMCreateGenericValueOfInt(LLVMInt32Type(), x, 0), + LLVMCreateGenericValueOfInt(LLVMInt32Type(), y, 0) + }; + LLVMGenericValueRef res = LLVMRunFunction(engine, sum, 2, args); + printf("%d\n", (int)LLVMGenericValueToInt(res, 0)); + + // Write out bitcode to file + if (LLVMWriteBitcodeToFile(mod, "sum.bc") != 0) { + fprintf(stderr, "error writing bitcode to file, skipping\n"); + } + + LLVMDisposeBuilder(builder); + LLVMDisposeExecutionEngine(engine); +} |