diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 04083427b499..45d85b7e9a45 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -91,9 +91,15 @@ jobs: libjsoncpp19,^ librhash0,^ libuv1,^ + libxml2,^ + libxml2-devel,^ + libxslt,^ + libxslt-devel,^ ninja,^ python2-devel,^ python3-devel,^ + python3-libxml2,^ + python3-libxslt,^ python36-pip,^ vala,^ wget,^ @@ -102,8 +108,8 @@ jobs: displayName: Install Dependencies - script: | set PATH=%CYGWIN_ROOT%\bin;%SYSTEMROOT%\system32 - env.exe -- python3 -m pip --disable-pip-version-check install pefile pytest-xdist jsonschema - displayName: pip install pefile pytest-xdist jsonschema + env.exe -- python3 -m pip --disable-pip-version-check install gcovr pefile pytest-xdist jsonschema + displayName: pip install gcovr pefile pytest-xdist jsonschema - script: | set BOOST_ROOT= set PATH=%CYGWIN_ROOT%\bin;%SYSTEMROOT%\system32 @@ -165,14 +171,17 @@ jobs: git ^ mercurial ^ mingw-w64-$(MSYS2_ARCH)-cmake ^ + mingw-w64-$(MSYS2_ARCH)-lcov ^ + mingw-w64-$(MSYS2_ARCH)-libxml2 ^ mingw-w64-$(MSYS2_ARCH)-ninja ^ mingw-w64-$(MSYS2_ARCH)-pkg-config ^ mingw-w64-$(MSYS2_ARCH)-python2 ^ mingw-w64-$(MSYS2_ARCH)-python3 ^ + mingw-w64-$(MSYS2_ARCH)-python3-lxml ^ mingw-w64-$(MSYS2_ARCH)-python3-setuptools ^ mingw-w64-$(MSYS2_ARCH)-python3-pip ^ %TOOLCHAIN% - %MSYS2_ROOT%\usr\bin\bash -lc "python3 -m pip --disable-pip-version-check install pefile jsonschema" + %MSYS2_ROOT%\usr\bin\bash -lc "python3 -m pip --disable-pip-version-check install gcovr jsonschema pefile" displayName: Install Dependencies - script: | set BOOST_ROOT= diff --git a/ci/ciimage/arch/install.sh b/ci/ciimage/arch/install.sh index 6cbbb27b0ac2..fb27c2619b1b 100755 --- a/ci/ciimage/arch/install.sh +++ b/ci/ciimage/arch/install.sh @@ -17,7 +17,7 @@ pkgs=( ) aur_pkgs=(scalapack) -pip_pkgs=(hotdoc) +pip_pkgs=(hotdoc gcovr) cleanup_pkgs=(go) AUR_USER=docker diff --git a/ci/ciimage/bionic/install.sh b/ci/ciimage/bionic/install.sh index 47deb2a5d487..0bfcdfb3f184 100755 --- a/ci/ciimage/bionic/install.sh +++ b/ci/ciimage/bionic/install.sh @@ -15,6 +15,7 @@ pkgs=( qt4-linguist-tools qt5-default qtbase5-private-dev python-dev libomp-dev + llvm lcov ldc libclang-dev libgcrypt20-dev @@ -45,7 +46,7 @@ done # packages eatmydata apt-get -y install "${pkgs[@]}" -eatmydata python3 -m pip install codecov jsonschema +eatmydata python3 -m pip install codecov gcovr jsonschema # Install the ninja 0.10 wget https://github.com/ninja-build/ninja/releases/download/v1.10.0/ninja-linux.zip diff --git a/ci/ciimage/eoan/install.sh b/ci/ciimage/eoan/install.sh index 7d7a1fde8b0a..36dec72b16b2 100755 --- a/ci/ciimage/eoan/install.sh +++ b/ci/ciimage/eoan/install.sh @@ -18,6 +18,7 @@ pkgs=( qt4-linguist-tools python-dev libomp-dev + llvm lcov dub ldc mingw-w64 mingw-w64-tools nim libclang-dev @@ -42,7 +43,7 @@ eatmydata apt-get -y build-dep meson eatmydata apt-get -y install "${pkgs[@]}" eatmydata apt-get -y install --no-install-recommends wine-stable # Wine is special -eatmydata python3 -m pip install hotdoc codecov jsonschema +eatmydata python3 -m pip install hotdoc codecov gcovr jsonschema # dub stuff dub_fetch urld diff --git a/ci/ciimage/fedora/install.sh b/ci/ciimage/fedora/install.sh index f61d97e01523..3beb11cf01fd 100755 --- a/ci/ciimage/fedora/install.sh +++ b/ci/ciimage/fedora/install.sh @@ -21,7 +21,7 @@ dnf -y upgrade # Install deps dnf -y install "${pkgs[@]}" -python3 -m pip install hotdoc gobject PyGObject +python3 -m pip install hotdoc gcovr gobject PyGObject # Cleanup dnf -y clean all diff --git a/ci/ciimage/opensuse/install.sh b/ci/ciimage/opensuse/install.sh index b9e440d0b998..4c8e7705eb09 100755 --- a/ci/ciimage/opensuse/install.sh +++ b/ci/ciimage/opensuse/install.sh @@ -7,7 +7,7 @@ source /ci/common.sh pkgs=( python3-setuptools python3-wheel python3-pip python3-pytest-xdist python3 python3-lxml ninja make git autoconf automake patch python3-Cython python3-jsonschema - elfutils gcc gcc-c++ gcc-fortran gcc-objc gcc-obj-c++ vala rust bison flex curl + elfutils gcc gcc-c++ gcc-fortran gcc-objc gcc-obj-c++ vala rust bison flex curl lcov mono-core gtkmm3-devel gtest gmock protobuf-devel wxGTK3-3_2-devel gobject-introspection-devel itstool gtk3-devel java-15-openjdk-devel gtk-doc llvm-devel clang-devel libSDL2-devel graphviz-devel zlib-devel zlib-devel-static #hdf5-devel netcdf-devel libscalapack2-openmpi3-devel libscalapack2-gnu-openmpi3-hpc-devel openmpi3-devel @@ -26,7 +26,7 @@ zypper --non-interactive update # Install deps zypper install -y "${pkgs[@]}" -python3 -m pip install hotdoc gobject PyGObject +python3 -m pip install hotdoc gcovr gobject PyGObject echo 'export PKG_CONFIG_PATH="/usr/lib64/mpi/gcc/openmpi3/lib64/pkgconfig:$PKG_CONFIG_PATH"' >> /ci/env_vars.sh diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md index 3aecae18cb2e..615b30224b98 100644 --- a/docs/markdown/Commands.md +++ b/docs/markdown/Commands.md @@ -183,21 +183,7 @@ optional arguments: --no-tests Do not build and test generated packages. ``` -This creates a file called `projectname-version.tar.xz` in the build -tree subdirectory `meson-dist`. This archive contains the full -contents of the latest commit in revision control including all the -submodules (recursively). All revision control metadata is removed. -Meson then takes -this archive and tests that it works by doing a full compile + test + -install cycle. If all these pass, Meson will then create a SHA-256 -checksum file next to the archive. - -**Note**: Meson behaviour is different from Autotools. The Autotools -"dist" target packages up the current source tree. Meson packages -the latest revision control commit. The reason for this is that it -prevents developers from doing accidental releases where the -distributed archive does not match any commit in revision control -(especially the one tagged for the release). +See [notes about creating releases](Creating-releases.md) for more info. #### Examples: @@ -310,7 +296,7 @@ meson introspect builddir $ meson install [-h] [-C WD] [--no-rebuild] [--only-changed] [--quiet] ``` -Installs the project to the prefix specified in `setup`. +Installs the project to the prefix specified in [`setup`](#setup). ``` optional arguments: @@ -325,7 +311,7 @@ See [the installation documentation](Installing.md) for more info. #### Examples: -Install project to `prefix` (see [`setup`](#setup)): +Install project to `prefix`: ``` meson install -C builddir ``` diff --git a/docs/markdown/Configuring-a-build-directory.md b/docs/markdown/Configuring-a-build-directory.md index 1387a465bfe3..330899f79c2f 100644 --- a/docs/markdown/Configuring-a-build-directory.md +++ b/docs/markdown/Configuring-a-build-directory.md @@ -109,11 +109,11 @@ you would issue the following command. meson configure -Dprefix=/tmp/testroot -Then you would run your build command (usually `ninja`), which would +Then you would run your build command (usually `meson compile`), which would cause Meson to detect that the build setup has changed and do all the work required to bring your build tree up to date. Since 0.50.0, it is also possible to get a list of all build options -by invoking `meson configure` with the project source directory or +by invoking [`meson configure`](Commands.md#configure) with the project source directory or the path to the root `meson.build`. In this case, meson will print the default values of all options similar to the example output from above. diff --git a/docs/markdown/Continuous-Integration.md b/docs/markdown/Continuous-Integration.md index 0846f2d6f492..76a05a3e85ec 100644 --- a/docs/markdown/Continuous-Integration.md +++ b/docs/markdown/Continuous-Integration.md @@ -36,8 +36,8 @@ script: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo FROM YOUR/REPO:eoan > 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 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 + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true CC=$CC CXX=$CXX meson builddir && meson test -C builddir"; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) meson builddir && meson test -C builddir; fi ``` ## CircleCi for Linux (with Docker) @@ -69,7 +69,7 @@ jobs: steps: - checkout - run: meson setup builddir --backend ninja - - run: ninja -C builddir + - run: meson compile -C builddir - run: meson test -C builddir meson_debian_build: @@ -77,7 +77,7 @@ jobs: steps: - checkout - run: meson setup builddir --backend ninja - - run: ninja -C builddir + - run: meson compile -C builddir - run: meson test -C builddir meson_fedora_build: @@ -85,7 +85,7 @@ jobs: steps: - checkout - run: meson setup builddir --backend ninja - - run: ninja -C builddir + - run: meson compile -C builddir - run: meson test -C builddir workflows: @@ -138,10 +138,10 @@ install: build_script: - cmd: echo Building on %arch% with %compiler% - cmd: meson --backend=ninja builddir - - cmd: ninja -C builddir + - cmd: meson compile -C builddir test_script: - - cmd: ninja -C builddir test + - cmd: meson test -C builddir ``` ### Qt @@ -187,8 +187,8 @@ install: script: - meson builddir - - ninja -C builddir - - ninja -C builddir test + - meson compile -C builddir + - meson test -C builddir ``` ## GitHub Actions diff --git a/docs/markdown/Creating-OSX-packages.md b/docs/markdown/Creating-OSX-packages.md index bda06a36a8d1..849d5fd5de5b 100644 --- a/docs/markdown/Creating-OSX-packages.md +++ b/docs/markdown/Creating-OSX-packages.md @@ -39,7 +39,7 @@ $ meson --prefix=/tmp/myapp.app \ ``` -Now when we do `ninja install` the bundle is properly staged. If you +Now when we do `meson install` the bundle is properly staged. If you have any resource files or data, you need to install them into `Contents/Resources` either by custom install commands or specifying more install paths to the Meson command. diff --git a/docs/markdown/Creating-releases.md b/docs/markdown/Creating-releases.md index 45c4b4ee2bbd..efaa85a2fdc3 100644 --- a/docs/markdown/Creating-releases.md +++ b/docs/markdown/Creating-releases.md @@ -10,9 +10,17 @@ or zip format) of the source code. They do not contain any revision control metadata, only the source code. Meson provides a simple way of generating these. It consists of a -single command: +single command *(available since 0.52.0)*: - ninja dist +```sh +meson dist +``` + +or alternatively (on older meson versions with `ninja` backend): + +```sh +ninja dist +``` This creates a file called `projectname-version.tar.xz` in the build tree subdirectory `meson-dist`. This archive contains the full diff --git a/docs/markdown/Cross-compilation.md b/docs/markdown/Cross-compilation.md index 1c53dcf3fccf..d86d417abaa3 100644 --- a/docs/markdown/Cross-compilation.md +++ b/docs/markdown/Cross-compilation.md @@ -222,7 +222,7 @@ Once you have the cross file, starting a build is simple $ meson srcdir builddir --cross-file cross_file.txt ``` -Once configuration is done, compilation is started by invoking Ninja +Once configuration is done, compilation is started by invoking `meson compile` in the usual way. ## Introspection and system checks diff --git a/docs/markdown/Design-rationale.md b/docs/markdown/Design-rationale.md index 57aaee470f6a..71211923d24d 100644 --- a/docs/markdown/Design-rationale.md +++ b/docs/markdown/Design-rationale.md @@ -223,11 +223,11 @@ 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 +installable, so running `meson 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 not be installed, but instead it is added to the list -of unit tests, which can be run with the command `ninja test`. +of unit tests, which can be run with the command `meson test`. Above we mentioned precompiled headers as a feature not supported by other build systems. Here's how you would use them. diff --git a/docs/markdown/FAQ.md b/docs/markdown/FAQ.md index 7b5c03a37170..7a414431d1b6 100644 --- a/docs/markdown/FAQ.md +++ b/docs/markdown/FAQ.md @@ -51,7 +51,7 @@ $ /path/to/meson.py After this you don't have to care about invoking Meson any more. It remembers where it was originally invoked from and calls itself appropriately. As a user the only thing you need to do is to `cd` into -your build directory and invoke `ninja`. +your build directory and invoke `meson compile`. ## Why can't I specify target files with a wildcard? diff --git a/docs/markdown/Feature-autodetection.md b/docs/markdown/Feature-autodetection.md index c1b7659bc707..a568313e8855 100644 --- a/docs/markdown/Feature-autodetection.md +++ b/docs/markdown/Feature-autodetection.md @@ -34,6 +34,6 @@ also generated which will produce all 3 coverage report types, if possible. Note that generating any of the coverage reports described above -requires the tests (i.e. `ninja test`) to finish running so the +requires the tests (i.e. `meson test`) to finish running so the information about the functions that are called in the tests can be gathered for the report. diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md index ced8a40c4429..3d06233d388c 100644 --- a/docs/markdown/Gnome-module.md +++ b/docs/markdown/Gnome-module.md @@ -223,7 +223,7 @@ directory. Note that this is not for installing schemas and is only useful when running the application locally for example during tests. * `build_by_default`: causes, when set to true, to have this target be - built by default, that is, when invoking plain `ninja`, the default + built by default, that is, when invoking plain `meson compile`, the default value is true for all built target types * `depend_files`: files ([`string`](Reference-manual.md#string-object), [`files()`](Reference-manual.md#files), or @@ -246,7 +246,7 @@ one XML file. * `annotations`: *(Added 0.43.0)* list of lists of 3 strings for the annotation for `'ELEMENT', 'KEY', 'VALUE'` * `docbook`: *(Added 0.43.0)* prefix to generate `'PREFIX'-NAME.xml` docbooks * `build_by_default`: causes, when set to true, to have this target be - built by default, that is, when invoking plain `ninja`, the default + built by default, that is, when invoking plain `meson compile`, the default value is true for all built target types * `install_dir`: (*Added 0.46.0*) location to install the header or bundle depending on previous options diff --git a/docs/markdown/IDE-integration.md b/docs/markdown/IDE-integration.md index f51075e24924..2cc4f4f984b6 100644 --- a/docs/markdown/IDE-integration.md +++ b/docs/markdown/IDE-integration.md @@ -227,8 +227,8 @@ in the `meson.build`. ## Tests -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 +Compilation and unit tests are done as usual by running the `meson compile` and +`meson 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 diff --git a/docs/markdown/IndepthTutorial.md b/docs/markdown/IndepthTutorial.md index dd93f826ba7a..d2e26626f863 100644 --- a/docs/markdown/IndepthTutorial.md +++ b/docs/markdown/IndepthTutorial.md @@ -79,12 +79,12 @@ With these four files we are done. To configure, build and run the test suite, w ```console $ meson builddir && cd builddir -$ ninja -$ ninja test +$ meson compile +$ meson test ``` To then install the project you only need one command. ```console -$ ninja install +$ meson install ``` diff --git a/docs/markdown/Installing.md b/docs/markdown/Installing.md index 5abfdd452337..9dc2ad438709 100644 --- a/docs/markdown/Installing.md +++ b/docs/markdown/Installing.md @@ -4,6 +4,18 @@ short-description: Installing targets # Installing +Invoked via the [following command](Commands.md#install) *(available since 0.47.0)*: + +```sh +meson install +``` + +or alternatively (on older meson versions with `ninja` backend): + +```sh +ninja install +``` + By default Meson will not install anything. Build targets can be installed by tagging them as installable in the definition. @@ -97,15 +109,13 @@ packages. This is done with the `DESTDIR` environment variable and it is used just like with other build systems: ```console -$ DESTDIR=/path/to/staging/area ninja install +$ DESTDIR=/path/to/staging/area meson install ``` ## Custom install behaviour -The default install target (executed via, e.g., `ninja install`) does -installing with reasonable default options. More control over the -install behaviour can be achieved with the `meson install` command, -that has been available since 0.47.0. +Installation behaviour can be further customized using +additional arguments. For example, if you wish to install the current setup without rebuilding the code (which the default install target always does) and diff --git a/docs/markdown/Meson-sample.md b/docs/markdown/Meson-sample.md index 6f26f3642bbd..f98e022a4a7e 100644 --- a/docs/markdown/Meson-sample.md +++ b/docs/markdown/Meson-sample.md @@ -50,7 +50,7 @@ exe = executable('myexe', src) test('simple test', exe) ``` -Here we create a unit test called *simple test*, and which uses the built executable. When the tests are run with the `ninja test` command, the built executable is run. If it returns zero, the test passes. A non-zero return value indicates an error, which Meson will then report to the user. +Here we create a unit test called *simple test*, and which uses the built executable. When the tests are run with the `meson test` command, the built executable is run. If it returns zero, the test passes. A non-zero return value indicates an error, which Meson will then report to the user. A note to Visual Studio users ----- diff --git a/docs/markdown/Project-templates.md b/docs/markdown/Project-templates.md index 832cd1d5a856..7ded318b7487 100644 --- a/docs/markdown/Project-templates.md +++ b/docs/markdown/Project-templates.md @@ -16,8 +16,8 @@ $ meson init --language=c --name=myproject --version=0.1 ``` This would create the build definitions for a helloworld type -project. The result can be compiled as usual. For example compiling it -with Ninja could be done like this: +project. The result can be compiled as usual. For example it +could be done like this: ``` $ meson setup builddir diff --git a/docs/markdown/Qt5-module.md b/docs/markdown/Qt5-module.md index f1c2f6c00d7d..0d9a6b6b9652 100644 --- a/docs/markdown/Qt5-module.md +++ b/docs/markdown/Qt5-module.md @@ -21,7 +21,7 @@ This method generates the necessary targets to build translation files with lrel - `ts_files`, the list of input translation files produced by Qt's lupdate tool. - `install` when true, this target is installed during the install step (optional). - `install_dir` directory to install to (optional). - - `build_by_default` when set to true, to have this target be built by default, that is, when invoking plain ninja; the default value is false (optional). + - `build_by_default` when set to true, to have this target be built by default, that is, when invoking `meson compile`; the default value is false (optional). ## has_tools diff --git a/docs/markdown/Quick-guide.md b/docs/markdown/Quick-guide.md index 0bed6832ed75..74636e5d40f2 100644 --- a/docs/markdown/Quick-guide.md +++ b/docs/markdown/Quick-guide.md @@ -93,8 +93,8 @@ are working on. The steps to take are very simple. ```console $ cd /path/to/source/root $ meson builddir && cd builddir -$ ninja -$ ninja test +$ meson compile +$ meson test ``` The only thing to note is that you need to create a separate build @@ -104,14 +104,14 @@ directory. This allows you to have multiple build trees with different configurations at the same time. This way generated files are not added into revision control by accident. -To recompile after code changes, just type `ninja`. The build command +To recompile after code changes, just type `meson compile`. The build command is always the same. You can do arbitrary changes to source code and build system files and Meson will detect those and will do the right thing. If you want to build optimized binaries, just use the argument `--buildtype=debugoptimized` when running Meson. It is recommended that you keep one build directory for unoptimized builds and one for optimized ones. To compile any given configuration, just go into the -corresponding build directory and run `ninja`. +corresponding build directory and run `meson compile`. Meson will automatically add compiler flags to enable debug information and compiler warnings (i.e. `-g` and `-Wall`). This means @@ -128,9 +128,9 @@ build and install Meson projects are the following. ```console $ cd /path/to/source/root $ meson --prefix /usr --buildtype=plain builddir -Dc_args=... -Dcpp_args=... -Dc_link_args=... -Dcpp_link_args=... -$ ninja -v -C builddir -$ ninja -C builddir test -$ DESTDIR=/path/to/staging/root ninja -C builddir install +$ meson compile -C builddir +$ meson test -C builddir +$ DESTDIR=/path/to/staging/root meson install -C builddir ``` The command line switch `--buildtype=plain` tells Meson not to add its @@ -139,7 +139,7 @@ on used flags. This is very similar to other build systems. The only difference is that the `DESTDIR` variable is passed as an environment variable -rather than as an argument to `ninja install`. +rather than as an argument to `meson install`. As distro builds happen always from scratch, you might consider enabling [unity builds](Unity-builds.md) on your packages because they diff --git a/docs/markdown/Running-Meson.md b/docs/markdown/Running-Meson.md index 910513c54c7a..326ecb96f945 100644 --- a/docs/markdown/Running-Meson.md +++ b/docs/markdown/Running-Meson.md @@ -9,13 +9,12 @@ from the source tree with the command `/path/to/source/meson.py`. Meson may also be installed in which case the command is simply `meson`. In this manual we only use the latter format for simplicity. -Additionally, the invocation can pass options to meson. The list of options is -documented [here](Builtin-options.md). - At the time of writing only a command line version of Meson is available. This means that Meson must be invoked using the terminal. If you wish to use the MSVC compiler, you need to run Meson under "Visual Studio command prompt". +All available meson commands are listed on the [commands reference page](Commands.md). + ## Configuring the build directory Let us assume that we have a source tree that has a Meson build system. This @@ -41,6 +40,9 @@ build backend in the build directory. By default Meson generates a *debug build*, which turns on basic warnings and debug information and disables compiler optimizations. +Additionally, the invocation can pass options to meson. The list of options is +documented [here](Builtin-options.md). + You can specify a different type of build with the `--buildtype` command line argument. It can have one of the following values. @@ -83,7 +85,7 @@ during configuration time. As an example, here is how you would use Meson to generate a Visual studio solution. ```sh -meson setup --backend=vs2010 +meson setup --backend=vs ``` You can then open the generated solution with Visual Studio and compile it in @@ -105,9 +107,18 @@ linker arguments needed. ## Building from the source -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. +To start the build, simply type the following command. + +```sh +meson compile -C builddir +``` + +See [`meson compile` description](Commands.md#compile) for more info. + +### Building directly with ninja + +By default Meson uses the [Ninja build system](https://ninja-build.org/) to +actually build the code. To start the build, simply type the following command. ```sh ninja -C builddir @@ -133,20 +144,29 @@ Meson provides native support for running tests. The command to do that is simple. ```sh -ninja -C builddir test +meson test -C builddir ``` +See [`meson test` description](Commands.md#test) for more info. + Meson does not force the use of any particular testing framework. You are free to use GTest, Boost Test, Check or even custom executables. +Note: it can be also invoked directly with ninja with the following command: +```sh +ninja -C builddir test +``` + ## Installing Installing the built software is just as simple. ```sh -ninja -C builddir install +meson install -C builddir ``` +See [`meson install` description](Commands.md#install) for more info. + Note that Meson will only install build targets explicitly tagged as installable, as detailed in the [installing targets documentation](Installing.md). @@ -157,7 +177,12 @@ Meson also supports the `DESTDIR` variable used in e.g. building packages. It is used like this: ```sh -DESTDIR=/path/to/staging ninja -C builddir install +DESTDIR=/path/to/staging meson install -C builddir +``` + +Note: it can be also invoked directly with ninja with the following command: +```sh +ninja -C builddir install ``` ## Command line help diff --git a/docs/markdown/Tutorial.md b/docs/markdown/Tutorial.md index 6b248b519f1d..be6888d6ac16 100644 --- a/docs/markdown/Tutorial.md +++ b/docs/markdown/Tutorial.md @@ -124,12 +124,12 @@ or the like. Instead we just type the exact same command as if we were rebuilding our code without any build system changes. ``` -$ ninja +$ meson compile ``` Once you have set up your build directory the first time, you don't ever need to run the `meson` command again. You always just run -`ninja`. Meson will automatically detect when you have done changes to +`meson compile`. Meson will automatically detect when you have done changes to build definitions and will take care of everything so users don't have to care. In this case the following output is produced. diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md index 06664db6b22e..4f51d35b93a0 100644 --- a/docs/markdown/Unit-tests.md +++ b/docs/markdown/Unit-tests.md @@ -75,7 +75,7 @@ test machine. You can override this with the environment variable `MESON_TESTTHREADS` like this. ```console -$ MESON_TESTTHREADS=5 ninja test +$ MESON_TESTTHREADS=5 meson test ``` ## Priorities @@ -122,8 +122,7 @@ The goal of the meson test tool is to provide a simple way to run tests in a variety of different ways. The tool is designed to be run in the build directory. -The simplest thing to do is just to run all tests, which is equivalent to -running `ninja test`. +The simplest thing to do is just to run all tests. ```console $ meson test diff --git a/docs/markdown/Using-multiple-build-directories.md b/docs/markdown/Using-multiple-build-directories.md index 2455640742b5..ab6cf3c85d56 100644 --- a/docs/markdown/Using-multiple-build-directories.md +++ b/docs/markdown/Using-multiple-build-directories.md @@ -32,9 +32,9 @@ You can add cross builds, too. As an example, let's set up a Linux -> Windows cr mkdir buildwine meson --cross-file=mingw-cross.txt buildwine -The cross compilation file sets up Wine so that not only can you compile your application, you can also run the unit test suite just by issuing the command `ninja test`. +The cross compilation file sets up Wine so that not only can you compile your application, you can also run the unit test suite just by issuing the command `meson test`. -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. +To compile any of these build types, just cd into the corresponding build directory and run `meson compile` 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. ## Specialized uses diff --git a/docs/markdown/Vs-External.md b/docs/markdown/Vs-External.md index add089e658dd..ab3d191f94ad 100644 --- a/docs/markdown/Vs-External.md +++ b/docs/markdown/Vs-External.md @@ -23,9 +23,9 @@ as follows: | entry | value | | ----- | ----- | -|build | `ninja -C $(Configuration)` | -|clean | `ninja -C $(Configuration) clean` | -|rebuild| `ninja -C $(Configuration) clean all| +|build | `meson compile -C $(Configuration)` | +|clean | `meson compile -C $(Configuration) --clean` | +|rebuild| `meson compile -C $(Configuration) --clean && meson compile -C $(Configuration)` | |Output | `$(Configuration)\name_of_your_executable.exe| diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md index 84546b73c421..5f9d13601389 100644 --- a/docs/markdown/howtox.md +++ b/docs/markdown/howtox.md @@ -148,15 +148,14 @@ $ meson -Db_coverage=true Then issue the following commands. ```console -$ ninja -$ ninja test +$ meson compile +$ meson test $ ninja coverage-html (or coverage-xml) ``` The coverage report can be found in the meson-logs subdirectory. -Note: Currently, Meson does not support generating coverage reports -with Clang. +*New in 0.55.0* llvm-cov support for use with clang ## Add some optimization to debug builds @@ -209,8 +208,8 @@ operation. First we set up the project with profile measurements enabled and compile it. ```console -$ meson -Db_pgo=generate -$ ninja -C builddir +$ meson setup -Db_pgo=generate +$ meson compile -C builddir ``` Then we need to run the program with some representative input. This @@ -221,7 +220,7 @@ information and rebuild. ```console $ meson configure -Db_pgo=use -$ ninja +$ meson compile ``` After these steps the resulting binary is fully optimized. diff --git a/docs/markdown/snippets/clang_coverage.md b/docs/markdown/snippets/clang_coverage.md new file mode 100644 index 000000000000..733a3d96cb8a --- /dev/null +++ b/docs/markdown/snippets/clang_coverage.md @@ -0,0 +1,4 @@ +## Clang coverage support + +llvm-cov is now used to generate coverage information when clang is used as +the compiler. \ No newline at end of file diff --git a/docs/templates/Commands.md b/docs/templates/Commands.md new file mode 100644 index 000000000000..5747123f964c --- /dev/null +++ b/docs/templates/Commands.md @@ -0,0 +1,248 @@ +# Command-line commands + +There are two different ways of invoking Meson. First, you can run it directly +from the source tree with the command `/path/to/source/meson.py`. Meson may +also be installed in which case the command is simply `meson`. In this manual +we only use the latter format for simplicity. + +Meson is invoked using the following syntax: +`meson [COMMAND] [COMMAND_OPTIONS]` + +This section describes all available commands and some of their Optional arguments. +The most common workflow is to run [`setup`](#setup), followed by [`compile`](#compile), and then [`install`](#install). + +For the full list of all available options for a specific command use the following syntax: +`meson COMMAND --help` + +### configure + +``` +{{ cmd_help['configure']['usage'] }} +``` + +Changes options of a configured meson project. + +``` +{{ cmd_help['configure']['arguments'] }} +``` + +Most arguments are the same as in [`setup`](#setup). + +Note: reconfiguring project will not reset options to their default values (even if they were changed in `meson.build`). + +#### Examples: + +List all available options: +``` +meson configure builddir +``` + +Change value of a single option: +``` +meson configure builddir -Doption=new_value +``` + +### compile + +*(since 0.54.0)* + +``` +{{ cmd_help['compile']['usage'] }} +``` + +Builds a default or a specified target of a configured meson project. + +``` +{{ cmd_help['compile']['arguments'] }} +``` + +#### Examples: + +Build the project: +``` +meson compile -C builddir +``` + +### dist + +*(since 0.52.0)* + +``` +{{ cmd_help['dist']['usage'] }} +``` + +Generates a release archive from the current source tree. + +``` +{{ cmd_help['dist']['arguments'] }} +``` + +See [notes about creating releases](Creating-releases.md) for more info. + +#### Examples: + +Create a release archive: +``` +meson dist -C builddir +``` + +### init + +*(since 0.45.0)* + +``` +{{ cmd_help['init']['usage'] }} +``` + +Creates a basic set of build files based on a template. + +``` +{{ cmd_help['init']['arguments'] }} +``` + +#### Examples: + +Create a project in `sourcedir`: +``` +meson init -C sourcedir +``` + +### introspect + +``` +{{ cmd_help['introspect']['usage'] }} +``` + +Displays information about a configured meson project. + +``` +{{ cmd_help['introspect']['arguments'] }} +``` + +#### Examples: + +Display basic information about a configured project in `builddir`: +``` +meson introspect builddir +``` + +### install + +*(since 0.47.0)* + +``` +{{ cmd_help['install']['usage'] }} +``` + +Installs the project to the prefix specified in `setup`. + +``` +{{ cmd_help['install']['arguments'] }} +``` + +See [the installation documentation](Installing.md) for more info. + +#### Examples: + +Install project to `prefix`: +``` +meson install -C builddir +``` + +Install project to `$DESTDIR/prefix`: +``` +DESTDIR=/path/to/staging/area meson install -C builddir +``` + +### rewrite + +*(since 0.50.0)* + +``` +{{ cmd_help['rewrite']['usage'] }} +``` + +Modifies the meson project. + +``` +{{ cmd_help['rewrite']['arguments'] }} +``` + +See [the meson file rewriter documentation](Rewriter.md) for more info. + +### setup + +``` +{{ cmd_help['setup']['usage'] }} +``` + +Configures a build directory for the meson project. + +This is the default meson command (invoked if there was no COMMAND supplied). + +``` +{{ cmd_help['setup']['arguments'] }} +``` + +See [meson introduction page](Running-Meson.md#configuring-the-build-directory) for more info. + +#### Examples: + +Configures `builddir` with default values: +``` +meson setup builddir +``` + +### subprojects + +*(since 0.49.0)* + +``` +{{ cmd_help['subprojects']['usage'] }} +``` + +Manages subprojects of the meson project. + +``` +{{ cmd_help['subprojects']['arguments'] }} +``` + +### test + +``` +{{ cmd_help['test']['usage'] }} +``` + +Run tests for the configure meson project. + +``` +{{ cmd_help['test']['arguments'] }} +``` + +See [the unit test documentation](Unit-tests.md) for more info. + +#### Examples: + +Run tests for the project: +``` +meson test -C builddir +``` + +Run only `specific_test_1` and `specific_test_2`: +``` +meson test -C builddir specific_test_1 specific_test_2 +``` + +### wrap + +``` +{{ cmd_help['wrap']['usage'] }} +``` + +An utility to manage WrapDB dependencies. + +``` +{{ cmd_help['wrap']['arguments'] }} +``` + +See [the WrapDB tool documentation](Using-wraptool.md) for more info. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 8dbb57a04ade..252f6463da73 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -968,6 +968,13 @@ def generate_run_target(self, target): self.processed_targets[target.get_id()] = True def generate_coverage_command(self, elem, outputs): + targets = self.build.get_targets().values() + use_llvm_cov = False + for target in targets: + for compiler in target.compilers.values(): + if compiler.get_id() == 'clang' and not compiler.info.is_darwin(): + use_llvm_cov = True + break elem.add_item('COMMAND', self.environment.get_build_command() + ['--internal', 'coverage'] + outputs + @@ -975,7 +982,8 @@ def generate_coverage_command(self, elem, outputs): os.path.join(self.environment.get_source_dir(), self.build.get_subproject_dir()), self.environment.get_build_dir(), - self.environment.get_log_dir()]) + self.environment.get_log_dir()] + + ['--use_llvm_cov'] if use_llvm_cov else []) def generate_coverage_rules(self): e = NinjaBuildElement(self.all_outputs, 'meson-coverage', 'CUSTOM_COMMAND', 'PHONY') diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index c02376ee2700..afc2a6396643 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -134,9 +134,18 @@ def detect_gcovr(min_version='3.3', new_rootdir_version='4.2', log=False): return gcovr_exe, mesonlib.version_compare(found, '>=' + new_rootdir_version) return None, None +def detect_llvm_cov(): + tools = get_llvm_tool_names('llvm-cov') + for tool in tools: + if mesonlib.exe_exists([tool, '--version']): + return tool + return None + def find_coverage_tools(): gcovr_exe, gcovr_new_rootdir = detect_gcovr() + llvm_cov_exe = detect_llvm_cov() + lcov_exe = 'lcov' genhtml_exe = 'genhtml' @@ -145,7 +154,7 @@ def find_coverage_tools(): if not mesonlib.exe_exists([genhtml_exe, '--version']): genhtml_exe = None - return gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe + return gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe, llvm_cov_exe def detect_ninja(version: str = '1.7', log: bool = False) -> str: r = detect_ninja_command_and_version(version, log) diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 05e9518ff415..2e03cabafa6a 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -97,9 +97,9 @@ def print_aligned(self): else: print('{0:{width[0]}} {1:{width[1]}} {3}'.format(*line, width=col_widths)) - def split_options_per_subproject(self, options_iter): + def split_options_per_subproject(self, options): result = {} - for k, o in options_iter: + for k, o in options.items(): subproject = '' if ':' in k: subproject, optname = k.split(':') @@ -211,15 +211,15 @@ def insert_build_prefix(k): return 'build.' + k return k[:idx + 1] + 'build.' + k[idx + 1:] - core_options = self.split_options_per_subproject(core_options.items()) + core_options = self.split_options_per_subproject(core_options) host_compiler_options = self.split_options_per_subproject( - self.coredata.flatten_lang_iterator( - self.coredata.compiler_options.host.items())) + dict(self.coredata.flatten_lang_iterator( + self.coredata.compiler_options.host.items()))) build_compiler_options = self.split_options_per_subproject( - self.coredata.flatten_lang_iterator( + dict(self.coredata.flatten_lang_iterator( (insert_build_prefix(k), o) - for k, o in self.coredata.compiler_options.build.items())) - project_options = self.split_options_per_subproject(self.coredata.user_options.items()) + for k, o in self.coredata.compiler_options.build.items()))) + project_options = self.split_options_per_subproject(self.coredata.user_options) show_build_options = self.default_values_only or self.build.environment.is_cross_build() self.add_section('Main project options') diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index 4bd41fe91acd..72319724d628 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -12,15 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -from mesonbuild import environment +from mesonbuild import environment, mesonlib -import argparse, sys, os, subprocess, pathlib +import argparse, sys, os, subprocess, pathlib, stat -def coverage(outputs, source_root, subproject_root, build_root, log_dir): +def coverage(outputs, source_root, subproject_root, build_root, log_dir, use_llvm_cov): outfiles = [] exitcode = 0 - (gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe) = environment.find_coverage_tools() + (gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools() # gcovr >= 4.2 requires a different syntax for out of source builds if gcovr_new_rootdir: @@ -28,13 +28,18 @@ def coverage(outputs, source_root, subproject_root, build_root, log_dir): else: gcovr_base_cmd = [gcovr_exe, '-r', build_root] + if use_llvm_cov: + gcov_exe_args = ['--gcov-executable', llvm_cov_exe + ' gcov'] + else: + gcov_exe_args = [] + if not outputs or 'xml' in outputs: if gcovr_exe: subprocess.check_call(gcovr_base_cmd + ['-x', '-e', subproject_root, - '-o', os.path.join(log_dir, 'coverage.xml'), - ]) + '-o', os.path.join(log_dir, 'coverage.xml') + ] + gcov_exe_args) outfiles.append(('Xml', pathlib.Path(log_dir, 'coverage.xml'))) elif outputs: print('gcovr >= 3.3 needed to generate Xml coverage report') @@ -44,8 +49,8 @@ def coverage(outputs, source_root, subproject_root, build_root, log_dir): if gcovr_exe: subprocess.check_call(gcovr_base_cmd + ['-e', subproject_root, - '-o', os.path.join(log_dir, 'coverage.txt'), - ]) + '-o', os.path.join(log_dir, 'coverage.txt') + ] + gcov_exe_args) outfiles.append(('Text', pathlib.Path(log_dir, 'coverage.txt'))) elif outputs: print('gcovr >= 3.3 needed to generate text coverage report') @@ -58,19 +63,34 @@ def coverage(outputs, source_root, subproject_root, build_root, log_dir): initial_tracefile = covinfo + '.initial' run_tracefile = covinfo + '.run' raw_tracefile = covinfo + '.raw' + if use_llvm_cov: + # Create a shim to allow using llvm-cov as a gcov tool. + if mesonlib.is_windows(): + llvm_cov_shim_path = os.path.join(log_dir, 'llvm-cov.bat') + with open(llvm_cov_shim_path, 'w') as llvm_cov_bat: + llvm_cov_bat.write('@"{}" gcov %*'.format(llvm_cov_exe)) + else: + llvm_cov_shim_path = os.path.join(log_dir, 'llvm-cov.sh') + with open(llvm_cov_shim_path, 'w') as llvm_cov_sh: + llvm_cov_sh.write('#!/usr/bin/env sh\nexec "{}" gcov $@'.format(llvm_cov_exe)) + os.chmod(llvm_cov_shim_path, os.stat(llvm_cov_shim_path).st_mode | stat.S_IEXEC) + gcov_tool_args = ['--gcov-tool', llvm_cov_shim_path] + else: + gcov_tool_args = [] subprocess.check_call([lcov_exe, '--directory', build_root, '--capture', '--initial', '--output-file', - initial_tracefile]) + initial_tracefile] + + gcov_tool_args) subprocess.check_call([lcov_exe, '--directory', build_root, '--capture', '--output-file', run_tracefile, '--no-checksum', - '--rc', 'lcov_branch_coverage=1', - ]) + '--rc', 'lcov_branch_coverage=1'] + + gcov_tool_args) # Join initial and test results. subprocess.check_call([lcov_exe, '-a', initial_tracefile, @@ -137,6 +157,8 @@ def run(args): const='xml', help='generate Xml report') parser.add_argument('--html', dest='outputs', action='append_const', const='html', help='generate Html report') + parser.add_argument('--use_llvm_cov', action='store_true', + help='use llvm-cov') parser.add_argument('source_root') parser.add_argument('subproject_root') parser.add_argument('build_root') @@ -144,7 +166,7 @@ def run(args): options = parser.parse_args(args) return coverage(options.outputs, options.source_root, options.subproject_root, options.build_root, - options.log_dir) + options.log_dir, options.use_llvm_cov) if __name__ == '__main__': sys.exit(run(sys.argv[1:])) diff --git a/run_unittests.py b/run_unittests.py index 827e3c8c718e..1f22976a5daa 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -4787,13 +4787,48 @@ def clean_dir_arguments(text): out = re.sub(r'(--' + a + r' .+?)[ |\n]\(default:.+?\)(\.)?', r'\1\2', out, flags=re.MULTILINE|re.DOTALL) return out - ## Get command sections + ## Read .md files md = None with open('docs/markdown/Commands.md', encoding='utf-8') as f: md = f.read() self.assertIsNotNone(md) + md_template = None + with open('docs/templates/Commands.md', encoding='utf-8') as f: + md_template = f.read() + self.assertIsNotNone(md_template) + + ## Validate that `Commands.md` was not edited directly + + # Remove dynamic blocks from each section + clean_re = [r'(' + r'^### .*?' + r'^```' + r')' + r'.*?' + r'(' + r'^```' + r'.*?' + r'^```' + r')' + r'.*?' + r'(' + r'^```' + r')', + r'\1\n' + '{usage place-holder}\n' + r'\2\n' + '{arguments place-holder}\n' + r'\3'] + md_clean = re.sub(*clean_re, md, flags=re.MULTILINE|re.DOTALL) + md_template_clean = re.sub(*clean_re, md_template, flags=re.MULTILINE|re.DOTALL) + + self.assertEqual(md_clean, md_template_clean, '`markdown/Commands.md` is not consistent with `templates/Commands.md`!\n' + 'Re-apply changes to `templates/Commands.md` and use `tools/regenerate_docs.py` to regenerate docs.') + + ## Get command sections + section_pattern = re.compile(r'^### (.+)$', re.MULTILINE) md_command_section_matches = [i for i in section_pattern.finditer(md)] md_command_sections = dict() @@ -4826,8 +4861,85 @@ def clean_dir_arguments(text): if command in ['setup', 'configure']: parsed_help['arguments'] = clean_dir_arguments(parsed_help['arguments']) - self.assertEqual(parsed_help['usage'], parsed_section['usage']) - self.assertEqual(parsed_help['arguments'], parsed_section['arguments']) + errorMsg = 'Commands.md is outdated! Use `tools/regenerate_docs.py` to regenerate docs.' + self.assertEqual(parsed_help['usage'], parsed_section['usage'], errorMsg) + self.assertEqual(parsed_help['arguments'], parsed_section['arguments'], errorMsg) + + def test_coverage(self): + if mesonbuild.environment.detect_msys2_arch(): + raise unittest.SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise unittest.SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = env.detect_c_compiler(MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise unittest.SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise unittest.SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage') + + def test_coverage_html(self): + if mesonbuild.environment.detect_msys2_arch(): + raise unittest.SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise unittest.SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = env.detect_c_compiler(MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise unittest.SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise unittest.SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage-html') + + def test_coverage_text(self): + if mesonbuild.environment.detect_msys2_arch(): + raise unittest.SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise unittest.SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = env.detect_c_compiler(MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise unittest.SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise unittest.SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage-text') + + def test_coverage_xml(self): + if mesonbuild.environment.detect_msys2_arch(): + raise unittest.SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise unittest.SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = env.detect_c_compiler(MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise unittest.SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise unittest.SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage-xml') class FailureTests(BasePlatformTests): ''' @@ -6301,21 +6413,6 @@ def test_pch_with_address_sanitizer(self): for i in compdb: self.assertIn("-fsanitize=address", i["command"]) - def test_coverage(self): - gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() - if not gcovr_exe: - raise unittest.SkipTest('gcovr not found') - if not shutil.which('genhtml') and not gcovr_new_rootdir: - raise unittest.SkipTest('genhtml not found and gcovr is too old') - if 'clang' in os.environ.get('CC', ''): - # We need to use llvm-cov instead of gcovr with clang - raise unittest.SkipTest('Coverage does not work with clang right now, help wanted!') - testdir = os.path.join(self.common_test_dir, '1 trivial') - self.init(testdir, extra_args=['-Db_coverage=true']) - self.build() - self.run_tests() - self.run_target('coverage-html') - def test_cross_find_program(self): testdir = os.path.join(self.unit_test_dir, '11 cross prog') crossfile = tempfile.NamedTemporaryFile(mode='w') diff --git a/tools/regenerate_docs.py b/tools/regenerate_docs.py new file mode 100644 index 000000000000..12b8f8978204 --- /dev/null +++ b/tools/regenerate_docs.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 + + +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# 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. + +''' +Regenerate markdown docs by using `meson.py` from the root dir +''' + +import jinja2 +import os +import re +import subprocess +import sys +import textwrap +import typing as T +from pathlib import Path + +def _get_meson_output(root_dir: Path, args: T.List): + env = os.environ.copy() + env['COLUMNS'] = '80' + return subprocess.run([str(sys.executable), str(root_dir/'meson.py')] + args, check=True, capture_output=True, text=True, env=env).stdout.strip() + +def get_commands_data(root_dir: Path): + usage_start_pattern = re.compile(r'^usage: ', re.MULTILINE) + positional_start_pattern = re.compile(r'^positional arguments:[\t ]*[\r\n]+', re.MULTILINE) + options_start_pattern = re.compile(r'^optional arguments:[\t ]*[\r\n]+', re.MULTILINE) + commands_start_pattern = re.compile(r'^[A-Za-z ]*[Cc]ommands:[\t ]*[\r\n]+', re.MULTILINE) + + def get_next_start(iterators, end): + return next((i.start() for i in iterators if i), end) + + def normalize_text(text): + # clean up formatting + out = text + out = re.sub(r'\r\n', r'\r', out, flags=re.MULTILINE) # replace newlines with a linux EOL + out = re.sub(r'^ +$', '', out, flags=re.MULTILINE) # remove trailing whitespace + out = re.sub(r'(?:^\n+|\n+$)', '', out) # remove trailing empty lines + return out + + def parse_cmd(cmd): + cmd_len = len(cmd) + usage = usage_start_pattern.search(cmd) + positionals = positional_start_pattern.search(cmd) + options = options_start_pattern.search(cmd) + commands = commands_start_pattern.search(cmd) + + arguments_start = get_next_start([positionals, options, commands], None) + assert arguments_start + + # replace `usage:` with `$` and dedent + dedent_size = (usage.end() - usage.start()) - len('$ ') + usage_text = textwrap.dedent(f'{dedent_size * " "}$ {normalize_text(cmd[usage.end():arguments_start])}') + + return { + 'usage': usage_text, + 'arguments': normalize_text(cmd[arguments_start:cmd_len]), + } + + def clean_dir_arguments(text): + # Remove platform specific defaults + args = [ + 'prefix', + 'bindir', + 'datadir', + 'includedir', + 'infodir', + 'libdir', + 'libexecdir', + 'localedir', + 'localstatedir', + 'mandir', + 'sbindir', + 'sharedstatedir', + 'sysconfdir' + ] + out = text + for a in args: + out = re.sub(r'(--' + a + r' .+?)\s+\(default:.+?\)(\.)?', r'\1\2', out, flags=re.MULTILINE|re.DOTALL) + return out + + output = _get_meson_output(root_dir, ['--help']) + commands = set(c.strip() for c in re.findall(r'usage:(?:.+)?{((?:[a-z]+,*)+?)}', output, re.MULTILINE|re.DOTALL)[0].split(',')) + commands.remove('help') + + cmd_data = dict() + + for cmd in commands: + cmd_output = _get_meson_output(root_dir, [cmd, '--help']) + cmd_data[cmd] = parse_cmd(cmd_output) + if cmd in ['setup', 'configure']: + cmd_data[cmd]['arguments'] = clean_dir_arguments(cmd_data[cmd]['arguments']) + + return cmd_data + +def regenerate_commands(root_dir: Path) -> None: + with open(root_dir/'docs'/'templates'/'Commands.md') as f: + template = f.read() + + cmd_data = get_commands_data(root_dir) + + t = jinja2.Template(template, keep_trailing_newline=True) + content = t.render(cmd_help=cmd_data) + + output_file = root_dir/'docs'/'markdown'/'Commands.md' + with open(output_file, 'w') as f: + f.write(content) + + print(f'`{output_file}` was regenerated') + +def regenerate_docs() -> None: + root_dir = Path(__file__).resolve().parent.parent + regenerate_commands(root_dir) + +if __name__ == '__main__': + if len(sys.argv) != 1: + raise SystemExit('This script takes no arguments.') + regenerate_docs()