The Meson Build System
http://mesonbuild.com/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
4.6 KiB
134 lines
4.6 KiB
--- |
|
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. |
|
|
|
## Installing system and GCC |
|
|
|
First you need to do a fresh operating system install. You can use |
|
spare hardware, VirtualBox, cloud or whatever you want. Note that the |
|
distro you install must be *at least as old* as the oldest release you |
|
wish to support. Debian stable is usually a good choice, though |
|
immediately after its release you might want to use Debian oldstable |
|
or the previous Ubuntu LTS. The oldest supported version of CentOS is |
|
also a good choice. |
|
|
|
Once you have installed the system, you need to install |
|
build-dependencies for GCC. In Debian-based distros this can be done |
|
with the following commands: |
|
|
|
```console |
|
$ apt-get build-dep g++ |
|
$ apt-get install pkg-config libgmp-dev libmpfr-dev libmpc-dev |
|
``` |
|
|
|
Then create a `src` subdirectory in your home directory. Copy-paste |
|
the following into `install_gcc.sh` and execute it. |
|
|
|
```bash |
|
#!/bin/sh |
|
|
|
wget ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-4.9.2/gcc-4.9.2.tar.bz2 |
|
tar xf gcc-4.9.2.tar.bz2 |
|
|
|
mkdir objdir |
|
cd objdir |
|
../gcc-4.9.2/configure --disable-bootstrap --prefix=${HOME}/devroot \ |
|
--disable-multilib --enable-languages=c,c++ |
|
make -j 4 |
|
make install-strip |
|
ln -s gcc ${HOME}/devroot/bin/cc |
|
``` |
|
|
|
Then finally add the following lines to your `.bashrc`. |
|
|
|
```console |
|
$ export LD_LIBRARY_PATH=${HOME}/devroot/lib |
|
$ export PATH=${HOME}/devroot/bin:$PATH |
|
$ export PKG_CONFIG_PATH=${HOME}/devroot/lib/pkgconfig |
|
``` |
|
|
|
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. |
|
|
|
## 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. |
|
|
|
## 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: |
|
|
|
```console |
|
$ LDFLAGS=-static-libstdc++ meson --prefix=/tmp/myapp <other args> |
|
``` |
|
|
|
The aim is to put the executable in `/tmp/myapp/bin` and shared |
|
libraries to `/tmp/myapp/lib`. The next thing you need is the |
|
embedder. It takes your dependencies (in this case only |
|
`libSDL2-2.0.so.0`) and copies them in the lib directory. Depending on |
|
your use case you can either copy the files by hand or write a script |
|
that parses the output of `ldd binary_file`. Be sure not to copy |
|
system libraries (`libc`, `libpthread`, `libm` etc). For an example, |
|
see the [sample |
|
project](https://github.com/jpakkane/meson/tree/master/manual%20tests/4%20standalone%20binaries). |
|
|
|
Make the script run during install with this: |
|
|
|
```meson |
|
meson.add_install_script('linux_bundler.sh') |
|
``` |
|
|
|
## Final steps |
|
|
|
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 |
|
|
|
cd "${0%/*}" |
|
export LD_LIBRARY_PATH="$(pwd)/lib" |
|
bin/myapp |
|
``` |
|
|
|
Install it with this Meson snippet: |
|
|
|
```meson |
|
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`.
|
|
|