diff --git a/docs/markdown/ARM-performance-test.md b/docs/markdown/ARM-performance-test.md index 7e42fb345..4be6e4aab 100644 --- a/docs/markdown/ARM-performance-test.md +++ b/docs/markdown/ARM-performance-test.md @@ -1,10 +1,21 @@ # Arm performance test -Performance differences in build systems become more apparent on slower platforms. To examine this difference we compared the performance of Meson with GNU Autotools. We took the GLib software project and rewrote its build setup with Meson. GLib was chosen because it is a relatively large C code base which requires lots of low level configuration. - -The Meson version of the build system is not fully equivalent to the original Autotools one. It does not do all the same configuration steps and does not build all the same targets. The biggest missing piece being internationalisation support with Gettext. However it does configure the system enough to build all C source and run all unit tests. - -All measurements were done on a Nexus 4 smart phone running the latest Ubuntu touch image (updated on September 9th 2013). +Performance differences in build systems become more apparent on +slower platforms. To examine this difference we compared the +performance of Meson with GNU Autotools. We took the GLib software +project and rewrote its build setup with Meson. GLib was chosen +because it is a relatively large C code base which requires lots of +low level configuration. + +The Meson version of the build system is not fully equivalent to the +original Autotools one. It does not do all the same configuration +steps and does not build all the same targets. The biggest missing +piece being internationalisation support with Gettext. However it does +configure the system enough to build all C source and run all unit +tests. + +All measurements were done on a Nexus 4 smart phone running the latest +Ubuntu touch image (updated on September 9th 2013). Measurements ------ @@ -13,25 +24,58 @@ The first thing we measured was the time it took to run the configure step. ![GLib config time](images/glib_conf.png) -Meson takes roughly 20 seconds whereas Autotools takes 220. This is a difference of one order of magnitude. Autotools' time contains both autogen and configure. Again it should be remembered that Meson does not do all the configure steps that Autotools does. It does do about 90% of them and it takes just 10% of the time to do it. +Meson takes roughly 20 seconds whereas Autotools takes 220. This is a +difference of one order of magnitude. Autotools' time contains both +autogen and configure. Again it should be remembered that Meson does +not do all the configure steps that Autotools does. It does do about +90% of them and it takes just 10% of the time to do it. -Then we measured the build times. Two parallel compilation processes were used for both systems. +Then we measured the build times. Two parallel compilation processes +were used for both systems. ![GLib build time](images/glib_build.png) -On desktop machines Ninja based build systems are 10-20% faster than Make based ones. On this platform the difference grows to 50%. The difference is probably caused by Make's inefficient disk access patterns. Ninja is better at keeping both cores running all the time which yields impressive performance improvements. +On desktop machines Ninja based build systems are 10-20% faster than +Make based ones. On this platform the difference grows to 50%. The +difference is probably caused by Make's inefficient disk access +patterns. Ninja is better at keeping both cores running all the time +which yields impressive performance improvements. ![GLib no-op time](images/glib_empty.png) -Next we measured the "empty build" case. That is, how long does it take for the build system to detect that no changes need to be made. This is one of the most important metrics of build systems because it places a hard limit on how fast you can iterate on your code. Autotools takes 14 seconds to determine that no work needs to be done. Meson (or, rather, Ninja) takes just one quarter of a second. +Next we measured the "empty build" case. That is, how long does it +take for the build system to detect that no changes need to be +made. This is one of the most important metrics of build systems +because it places a hard limit on how fast you can iterate on your +code. Autotools takes 14 seconds to determine that no work needs to be +done. Meson (or, rather, Ninja) takes just one quarter of a second. ![GLib link time](images/glib_link.png) -One step which takes quite a lot of time is linking. A common case is that you are working on a library and there are tens of small test executables that link to it. Even if the compilation step would be fast, relinking all of the test executables takes time. It is common for people to manually compile only one test application with a command such as `make sometest` rather than rebuild everything. - -Meson has an optimization for this case. Whenever a library is rebuilt, Meson inspects the ABI it exports. If it has not changed, Meson will skip all relinking steps as unnecessary. The difference this makes can be clearly seen in the chart above. In that test the source was fully built, then the file `glib/gbytes.c` was touched to force the rebuild of the base glib shared library. As can be seen, Autotools then relinks all test executables that link with glib. Since Meson can detect that the ABI is the same it can skip those steps. The end result being that Meson is almost one hundred times faster on this very common use case. +One step which takes quite a lot of time is linking. A common case is +that you are working on a library and there are tens of small test +executables that link to it. Even if the compilation step would be +fast, relinking all of the test executables takes time. It is common +for people to manually compile only one test application with a +command such as `make sometest` rather than rebuild everything. + +Meson has an optimization for this case. Whenever a library is +rebuilt, Meson inspects the ABI it exports. If it has not changed, +Meson will skip all relinking steps as unnecessary. The difference +this makes can be clearly seen in the chart above. In that test the +source was fully built, then the file `glib/gbytes.c` was touched to +force the rebuild of the base glib shared library. As can be seen, +Autotools then relinks all test executables that link with glib. Since +Meson can detect that the ABI is the same it can skip those steps. The +end result being that Meson is almost one hundred times faster on this +very common use case. Conclusions ----- -One of the main drawbacks of C and C++ compared to languages such as Java are long compilation times. However at least some of the blame can be found in the build tools used rather than the languages themselves or their compilers. Choosing proper tools can bring C and C++ compilation very close to instantaneous rebuilds. This has a direct impact on programmer productivity. +One of the main drawbacks of C and C++ compared to languages such as +Java are long compilation times. However at least some of the blame +can be found in the build tools used rather than the languages +themselves or their compilers. Choosing proper tools can bring C and +C++ compilation very close to instantaneous rebuilds. This has a +direct impact on programmer productivity. diff --git a/docs/markdown/Adding-arguments.md b/docs/markdown/Adding-arguments.md index 0bf5944d0..e3141020c 100644 --- a/docs/markdown/Adding-arguments.md +++ b/docs/markdown/Adding-arguments.md @@ -4,22 +4,38 @@ 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. +Often you need to specify extra compiler arguments. Meson provides two +different ways to achieve this: global arguments and per-target +arguments. Global arguments -- -Global compiler arguments are set with the following command. As an example you could do this. +Global compiler arguments are set with the following command. As an +example you could do this. ```meson 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.md). - -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. - -You should set only the most essential flags with this setting, you should *not* set debug or optimization flags. Instead they should be specified by selecting an appropriate build type. +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.md). + +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. + +You should set only the most essential flags with this setting, you +should *not* set debug or optimization flags. Instead they should be +specified by selecting an appropriate build type. Per target arguments -- @@ -30,7 +46,8 @@ Per target arguments are just as simple to define. executable('prog', 'prog.cc', cpp_args : '-DCPPTHING') ``` -Here we create a C++ executable with an extra argument that is used during compilation but not for linking. +Here we create a C++ executable with an extra argument that is used +during compilation but not for linking. Specifying extra linker arguments is done in the same way: diff --git a/docs/markdown/Adding-new-projects-to-wrapdb.md b/docs/markdown/Adding-new-projects-to-wrapdb.md index e14e0ac49..4420de553 100644 --- a/docs/markdown/Adding-new-projects-to-wrapdb.md +++ b/docs/markdown/Adding-new-projects-to-wrapdb.md @@ -1,18 +1,35 @@ # Adding new projects to wrap -**If you don't have permissions to do something on this page, please open issue against https://github.com/mesonbuild/wrapweb/issues to let us know that you want to start new project.** +**If you don't have permissions to do something on this page, please + open issue against https://github.com/mesonbuild/wrapweb/issues to + let us know that you want to start new project.** ## 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 -The WrapDB repository has a [helper script](https://github.com/mesonbuild/wrapweb/blob/master/tools/repoinit.py) to generate new repositories. The documentation below roughly explains what it does using plain shell commands. +The WrapDB repository has a [helper +script](https://github.com/mesonbuild/wrapweb/blob/master/tools/repoinit.py) +to generate new repositories. The documentation below roughly explains +what it does using plain shell commands. ## Choosing the repository name -Wrapped subprojects are used much like external dependencies. Thus they should have the same name as the upstream projects. If the project provides a pkg-config file, then the repository name should be the same as the pkg-config name. Usually this is the name of the project, such as `libpng`. Sometimes it is slightly different, however. As an example the libogg project's chosen pkg-config name is `ogg` instead of `libogg`, which is the reason why the repository is named plain `ogg`. +Wrapped subprojects are used much like external dependencies. Thus +they should have the same name as the upstream projects. If the +project provides a pkg-config file, then the repository name should be +the same as the pkg-config name. Usually this is the name of the +project, such as `libpng`. Sometimes it is slightly different, +however. As an example the libogg project's chosen pkg-config name is +`ogg` instead of `libogg`, which is the reason why the repository is +named plain `ogg`. ## Adding new project to the Wrap provider service @@ -61,13 +78,21 @@ 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 -The point of a wrap is to provide the upstream project with as few changes as possible. Most projects should not contain anything more than a few Meson definition files. Sometimes it may be necessary to add a template header file or something similar. These should be held at a minimum. +The point of a wrap is to provide the upstream project with as few +changes as possible. Most projects should not contain anything more +than a few Meson definition files. Sometimes it may be necessary to +add a template header file or something similar. These should be held +at a minimum. -It should especially be noted that there must **not** be any patches to functionality. All such changes must be submitted to upstream. You may also host your own Git repo with the changes if you wish. The Wrap system has native support for Git subprojects. +It should especially be noted that there must **not** be any patches +to functionality. All such changes must be submitted to upstream. You +may also host your own Git repo with the changes if you wish. The Wrap +system has native support for Git subprojects. ## Reviewing wraps diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md index 6029a2c99..54905d519 100644 --- a/docs/markdown/Build-options.md +++ b/docs/markdown/Build-options.md @@ -4,7 +4,11 @@ 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. +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. Here is a simple option file. @@ -14,7 +18,14 @@ option('other_one', type : 'boolean', value : false) option('combo_opt', type : 'combo', choices : ['one', 'two', 'three'], value : 'three') ``` -This demonstrates the three basic option types and their usage. String option is just a free form string and a boolean option is, unsurprisingly, true or false. The combo option can have any value from the strings listed in argument `choices`. If `value` is not set, it defaults to empty string for strings, `true` for booleans or the first element in a combo. You can specify `description`, which is a free form piece of text describing the option. It defaults to option name. +This demonstrates the three basic option types and their usage. String +option is just a free form string and a boolean option is, +unsurprisingly, true or false. The combo option can have any value +from the strings listed in argument `choices`. If `value` is not set, +it defaults to empty string for strings, `true` for booleans or the +first element in a combo. You can specify `description`, which is a +free form piece of text describing the option. It defaults to option +name. These options are accessed in Meson code with the `get_option` function. @@ -22,13 +33,19 @@ These options are accessed in Meson code with the `get_option` function. optval = get_option('opt_name') ``` -This function also allows you to query the value of Meson's built-in project options. For example, to get the installation prefix you would issue the following command: +This function also allows you to query the value of Meson's built-in +project options. For example, to get the installation prefix you would +issue the following command: ```meson prefix = get_option('prefix') ``` -It should be noted that you can not set option values in your Meson scripts. They have to be set externally with the `mesonconf` command line tool. Running `mesonconf` without arguments in a build dir shows you all options you can set. To change their values use the `-D` option: +It should be noted that you can not set option values in your Meson +scripts. They have to be set externally with the `mesonconf` command +line tool. Running `mesonconf` without arguments in a build dir shows +you all options you can set. To change their values use the `-D` +option: ```console $ mesonconf -Doption=newvalue diff --git a/docs/markdown/Build-system-converters.md b/docs/markdown/Build-system-converters.md index 18e7470df..1c0b4fc50 100644 --- a/docs/markdown/Build-system-converters.md +++ b/docs/markdown/Build-system-converters.md @@ -4,10 +4,24 @@ 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. +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. -The scripts do not try to do a perfect conversion. This would be extremely difficult because the data models of other build systems are very different. The goal of the converter script is to convert as much of the low level drudgery as possible. Using the scripts is straightforward. We'll use the CMake one as an example but the Autotools one works exactly the same way. +The scripts do not try to do a perfect conversion. This would be +extremely difficult because the data models of other build systems are +very different. The goal of the converter script is to convert as much +of the low level drudgery as possible. Using the scripts is +straightforward. We'll use the CMake one as an example but the +Autotools one works exactly the same way. 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 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. +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 4153e974c..e48de1252 100644 --- a/docs/markdown/Build-targets.md +++ b/docs/markdown/Build-targets.md @@ -4,7 +4,13 @@ short-description: Definition of build targets # Build targets -Meson provides three kinds of build targets: executables, static libraries and shared libraries. They are created with the commands `executable`, `static_library` and `shared_library`, respectively. All objects created in this way are **immutable**. That is, you can not change any aspect of them after they have been constructed. This ensures that all information pertaining to a given build target is specified in one well defined place. +Meson provides three kinds of build targets: executables, static +libraries and shared libraries. They are created with the commands +`executable`, `static_library` and `shared_library`, respectively. All +objects created in this way are **immutable**. That is, you can not +change any aspect of them after they have been constructed. This +ensures that all information pertaining to a given build target is +specified in one well defined place. As an example, here is how you would build a shared library. @@ -13,14 +19,16 @@ 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') shared_library('mylib', 'source.c', version : '1.2.3', soversion : '0') ``` -It is common to build a library and then an executable that links against it. This is supported as well. +It is common to build a library and then an executable that links +against it. This is supported as well. ```meson project('shared lib', 'c') @@ -28,7 +36,9 @@ lib = shared_library('mylib', 'source.c') executable('program', 'prog.c', link_with : lib) ``` -Meson sets things up so that the resulting executable can be run directly from the build directory. There is no need to write shell scripts or set environment variables. +Meson sets things up so that the resulting executable can be run +directly from the build directory. There is no need to write shell +scripts or set environment variables. One target can have multiple language source files. @@ -40,15 +50,25 @@ executable('multiexe', 'file.c', 'file2.cc') Object files -- -Sometimes you can't build files from sources but need to utilize an existing object file. A typical case is using an object file provided by a third party. Object files can be specified just like sources. +Sometimes you can't build files from sources but need to utilize an +existing object file. A typical case is using an object file provided +by a third party. Object files can be specified just like sources. ```meson exe = executable('myexe', 'source.cpp', objects : 'third_party_object.o') ``` -A different case is when you want to use object files built in one target directly in another. A typical case is when you build a shared library and it has an internal class that is not exported in the ABI. This means you can't access it even if you link against the library. Typical workarounds for this include building both a shared and static version of the library or putting the source file in the test executable's source list. Both of these approaches cause the source to be built twice, which is slow. +A different case is when you want to use object files built in one +target directly in another. A typical case is when you build a shared +library and it has an internal class that is not exported in the +ABI. This means you can't access it even if you link against the +library. Typical workarounds for this include building both a shared +and static version of the library or putting the source file in the +test executable's source list. Both of these approaches cause the +source to be built twice, which is slow. -In Meson you can extract object files from targets and use them as-is on other targets. This is the syntax for it. +In Meson you can extract object files from targets and use them as-is +on other targets. This is the syntax for it. ```meson lib = shared_library('somelib', 'internalclass.cc', 'file.cc', ...) @@ -56,6 +76,13 @@ eo = lib.extract_objects('internalclass.cc') executable('classtest', 'classtest.cpp', objects : eo) ``` -Here we take the internal class object and use it directly in the test. The source file is only compiled once. +Here we take the internal class object and use it directly in the +test. The source file is only compiled once. -Note that careless use of this feature may cause strange bugs. As an example trying to use objects of an executable or static library in a shared library will not work because shared library objects require special compiler flags. Getting this right is the user's responsibility. For this reason it is strongly recommended that you only use this feature for generating unit test executables in the manner described above. +Note that careless use of this feature may cause strange bugs. As an +example trying to use objects of an executable or static library in a +shared library will not work because shared library objects require +special compiler flags. Getting this right is the user's +responsibility. For this reason it is strongly recommended that you +only use this feature for generating unit test executables in the +manner described above. diff --git a/docs/markdown/Comparisons.md b/docs/markdown/Comparisons.md index eb0e4ddad..3c526ad2f 100644 --- a/docs/markdown/Comparisons.md +++ b/docs/markdown/Comparisons.md @@ -4,17 +4,25 @@ title: Comparisons # Comparing Meson with other build systems # -A common question is *Why should I choose Meson over a different build system X?* There is no one true answer to this as it depends on the use case. Almost all build systems have all the functionality needed to build medium-to-large projects so the decision is usually made on other points. Here we list some pros and cons of various build systems to help you do the decision yourself. +A common question is *Why should I choose Meson over a different build +system X?* There is no one true answer to this as it depends on the +use case. Almost all build systems have all the functionality needed +to build medium-to-large projects so the decision is usually made on +other points. Here we list some pros and cons of various build systems +to help you do the decision yourself. ## GNU Autotools ## ### Pros ### -Excellent support for legacy Unix platforms, large selection of existing modules. +Excellent support for legacy Unix platforms, large selection of +existing modules. ### Cons ### -Needlessly slow, complicated, hard to use correctly, unreliable, painful to debug, incomprehensible 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 ## @@ -24,7 +32,8 @@ Great support for multiple backends (Visual Studio, XCode, etc). ### Cons ### -The scripting language is cumbersome to work with. Some simple things are more complicated than necessary. +The scripting language is cumbersome to work with. Some simple things +are more complicated than necessary. ## SCons ## @@ -34,7 +43,11 @@ Full power of Python available for defining your build. ### Cons ### -Slow. Requires you to pass your configuration settings on every invocation. That is, if you do `scons OPT1 OPT2` and then just `scons`, it will reconfigure everything without settings `OPT1` and `OPT2`. Every other build system remembers build options from the previous invocation. +Slow. Requires you to pass your configuration settings on every +invocation. That is, if you do `scons OPT1 OPT2` and then just +`scons`, it will reconfigure everything without settings `OPT1` and +`OPT2`. Every other build system remembers build options from the +previous invocation. ## Bazel @@ -44,14 +57,22 @@ Proven to scale to very large projects. ## Cons -Implemented in Java. Poor Windows support. Heavily focused on Google's way of doing things (which may be a good or a bad thing). Contributing code requires [signing a CLA](https://bazel.build/contributing.html). +Implemented in Java. Poor Windows support. Heavily focused on Google's +way of doing things (which may be a good or a bad thing). Contributing +code requires [signing a CLA](https://bazel.build/contributing.html). ## Meson ## ### Pros ### -The fastest build system [see measurements](Performance-comparison.md), user friendly, designed to be as invisible to the developer as possible, native support for modern tools (precompiled headers, coverage, Valgrind etc). Not Turing complete so build definition files are easy to read and understand. +The fastest build system [see +measurements](Performance-comparison.md), user friendly, designed to +be as invisible to the developer as possible, native support for +modern tools (precompiled headers, coverage, Valgrind etc). Not Turing +complete so build definition files are easy to read and understand. ### Cons ### -Relatively new so it does not have a large user base yet, and may thus contain some unknown bugs. Visual Studio and XCode backends not as high quality as Ninja one. +Relatively new so it does not have a large user base yet, and may thus +contain some unknown bugs. Visual Studio and XCode backends not as +high quality as Ninja one. diff --git a/docs/markdown/Compiler-properties.md b/docs/markdown/Compiler-properties.md index 1765befda..5978b5d51 100644 --- a/docs/markdown/Compiler-properties.md +++ b/docs/markdown/Compiler-properties.md @@ -1,16 +1,25 @@ # Compiler properties -Not all compilers and platforms are alike. Therefore Meson provides the tools to detect properties of the system during configure time. To get most of this information, you first need to extract the *compiler object* from the main *meson* variable. +Not all compilers and platforms are alike. Therefore Meson provides +the tools to detect properties of the system during configure time. To +get most of this information, you first need to extract the *compiler +object* from the main *meson* variable. ```meson compiler = meson.get_compiler('c') ``` -Here we extract the C compiler. We could also have given the argument `cpp` to get the C++ compiler, `objc` to get the objective C compiler and so on. The call is valid for all languages specified in the *project* declaration. Trying to obtain some other compiler will lead to an unrecoverable error. +Here we extract the C compiler. We could also have given the argument +`cpp` to get the C++ compiler, `objc` to get the objective C compiler +and so on. The call is valid for all languages specified in the +*project* declaration. Trying to obtain some other compiler will lead +to an unrecoverable error. ## System information -This is a bit complex and more thoroughly explained on the page on [cross compilation](Cross-compilation.md). 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.md). But if you just want to +know the operating system your code will run on, issue this command: ```meson host_machine.system() @@ -19,7 +28,9 @@ host_machine.system() Compiler id == -The compiler object has a method called `get_id`, which returns a lower case string describing the "family" of the compiler. It has one of the following values. +The compiler object has a method called `get_id`, which returns a +lower case string describing the "family" of the compiler. It has one +of the following values. | Value | Compiler family | | ----- | ---------------- | @@ -42,7 +53,9 @@ The compiler object has a method called `get_id`, which returns a lower case str Does code compile? == -Sometimes the only way to test the system is to try to compile some sample code and see if it works. This is a two-phase operation. First we define some code using the multiline string operator: +Sometimes the only way to test the system is to try to compile some +sample code and see if it works. This is a two-phase operation. First +we define some code using the multiline string operator: ```meson code = '''#include @@ -56,15 +69,18 @@ Then we can run the test. result = compiler.compiles(code, name : 'basic check') ``` -The variable *result* will now contain either `true` or `false` depending on whether the compilation succeeded or not. The keyword argument `name` is optional. If it is specified, Meson will write the result of the check to its log. +The variable *result* will now contain either `true` or `false` +depending on whether the compilation succeeded or not. The keyword +argument `name` is optional. If it is specified, Meson will write the +result of the check to its log. Does code compile and link? == -Sometimes it is necessary to check whether a certain code fragment not only -compiles, but also links successfully, e.g. to check if a symbol is actually -present in a library. This can be done using the '''.links()''' method on a -compiler object like this: +Sometimes it is necessary to check whether a certain code fragment not +only compiles, but also links successfully, e.g. to check if a symbol +is actually present in a library. This can be done using the +'''.links()''' method on a compiler object like this: ```meson code = '''#include @@ -79,9 +95,9 @@ result = compiler.links(code, args : '-lfoo', name : 'link check') ``` The variable *result* will now contain either `true` or `false` -depending on whether the compilation and linking succeeded or not. The keyword -argument `name` is optional. If it is specified, Meson will write the -result of the check to its log. +depending on whether the compilation and linking succeeded or not. The +keyword argument `name` is optional. If it is specified, Meson will +write the result of the check to its log. Compile and run test application @@ -100,7 +116,9 @@ int main(int argc, char **argv) { result = compiler.run(code, name : 'basic check') ``` -The `result` variable encapsulates the state of the test, which can be extracted with the following methods. The `name` keyword argument works the same as with `compiles`. +The `result` variable encapsulates the state of the test, which can be +extracted with the following methods. The `name` keyword argument +works the same as with `compiles`. | Method | Return value | ------ | ------------ @@ -121,7 +139,11 @@ endif Does a header exist? == -Header files provided by different platforms vary quite a lot. Meson has functionality to detect whether a given header file is available on the system. The test is done by trying to compile a simple test program that includes the specified header. The following snippet describes how this feature can be used. +Header files provided by different platforms vary quite a lot. Meson +has functionality to detect whether a given header file is available +on the system. The test is done by trying to compile a simple test +program that includes the specified header. The following snippet +describes how this feature can be used. ```meson if compiler.has_header('sys/fstat.h') @@ -132,20 +154,31 @@ endif Expression size == -Often you need to determine the size of a particular element (such as `int`, `wchar_t` or `char*`). Using the `compiler` variable mentioned above, the check can be done like this. +Often you need to determine the size of a particular element (such as +`int`, `wchar_t` or `char*`). Using the `compiler` variable mentioned +above, the check can be done like this. ```meson wcharsize = compiler.sizeof('wchar_t', prefix : '#include') ``` -This will put the size of `wchar_t` as reported by sizeof into variable `wcharsize`. The keyword argument `prefix` is optional. If specified its contents is put at the top of the source file. This argument is typically used for setting `#include` directives in configuration files. +This will put the size of `wchar_t` as reported by sizeof into +variable `wcharsize`. The keyword argument `prefix` is optional. If +specified its contents is put at the top of the source file. This +argument is typically used for setting `#include` directives in +configuration files. -In older versions (<= 0.30) meson would error out if the size could not be determined. Since version 0.31 it returns -1 if the size could not be determined. +In older versions (<= 0.30) meson would error out if the size could +not be determined. Since version 0.31 it returns -1 if the size could +not be determined. Does a function exist? == -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` +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') @@ -156,7 +189,9 @@ endif Does a structure contain a member? == -Some platforms have different standard structures. Here's how one would check if a struct called `mystruct` from header `myheader.h contains a member called `some_member`. +Some platforms have different standard structures. Here's how one +would check if a struct called `mystruct` from header `myheader.h +contains a member called `some_member`. ```meson if compiler.has_member('struct mystruct', 'some_member', prefix : '#include') @@ -167,7 +202,10 @@ endif Type alignment == -Most platforms can't access some data types at any address. For example it is common that a `char` can be at any address but a 32 bit integer only at locations which are divisible by four. Determining the alignment of data types is simple. +Most platforms can't access some data types at any address. For +example it is common that a `char` can be at any address but a 32 bit +integer only at locations which are divisible by four. Determining the +alignment of data types is simple. ```meson int_alignment = compiler.alignment('int') # Will most likely contain the value 4. @@ -175,10 +213,13 @@ int_alignment = compiler.alignment('int') # Will most likely contain the value 4 ## Has argument -This method tests if the compiler supports a given command line argument. This is implemented by compiling a small file with the given argument. +This method tests if the compiler supports a given command line +argument. This is implemented by compiling a small file with the given +argument. ```meson has_special_flags = compiler.has_argument('-Wspecialthing') ``` -*Note*: some compilers silently swallow command line arguments they do not understand. Thus this test can not be made 100% reliable. +*Note*: some compilers silently swallow command line arguments they do +not understand. Thus this test can not be made 100% reliable. diff --git a/docs/markdown/Configuring-a-build-directory.md b/docs/markdown/Configuring-a-build-directory.md index c7aa91376..edf3d97e7 100644 --- a/docs/markdown/Configuring-a-build-directory.md +++ b/docs/markdown/Configuring-a-build-directory.md @@ -4,11 +4,18 @@ 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. +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. -The main tool for this is the `mesonconf` script. You may also use the `mesongui` graphical application if you want. However this document describes the use of the command line client. +The main tool for this is the `mesonconf` script. You may also use the +`mesongui` graphical application if you want. However this document +describes the use of the command line client. -You invoke `mesonconf` by giving it the location of your build dir. If omitted, the current working directory is used instead. Here's a sample output for a simple project. +You invoke `mesonconf` by giving it the location of your build dir. If +omitted, the current working directory is used instead. Here's a +sample output for a simple project. Core properties @@ -43,8 +50,14 @@ You invoke `mesonconf` by giving it the location of your build dir. If omitted, This project does not have any options -These are all the options available for the current project arranged into related groups. The first column in every field is the name of the option. To set an option you use the `-D` option. For example, changing the installation prefix from `/usr/local` to `/tmp/testroot` you would issue the following command. +These are all the options available for the current project arranged +into related groups. The first column in every field is the name of +the option. To set an option you use the `-D` option. For example, +changing the installation prefix from `/usr/local` to `/tmp/testroot` +you would issue the following command. mesonconf -Dprefix=/tmp/testroot -Then you would run your build command (usually `ninja`), 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. +Then you would run your build command (usually `ninja`), 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. diff --git a/docs/markdown/Contact-information.md b/docs/markdown/Contact-information.md index 407557306..87a76a549 100644 --- a/docs/markdown/Contact-information.md +++ b/docs/markdown/Contact-information.md @@ -1,7 +1,14 @@ # Contact information -For general discussion and questions, it is strongly recommended that you use the [mailing list](https://groups.google.com/forum/#!forum/mesonbuild). +For general discussion and questions, it is strongly recommended that +you use the [mailing +list](https://groups.google.com/forum/#!forum/mesonbuild). -If you find bugs, please file them in the [issue tracker](https://github.com/jpakkane/meson/issues). +If you find bugs, please file them in the [issue +tracker](https://github.com/jpakkane/meson/issues). -The maintainer of Meson is Jussi Pakkanen. You should usually not contact him privately but rather use the channels listed above. However if such a need arises, he can be reached at gmail where his username is `jpakkane` (that is not a typo, the last letter is indeed *e*). +The maintainer of Meson is Jussi Pakkanen. You should usually not +contact him privately but rather use the channels listed +above. However if such a need arises, he can be reached at gmail where +his username is `jpakkane` (that is not a typo, the last letter is +indeed *e*). diff --git a/docs/markdown/Custom-build-targets.md b/docs/markdown/Custom-build-targets.md index a425f8cbf..8bd31dba2 100644 --- a/docs/markdown/Custom-build-targets.md +++ b/docs/markdown/Custom-build-targets.md @@ -4,7 +4,10 @@ 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. +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. ```meson comp = find_program('custom_compiler') @@ -20,12 +23,21 @@ mytarget = custom_target('targetname', install_dir : 'subdir') ``` -This would generate the binary `output.bin` and install it to `${prefix}/subdir/output.bin`. Variable substitution works just like it does for source generation. +This would generate the binary `output.bin` and install it to +`${prefix}/subdir/output.bin`. Variable substitution works just like +it does for source generation. ## Details on compiler invocations ## -Meson only permits you to specify one command to run. This is by design as writing shell pipelines into build definition files leads to code that is very hard to maintain. If your compilation requires multiple steps you need to write a wrapper script that does all the necessary work. When doing this you need to be mindful of the following issues: +Meson only permits you to specify one command to run. This is by +design as writing shell pipelines into build definition files leads to +code that is very hard to maintain. If your compilation requires +multiple steps you need to write a wrapper script that does all the +necessary work. When doing this you need to be mindful of the +following issues: * do not assume that the command is invoked in any specific directory -* a target called `target` file `outfile` defined in subdir `subdir` must be written to `build_dir/subdir/foo.dat` -* if you need a subdirectory for temporary files, use `build_dir/subdir/target.dir` +* a target called `target` file `outfile` defined in subdir `subdir` + must be written to `build_dir/subdir/foo.dat` +* if you need a subdirectory for temporary files, use + `build_dir/subdir/target.dir` diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index faf410213..9050696be 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -4,14 +4,22 @@ 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') exe = executable('zlibprog', 'prog.c', dependencies : zdep) ``` -First Meson is told to find the external library `zlib` and error out if it is not found. The `version` keyword is optional and specifies a version requirement for the dependency. Then an executable is built using the specified dependency. Note how the user does not need to manually handle compiler or linker flags or deal with any other minutiae. +First Meson is told to find the external library `zlib` and error out +if it is not found. The `version` keyword is optional and specifies a +version requirement for the dependency. Then an executable is built +using the specified dependency. Note how the user does not need to +manually handle compiler or linker flags or deal with any other +minutiae. If you have multiple dependencies, pass them as an array: @@ -19,7 +27,8 @@ If you have multiple dependencies, pass them as an array: executable('manydeps', 'file.c', dependencies : [dep1, dep2, dep3, dep4]) ``` -If the dependency is optional, you can tell Meson not to error out if the dependency is not found and then do further configuration. +If the dependency is optional, you can tell Meson not to error out if +the dependency is not found and then do further configuration. ```meson opt_dep = dependency('somedep', required : false) @@ -30,26 +39,39 @@ else endif ``` -You can pass the `opt_dep` variable to target construction functions whether the actual dependency was found or not. Meson will ignore non-found dependencies. +You can pass the `opt_dep` variable to target construction functions +whether the actual dependency was found or not. Meson will ignore +non-found dependencies. -The dependency detector works with all libraries that provide a `pkg-config` file. Unfortunately several packages don't provide pkg-config files. Meson has autodetection support for some of these. +The dependency detector works with all libraries that provide a +`pkg-config` file. Unfortunately several packages don't provide +pkg-config files. Meson has autodetection support for some of these. ## Boost ## -Boost is not a single dependency but rather a group of different libraries. To use Boost with Meson, simply list which Boost modules you would like to use. +Boost is not a single dependency but rather a group of different +libraries. To use Boost with Meson, simply list which Boost modules +you would like to use. ```meson boost_dep = dependency('boost', modules : ['thread', 'utility']) exe = executable('myprog', 'file.cc', dependencies : boost_dep) ``` -You can call `dependency` multiple times with different modules and use those to link against your targets. +You can call `dependency` multiple times with different modules and +use those to link against your targets. -If your boost headers or libraries are in non-standard locations you can set the BOOST_ROOT, BOOST_INCLUDEDIR, and/or BOOST_LIBRARYDIR environment variables. +If your boost headers or libraries are in non-standard locations you +can set the BOOST_ROOT, BOOST_INCLUDEDIR, and/or BOOST_LIBRARYDIR +environment variables. ## GTest and GMock ## -GTest and GMock come as sources that must be compiled as part of your project. With Meson you don't have to care about the details, just pass `gtest` or `gmock` to `dependency` and it will do everything for you. If you want to use GMock, it is recommended to use GTest as well, as getting it to work standalone is tricky. +GTest and GMock come as sources that must be compiled as part of your +project. With Meson you don't have to care about the details, just +pass `gtest` or `gmock` to `dependency` and it will do everything for +you. If you want to use GMock, it is recommended to use GTest as well, +as getting it to work standalone is tricky. ## MPI ## @@ -60,15 +82,17 @@ language-specific, you must specify the requested language using the * `dependency('mpi', language='cpp')` for the C++ MPI headers and libraries * `dependency('mpi', language='fortran')` for the Fortran MPI headers and libraries -Meson prefers pkg-config for MPI, but if your MPI implementation does not -provide them, it will search for the standard wrapper executables, `mpic`, -`mpicxx`, `mpic++`, `mpifort`, `mpif90`, `mpif77`. If these are not in your -path, they can be specified by setting the standard environment variables -`MPICC`, `MPICXX`, `MPIFC`, `MPIF90`, or `MPIF77`, during configuration. +Meson prefers pkg-config for MPI, but if your MPI implementation does +not provide them, it will search for the standard wrapper executables, +`mpic`, `mpicxx`, `mpic++`, `mpifort`, `mpif90`, `mpif77`. If these +are not in your path, they can be specified by setting the standard +environment variables `MPICC`, `MPICXX`, `MPIFC`, `MPIF90`, or +`MPIF77`, during configuration. ## Qt5 ## -Meson has native Qt5 support. Its usage is best demonstrated with an example. +Meson has native Qt5 support. Its usage is best demonstrated with an +example. ```meson qt5_mod = import('qt5') @@ -88,7 +112,15 @@ q5exe = executable('qt5test', dependencies: qt5widgets) ``` -Here we have an UI file created with Qt Designer and one source and header file each that require preprocessing with the `moc` tool. We also define a resource file to be compiled with `rcc`. We just have to tell Meson which files are which and it will take care of invoking all the necessary tools in the correct order, which is done with the `preprocess` method of the `qt5` module. Its output is simply put in the list of sources for the target. The `modules` keyword of `dependency` works just like it does with Boost. It tells which subparts of Qt the program uses. +Here we have an UI file created with Qt Designer and one source and +header file each that require preprocessing with the `moc` tool. We +also define a resource file to be compiled with `rcc`. We just have to +tell Meson which files are which and it will take care of invoking all +the necessary tools in the correct order, which is done with the +`preprocess` method of the `qt5` module. Its output is simply put in +the list of sources for the target. The `modules` keyword of +`dependency` works just like it does with Boost. It tells which +subparts of Qt the program uses. ## Pcap @@ -102,7 +134,9 @@ pcap_dep = dependency('pcap', version : '>=1.0') ## Declaring your own -You can declare your own dependency objects that can be used interchangeably with dependency objects obtained from the system. The syntax is straightforward: +You can declare your own dependency objects that can be used +interchangeably with dependency objects obtained from the system. The +syntax is straightforward: ```meson my_inc = include_directories(...) @@ -111,4 +145,5 @@ my_dep = declare_dependency(link_with : my_lib, include_directories : my_inc) ``` -This declares a dependency that adds the given include directories and static library to any target you use it in. +This declares a dependency that adds the given include directories and +static library to any target you use it in. diff --git a/docs/markdown/External-commands.md b/docs/markdown/External-commands.md index f597b0cef..9336ec314 100644 --- a/docs/markdown/External-commands.md +++ b/docs/markdown/External-commands.md @@ -4,7 +4,8 @@ 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. +As a part of the software configuration, you may want to get extra +data by running external commands. The basic syntax is the following. ```meson r = run_command('command', 'arg1', 'arg2', 'arg3') @@ -15,6 +16,19 @@ output = r.stdout().strip() errortxt = r.stderr().strip() ``` -The `run_command` function returns an object that can be queried for return value and text written to stdout and stderr. The `strip` method call is used to strip trailing and leading whitespace from strings. Usually output from command line programs ends in a newline, which is unwanted in string variables. The first argument can be either a string or an executable you have detected earlier with `find_program`. +The `run_command` function returns an object that can be queried for +return value and text written to stdout and stderr. The `strip` method +call is used to strip trailing and leading whitespace from +strings. Usually output from command line programs ends in a newline, +which is unwanted in string variables. The first argument can be +either a string or an executable you have detected earlier with +`find_program`. -Note that you can not pass your command line as a single string. That is, calling `run_command('do_something foo bar')` will not work. You must either split up the string into separate arguments or pass the split command as an array. It should also be noted that Meson will not pass the command to the shell, so any command lines that try to use things such as environment variables, backticks or pipelines will not work. If you require shell semantics, write your command into a script file and call that with `run_command`. +Note that you can not pass your command line as a single string. That +is, calling `run_command('do_something foo bar')` will not work. You +must either split up the string into separate arguments or pass the +split command as an array. It should also be noted that Meson will not +pass the command to the shell, so any command lines that try to use +things such as environment variables, backticks or pipelines will not +work. If you require shell semantics, write your command into a script +file and call that with `run_command`. diff --git a/docs/markdown/Precompiled-headers.md b/docs/markdown/Precompiled-headers.md index feac7f0c3..22fd762b1 100644 --- a/docs/markdown/Precompiled-headers.md +++ b/docs/markdown/Precompiled-headers.md @@ -4,11 +4,22 @@ 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. - -Precompiled headers are a tool to mitigate this issue. Basically what they do is parse the headers and then serialize the compiler's internal state to disk. The downside of precompiled headers is that they are tricky to set up. Meson has native support for precompiled headers, but using them takes a little work. - -A precompiled header file is relatively simple. It is a header file that contains `#include` directives for the system headers to precompile. Here is a C++ example. +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. + +Precompiled headers are a tool to mitigate this issue. Basically what +they do is parse the headers and then serialize the compiler's +internal state to disk. The downside of precompiled headers is that +they are tricky to set up. Meson has native support for precompiled +headers, but using them takes a little work. + +A precompiled header file is relatively simple. It is a header file +that contains `#include` directives for the system headers to +precompile. Here is a C++ example. ```cpp #include @@ -16,7 +27,13 @@ A precompiled header file is relatively simple. It is a header file that contain #include ``` -In Meson, precompiled header files are always per-target. That is, the given precompiled header is used when compiling every single file in the target. Due to limitations of the underlying compilers, this header file must not be in the same subdirectory as any of the source files. It is strongly recommended that you create a subdirectory called `pch` in the target directory and put the header files (and nothing else) there. +In Meson, precompiled header files are always per-target. That is, the +given precompiled header is used when compiling every single file in +the target. Due to limitations of the underlying compilers, this +header file must not be in the same subdirectory as any of the source +files. It is strongly recommended that you create a subdirectory +called `pch` in the target directory and put the header files (and +nothing else) there. Toggling the usage of precompiled headers -- @@ -33,15 +50,23 @@ order) and working around compiler bugs. Using precompiled headers with GCC and derivatives -- -Once you have a file to precompile, you can enable the use of pch for a give target with a *pch* keyword argument. As an example, here's how you would use it with a C binary. +Once you have a file to precompile, you can enable the use of pch for +a give target with a *pch* keyword argument. As an example, here's how +you would use it with a C binary. ```meson executable('myexe', sources : sourcelist, c_pch : 'pch/myexe_pch.h') ``` -You should note that your source files must _not_ include the file `myexe_pch.h` and you must _not_ add the pch subdirectory to your search path. Meson will make the compiler include the pch with compiler options. If you want to disable pch (because of, say, compiler bugs), it can be done entirely on the build system side with no changes to source code. +You should note that your source files must _not_ include the file +`myexe_pch.h` and you must _not_ add the pch subdirectory to your +search path. Meson will make the compiler include the pch with +compiler options. If you want to disable pch (because of, say, +compiler bugs), it can be done entirely on the build system side with +no changes to source code. -You can use precompiled headers on any build target. If your target has multiple languages, you can specify multiple pch files like this. +You can use precompiled headers on any build target. If your target +has multiple languages, you can specify multiple pch files like this. ```meson executable('multilang', sources : srclist, @@ -51,7 +76,11 @@ 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 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: +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) @@ -68,6 +97,9 @@ 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. +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.