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.
135 lines
4.6 KiB
135 lines
4.6 KiB
5 years ago
|
---
|
||
|
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`.
|