Here you will find snippets to use Meson with various CI such as Travis and AppVeyor.
Here you will find snippets to use Meson with various CI such as
Travis and AppVeyor.
Please [file an issue](https://github.com/mesonbuild/meson/issues/new) if these instructions don't work for you.
Please [file an issue](https://github.com/mesonbuild/meson/issues/new)
if these instructions don't work for you.
## Travis for OS X and Linux (with Docker)
Travis for Linux provides ancient versions of Ubuntu which will likely cause problems building your projects regardless of which build system you're using. We recommend using Docker to get a more-recent version of Ubuntu and installing Ninja, Python3, and Meson inside it.
Travis for Linux provides ancient versions of Ubuntu which will likely
cause problems building your projects regardless of which build system
you're using. We recommend using Docker to get a more-recent version
of Ubuntu and installing Ninja, Python3, and Meson inside it.
This `yml` file is derived from the [configuration used by Meson for running its own tests](https://github.com/mesonbuild/meson/blob/master/.travis.yml).
This `yml` file is derived from the [configuration used by Meson for
@ -4,20 +4,34 @@ short-description: Creating universal Linux binaries
# Creating Linux binaries
Creating Linux binaries that can be downloaded and run on any distro (like .dmg packages for OSX or .exe installers for Windows) has traditionally been difficult. This is even more tricky if you want to use modern compilers and features, which is especially desired in game development. There is still no simple turn-key solution for this problem but with a bit of setup it can be relatively straightforward.
Creating Linux binaries that can be downloaded and run on any distro
(like .dmg packages for OSX or .exe installers for Windows) has
traditionally been difficult. This is even more tricky if you want to
use modern compilers and features, which is especially desired in game
development. There is still no simple turn-key solution for this
problem but with a bit of setup it can be relatively straightforward.
## Installing system and GCC
First you need to do a fresh operating system install. You can use spare hardware, VirtualBox, cloud or whatever you want. Note that the distro you install must be *at least as old* as the oldest release you wish to support. Debian stable is usually a good choice, though immediately after its release you might want to use Debian oldstable or the previous Ubuntu LTS. The oldest supported version of CentOS is also a good choice.
First you need to do a fresh operating system install. You can use
spare hardware, VirtualBox, cloud or whatever you want. Note that the
distro you install must be *at least as old* as the oldest release you
wish to support. Debian stable is usually a good choice, though
immediately after its release you might want to use Debian oldstable
or the previous Ubuntu LTS. The oldest supported version of CentOS is
also a good choice.
Once you have installed the system, you need to install build-dependencies for GCC. In Debian-based distros this can be done with the following commands:
Once you have installed the system, you need to install
build-dependencies for GCC. In Debian-based distros this can be done
Then create a `src` subdirectory in your home directory. Copy-paste the following into `install_gcc.sh` and execute it.
Then create a `src` subdirectory in your home directory. Copy-paste
the following into `install_gcc.sh` and execute it.
```bash
#!/bin/sh
@ -46,21 +60,46 @@ Log out and back in and now your build environment is ready to use.
## Adding other tools
Old distros might have too old versions of some tools. For Meson this could include Python 3 and Ninja. If this is the case you need to download, build and install new versions into `~/devroot` in the usual way.
Old distros might have too old versions of some tools. For Meson this
could nclude Python 3 and Ninja. If this is the case you need to
download, build and install new versions into `~/devroot` in the usual
way.
## Adding dependencies
You want to embed and statically link every dependency you can (especially C++ dependencies). Meson's [Wrap package manager](Wrap-dependency-system-manual.md) might be of use here. This is equivalent to what you would do on Windows, OSX, Android etc. Sometimes static linking is not possible. In these cases you need to copy the .so files inside your package. Let's use SDL2 as an example. First we download and install it as usual giving it our custom install prefix (that is, `./configure --prefix=${HOME}/devroot`). This makes Meson's dependency detector pick it up automatically.
You want to embed and statically link every dependency you can
(especially C++ dependencies). Meson's [Wrap package
manager](Wrap-dependency-system-manual.md) might be of use here. This
is equivalent to what you would do on Windows, OSX, Android
etc. Sometimes static linking is not possible. In these cases you need
to copy the .so files inside your package. Let's use SDL2 as an
example. First we download and install it as usual giving it our
custom install prefix (that is, `./configure
--prefix=${HOME}/devroot`). This makes Meson's dependency detector
pick it up automatically.
## Building and installing
Building happens in much the same way as normally. There are just two things to note. First, you must tell GCC to link the C++ standard library statically. If you don't then your app is guaranteed to break as different distros have binary-incompatible C++ libraries. The second thing is that you need to point your install prefix to some empty staging area. Here's the meson command to do that:
Building happens in much the same way as normally. There are just two
things to note. First, you must tell GCC to link the C++ standard
library statically. If you don't then your app is guaranteed to break
as different distros have binary-incompatible C++ libraries. The
second thing is that you need to point your install prefix to some
empty staging area. Here's the meson command to do that:
The aim is to put the executable in `/tmp/myapp/bin` and shared libraries to `/tmp/myapp/lib`. The next thing you need is the embedder. It takes your dependencies (in this case only `libSDL2-2.0.so.0`) and copies them in the lib directory. Depending on your use case you can either copy the files by hand or write a script that parses the output of `ldd binary_file`. Be sure not to copy system libraries (`libc`, `libpthread`, `libm` etc). For an example, see the [sample project](https://github.com/jpakkane/meson/tree/master/manual%20tests/4%20standalone%20binaries).
The aim is to put the executable in `/tmp/myapp/bin` and shared
libraries to `/tmp/myapp/lib`. The next thing you need is the
embedder. It takes your dependencies (in this case only
`libSDL2-2.0.so.0`) and copies them in the lib directory. Depending on
your use case you can either copy the files by hand or write a script
that parses the output of `ldd binary_file`. Be sure not to copy
system libraries (`libc`, `libpthread`, `libm` etc). For an example,
If you try to run the program now it will most likely fail to start or crashes. The reason for this is that the system does not know that the executable needs libraries from the `lib` directory. The solution for this is a simple wrapper script. Create a script called `myapp.sh` with the following content:
If you try to run the program now it will most likely fail to start or
crashes. The reason for this is that the system does not know that the
executable needs libraries from the `lib` directory. The solution for
this is a simple wrapper script. Create a script called `myapp.sh`
with the following content:
```bash
#!/bin/bash
@ -86,4 +129,6 @@ Install it with this Meson snippet:
install_data('myapp.sh', install_dir : '.')
```
And now you are done. Zip up your `/tmp/myapp` directory and you have a working binary ready for deployment. To run the program, just unzip the file and run `myapp.sh`.
And now you are done. Zip up your `/tmp/myapp` directory and you have
a working binary ready for deployment. To run the program, just unzip
@ -4,15 +4,27 @@ short-description: Tools to create OS X packages
# Creating OSX packages
Meson does not have native support for building OSX packages but it does provide all the tools you need to create one yourself. The reason for this is that it is a very hard task to write a system that provides for all the different ways to do that but it is very easy to write simple scripts for each application.
Meson does not have native support for building OSX packages but it
does provide all the tools you need to create one yourself. The reason
for this is that it is a very hard task to write a system that
provides for all the different ways to do that but it is very easy to
write simple scripts for each application.
Sample code for this can be found in [the Meson manual test suite](https://github.com/jpakkane/meson/tree/master/manual%20tests/4%20standalone%20binaries).
Sample code for this can be found in [the Meson manual test
OSX app bundles are actually extremely simple. They are just a directory of files in a certain format. All the details you need to know are on [this page](https://stackoverflow.com/questions/1596945/building-osx-app-bundle) and it is highly recommended that you read it first.
OSX app bundles are actually extremely simple. They are just a
directory of files in a certain format. All the details you need to
and it is highly recommended that you read it first.
Let's assume that we are creating our app bundle into `/tmp/myapp.app`. Suppose we have one executable, so we need to install that into `Contents/MacOS`. If we define the executable like this:
Let's assume that we are creating our app bundle into
`/tmp/myapp.app`. Suppose we have one executable, so we need to
install that into `Contents/MacOS`. If we define the executable like
Now when we do `ninja 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.
Now when we do `ninja 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.
Next we need to install an `Info.plist` file and an icon. For those we need the following two Meson definitions.
Next we need to install an `Info.plist` file and an icon. For those we
The format of `Info.plist` can be found in the link or the sample project linked above. Be careful, the sample code on the linked page is malformed, it is missing a less than character (<) before `!DOCTYPE`. The simplest way to get an icon in the `icns` format is to save your image as a tiff an then use the `tiff2icns` helper application that comes with XCode.
The format of `Info.plist` can be found in the link or the sample
project linked above. Be careful, the sample code on the linked page
is malformed, it is missing a less than character (<) before
`!DOCTYPE`. The simplest way to get an icon in the `icns` format is to
save your image as a tiff an then use the `tiff2icns` helper
application that comes with XCode.
Some applications assume that the working directory of the app process is the same where the binary executable is. If this is the case for you, then you need to create a wrapper script that looks like this:
Some applications assume that the working directory of the app process
is the same where the binary executable is. If this is the case for
you, then you need to create a wrapper script that looks like this:
and make sure that you specify `myapp.sh` as the executable to run in your `Info.plist`.
and make sure that you specify `myapp.sh` as the executable to run in
your `Info.plist`.
If you are not using any external libraries, this is all you need to do. You now have a full app bundle in `/tmp/myapp.app` that you can use. Most applications use third party frameworks and libraries, though, so you need to add them to the bundle so it will work on other peoples' machines.
If you are not using any external libraries, this is all you need to
do. You now have a full app bundle in `/tmp/myapp.app` that you can
use. Most applications use third party frameworks and libraries,
though, so you need to add them to the bundle so it will work on other
peoples' machines.
As an example we are going to use the [SDL2](https://libsdl.org/) framework. In order to bundle it in our app, we first specify an installer script to run.
As an example we are going to use the [SDL2](https://libsdl.org/)
framework. In order to bundle it in our app, we first specify an
installer script to run.
```meson
meson.add_install_script('install_script.sh')
```
The install script does two things. First it copies the whole framework into our bundle.
The install script does two things. First it copies the whole
Then it needs to alter the library search path of our executable(s). This tells OSX that the libraries your app needs are inside your bundle. In the case of SDL2, the invocation goes like this:
Then it needs to alter the library search path of our
executable(s). This tells OSX that the libraries your app needs are
inside your bundle. In the case of SDL2, the invocation goes like
This is the part of OSX app bundling that you must always do manually. OSX dependencies come in many shapes and forms and unfortunately there is no reliable automatic way to determine how each dependency should be handled. Frameworks go to the `Frameworks` directory while plain `.dylib` files usually go to `Contents/Resources/lib` (but you can put them wherever you like). To get this done you have to check what your program links against with `otool -L /path/to/binary` and manually add the copy and fix steps to your install script. Do not copy system libraries inside your bundle, though.
This is the part of OSX app bundling that you must always do
manually. OSX dependencies come in many shapes and forms and
unfortunately there is no reliable automatic way to determine how each
dependency should be handled. Frameworks go to the `Frameworks`
directory while plain `.dylib` files usually go to
`Contents/Resources/lib` (but you can put them wherever you like). To
get this done you have to check what your program links against with
`otool -L /path/to/binary` and manually add the copy and fix steps to
your install script. Do not copy system libraries inside your bundle,
though.
After this you have a fully working, self-contained OSX app bundle ready for distribution.
After this you have a fully working, self-contained OSX app bundle
ready for distribution.
## Creating a .dmg installer
A .dmg installer is similarly quite simple, at its core it is basically a fancy compressed archive. A good description can be found on [this page](https://el-tramo.be/guides/fancy-dmg/). Please read it and create a template image file according to its instructions.
A .dmg installer is similarly quite simple, at its core it is
basically a fancy compressed archive. A good description can be found
on [this page](https://el-tramo.be/guides/fancy-dmg/). Please read it
and create a template image file according to its instructions.
The actual process of creating the installer is very simple: you mount the template image, copy your app bundle in it, unmount it and convert the image into a compressed archive. The actual commands to do this are not particularly interesting, feel free to steal them from either the linked page above or from the sample script in Meson's test suite.
The actual process of creating the installer is very simple: you mount
the template image, copy your app bundle in it, unmount it and convert
the image into a compressed archive. The actual commands to do this
are not particularly interesting, feel free to steal them from either
the linked page above or from the sample script in Meson's test suite.
## Putting it all together
There are many ways to put the .dmg installer together and different people will do it in different ways. The linked sample code does it by having two different scripts. This separates the different pieces generating the installer into logical pieces.
There are many ways to put the .dmg installer together and different
people will do it in different ways. The linked sample code does it by
having two different scripts. This separates the different pieces
generating the installer into logical pieces.
`install_script.sh` only deals with embedding dependencies and fixing the library paths.
`install_script.sh` only deals with embedding dependencies and fixing
the library paths.
`build_osx_installer.sh` sets up the build with the proper paths, compiles, installs and generates the .dmg package.
`build_osx_installer.sh` sets up the build with the proper paths,
compiles, installs and generates the .dmg package.
The main reasoning here is that in order to build a complete OSX installer package from source, all you need to do is to cd into the source tree and run `./build_osx_installer.sh`. To build packages on other platforms you would write scripts such as `build_windows_installer.bat` and so on.
The main reasoning here is that in order to build a complete OSX
installer package from source, all you need to do is to cd into the
source tree and run `./build_osx_installer.sh`. To build packages on
In addition to development, almost all projects provide periodical source releases. These are standalone packages (usually either in tar or zip format) of the source code. They do not contain any revision control metadata, only the source code.
In addition to development, almost all projects provide periodical
source releases. These are standalone packages (usually either in tar
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:
Meson provides a simple way of generating these. It consists of a
single command:
ninja dist
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. 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.
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. 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).
**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
@ -4,19 +4,55 @@ short-description: Overview of the Meson build system
# Overview
Meson is a build system that is designed to be as user-friendly as possible without sacrificing performance. The main tool for this is a custom language that the user uses to describe the structure of his build. The main design goals of this language has been simplicity, clarity and conciseness. Much inspiration was drawn from the Python programming language, which is considered very readable, even to people who have not programmed in Python before.
Another main idea has been to provide first class support for modern programming tools and best practices. These include features as varied as unit testing, code coverage reporting, precompiled headers and the like. All of these features should be immediately available to any project using Meson. The user should not need to hunt for third party macros or write shell scripts to get these features. They should just work out of the box.
This power should not come at the expense of limited usability. Many software builds require unorthodox steps. A common example is that you first need to build a custom tool and then use that tool to generate more source code to build. This functionality needs to be supported and be as easy to use as other parts of the system.
Meson is a build system that is designed to be as user-friendly as
possible without sacrificing performance. The main tool for this is a
custom language that the user uses to describe the structure of his
build. The main design goals of this language has been simplicity,
clarity and conciseness. Much inspiration was drawn from the Python
programming language, which is considered very readable, even to
people who have not programmed in Python before.
Another main idea has been to provide first class support for modern
programming tools and best practices. These include features as varied
as unit testing, code coverage reporting, precompiled headers and the
like. All of these features should be immediately available to any
project using Meson. The user should not need to hunt for third party
macros or write shell scripts to get these features. They should just
work out of the box.
This power should not come at the expense of limited usability. Many
software builds require unorthodox steps. A common example is that you
first need to build a custom tool and then use that tool to generate
more source code to build. This functionality needs to be supported
and be as easy to use as other parts of the system.
Terminology
--
Meson follows the overall structure of other popular build systems, such as CMake and GNU Autotools. This means that the build is divided into two discrete steps: *configure step* and *build step*. The first step inspects the system, checks for dependencies and does all other steps necessary to configure the build. It then generates the actual build system. The second step is simply executing this generated build system. The end result is a bunch of *build targets*, which are usually executables and shared and static libraries.
The directory that contains the source code is called the *source directory*. Correspondingly the directory where the output is written is called the *build directory*. In other build systems it is common to have these two be the same directory. This is called an *in-source build*. The case where the build directory is separate is called an *out-of-source build*.
What sets Meson apart from most build systems is that it enforces a separate build directory. All files created by the build system are put in the build directory. It is actually impossible to do an in-source build. For people used to building inside their source tree, this may seem like a needless complication. However there are several benefits to doing only out-of-source builds. These will be explained in the next chapter.
When the source code is built, a set of *unit tests* is usually run. They ensure that the program is working as it should. If it does, the build result can be *installed* after which it is ready for use.
Meson follows the overall structure of other popular build systems,
such as CMake and GNU Autotools. This means that the build is divided
into two discrete steps: *configure step* and *build step*. The first
step inspects the system, checks for dependencies and does all other
steps necessary to configure the build. It then generates the actual
build system. The second step is simply executing this generated build
system. The end result is a bunch of *build targets*, which are
usually executables and shared and static libraries.
The directory that contains the source code is called the *source
directory*. Correspondingly the directory where the output is written
is called the *build directory*. In other build systems it is common
to have these two be the same directory. This is called an *in-source
build*. The case where the build directory is separate is called an
*out-of-source build*.
What sets Meson apart from most build systems is that it enforces a
separate build directory. All files created by the build system are
put in the build directory. It is actually impossible to do an
in-source build. For people used to building inside their source tree,
this may seem like a needless complication. However there are several
benefits to doing only out-of-source builds. These will be explained
in the next chapter.
When the source code is built, a set of *unit tests* is usually
run. They ensure that the program is working as it should. If it does,
the build result can be *installed* after which it is ready for use.
@ -5,7 +5,9 @@ short-description: Guide to get started using meson
# Using Meson
Meson has been designed to be as easy to use as possible. This page outlines the basic use cases. For more advanced cases refer to Meson's command line help which is accessible with the command `meson --help`.
Meson has been designed to be as easy to use as possible. This page
outlines the basic use cases. For more advanced cases refer to Meson's
command line help which is accessible with the command `meson --help`.
Requirements
--
@ -15,7 +17,8 @@ Meson has two main dependencies.
* [Python 3](https://python.org)
* [Ninja](https://github.com/ninja-build/ninja/)
Ninja is only needed if you use the Ninja backend. Meson can also generate native VS and XCode project files.
Ninja is only needed if you use the Ninja backend. Meson can also
generate native VS and XCode project files.
On Ubuntu these can be easily installed with the following command:
@ -29,14 +32,18 @@ The best way to get Meson is to `pip install` it for your user
$ pip3 install --user meson
```
You can also use Meson as packaged by your distro, but beware that due to our frequent release cycle and development speed this version might be out of date.
You can also use Meson as packaged by your distro, but beware that due
to our frequent release cycle and development speed this version might
be out of date.
Another option is to clone the git repository and run it directly from there.
Another option is to clone the git repository and run it directly from
there.
Compiling a Meson project
--
The most common use case of Meson is compiling code on a code base you are working on. The steps to take are very simple.
The most common use case of Meson is compiling code on a code base you
are working on. The steps to take are very simple.
```console
$ cd /path/to/source/root
@ -45,16 +52,33 @@ $ ninja
$ ninja test
```
The only thing to note is that you need to create a separate build directory. Meson will not allow you to build source code inside your source tree. All build artifacts are stored in the build 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 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`.
Meson will automatically add compiler flags to enable debug information and compiler warnings (i.e. `-g` and `-Wall`). This means the user does not have to deal with them and can instead focus on coding.
The only thing to note is that you need to create a separate build
directory. Meson will not allow you to build source code inside your
source tree. All build artifacts are stored in the build
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
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`.
Meson will automatically add compiler flags to enable debug
information and compiler warnings (i.e. `-g` and `-Wall`). This means
the user does not have to deal with them and can instead focus on
coding.
Using Meson as a distro packager
--
Distro packagers usually want total control on the build flags used. Meson supports this use case natively. The commands needed to build and install Meson projects are the following.
Distro packagers usually want total control on the build flags
used. Meson supports this use case natively. The commands needed to
build and install Meson projects are the following.
The command line switch `--buildtype=plain` tells Meson not to add its own flags to the command line. This gives the packager total control on used flags.
The command line switch `--buildtype=plain` tells Meson not to add its
own flags to the command line. This gives the packager total control
on used flags.
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`.
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`.
As distro builds happen always from scratch, we recommend you to enable [unity builds](Unity-builds.md) whenever possible on your packages because they are faster and produce better code.
As distro builds happen always from scratch, we recommend you to
enable [unity builds](Unity-builds.md) whenever possible on your
packages because they are faster and produce better code.
This page shows from the ground up how to create a Meson build definition for a simple project. Then we expand it to use external dependencies to show how easily they can be integrated into your project.
This page shows from the ground up how to create a Meson build
definition for a simple project. Then we expand it to use external
dependencies to show how easily they can be integrated into your
project.
The humble beginning
-----
Let's start with the most basic of programs, the classic hello example. First we create a file `main.c` which holds the source. It looks like this.
Let's start with the most basic of programs, the classic hello
example. First we create a file `main.c` which holds the source. It
looks like this.
```c
#include<stdio.h>
@ -20,20 +25,27 @@ int main(int argc, char **argv) {
}
```
Then we create a Meson build description and put it in a file called `meson.build` in the same directory. Its contents are the following.
Then we create a Meson build description and put it in a file called
`meson.build` in the same directory. Its contents are the following.
```meson
project('tutorial', 'c')
executable('demo', 'main.c')
```
That is all. We are now ready to build our application. First we need to initialize the build by going into the source directory and issuing the following commands.
That is all. We are now ready to build our application. First we need
to initialize the build by going into the source directory and issuing
the following commands.
```console
$ meson builddir
```
We create a separate build directory to hold all of the compiler output. Meson is different from some other build systems in that it does not permit in-source builds. You must always create a separate build directory. Common convention is to put the default build directory in a subdirectory of your top level source directory.
We create a separate build directory to hold all of the compiler
output. Meson is different from some other build systems in that it
does not permit in-source builds. You must always create a separate
build directory. Common convention is to put the default build
directory in a subdirectory of your top level source directory.
When Meson is run it prints the following output.
@ -66,7 +78,10 @@ This produces the expected output.
Adding dependencies
-----
Just printing text is a bit old fashioned. Let's update our program to create a graphical window instead. We'll use the [GTK+](https://gtk.org) widget toolkit. First we edit the main file to use GTK+. The new version looks like this.
Just printing text is a bit old fashioned. Let's update our program to
create a graphical window instead. We'll use the
[GTK+](https://gtk.org) widget toolkit. First we edit the main file to
use GTK+. The new version looks like this.
```c
#include<gtk/gtk.h>
@ -82,7 +97,8 @@ int main(int argc, char **argv) {
}
```
Then we edit the Meson file, instructing it to find and use the GTK+ libraries.
Then we edit the Meson file, instructing it to find and use the GTK+
Now we are ready to build. The thing to notice is that we do *not* need to recreate our build directory, run any sort of magical commands or the like. Instead we just type the exact same command as if we were rebuilding our code without any build system changes.
Now we are ready to build. The thing to notice is that we do *not*
need to recreate our build directory, run any sort of magical commands
or the like. Instead we just type the exact same command as if we were
rebuilding our code without any build system changes.
```
$ ninja
```
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 build definitions and will take care of everything so users don't have to care. In this case the following output is produced.
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
build definitions and will take care of everything so users don't have
to care. In this case the following output is produced.
[1/1] Regenerating build files
The Meson build system
@ -112,7 +135,8 @@ Once you have set up your build directory the first time, you don't ever need to
[1/2] Compiling c object demo.dir/main.c.o
[2/2] Linking target demo
Note how Meson noticed that the build definition has changed and reran itself automatically. The program is now ready to be run:
Note how Meson noticed that the build definition has changed and reran
itself automatically. The program is now ready to be run: