Skip to content

Additional compilation instructions

Nathan S edited this page Jun 30, 2020 · 2 revisions

Instructions written by noahc3

This guide demonstrates how to cross-compile a Borealis project from Linux to Windows. The end result will be a native Windows executable that can be run without msys2 or Linux. This is helpful for developers wanting to test their Borealis projects on Windows without msys2. You'll be able to build the project using a WSL instance and then run the project natively in Windows.

Before starting you should have a working Meson build file for your project. For demonstration purposes we will use the example project included in the Borealis repo. We will be building the project using an Ubuntu 18.04 WSL1 instance, but the steps should be transferable to any distro and platform of your choice.

Building a native Linux executable

First make sure your environment can build a native Linux executable using meson and ninja. On Ubuntu, this means installing the following packages:

build-essential
meson
pkg-config
libglfw3-dev
libglm-dev

If you're on Ubuntu 19.10 or higher, this will just work. On Ubuntu 18.04 and lower, the version of the libglfw3-dev package is 3.2.1, but Borealis needs at least 3.3. We'll have to manually install the newer version of this package:

mkdir glfw3packages && cd glfw3packages
wget https://launchpad.net/ubuntu/+archive/primary/+files/libglfw3_3.3.2-1_amd64.deb
wget https://launchpad.net/ubuntu/+archive/primary/+files/libglfw3-dev_3.3.2-1_amd64.deb
sudo dpkg -i *
cd .. && rm -r glfw3packages

If you're using other libraries in your project, such as any of the Switch portlibs, you'll need to install their equivalent Linux package in your environment.

We should now be able to build a native Linux binary:

meson build && ninja -C build && ls build

The Meson build system
Version: 0.45.1
Build type: native build
Project name: borealis_example
[ ... ]
ninja: Entering directory `build'
[ ... ]
[42/42] Linking target borealis_example.
borealis_example      build.ninja            library     meson-private
borealis_example@exe  compile_commands.json  meson-logs

If you have a desktop environment supporting OpenGL 4.4, at this point the ./build/borealis_example executable can be run on Linux. Now we'll setup cross-compiling to Windows.

Cross-compiling a native Windows executable

This guide will cover cross-compiling for 64-bit Windows (x86_64/AMD64).

We'll be using Meson's built-in cross-building functionality along with mingw to compile your Borealis project for Windows. We need to install the following packages:

gcc-mingw-w64
g++-mingw-w64
pkg-config-mingw-w64-x86-64
glm-mingw-w64
glfw3-mingw-w64

Unfortunately Ubuntu doesn't provide official packages for glm-mingw-w64 or glfw3-mingw-w64. Thankfully these just consist of header files and some Windows DLLs, so we can install them manually from the msys2 repositories:

sudo su
cd /usr/x86_64-w64-mingw32/
mkdir mingwpackages && cd mingwpackages
wget http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-glm-0.9.9.8-1-any.pkg.tar.xz
wget http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-glfw-3.3.2-1-any.pkg.tar.xz
tar -xvf mingw-w64-x86_64-glfw-3.3.2-1-any.pkg.tar.xz
tar -xvf mingw-w64-x86_64-glm-0.9.9.8-1-any.pkg.tar.xz
cp -r ./mingw64/* ../
cd .. && rm -r mingwpackages
rm -r share
exit

If you're using other libraries in your project, such as any of the Switch portlibs, you'll need to install their equivalent mingw package in your environment. If you can't find them on the official Ubuntu repos, you can usually grab them from the msys2 repos (search https://packages.msys2.org/) and manually install them like we did above.

Almost done installing packages; you'll need to install wine-stable so Meson can determine various properties such as int size for the target platform automatically. You can skip the need of wine by specifying these properties manually in the cross-file we make next but that is outside the scope of this guide.

Now we need to give Meson some information about our target platform. Create a file named windows.cross next to your projects meson.build file and paste in the following:

[binaries]
name = 'windows'
c = '/usr/bin/x86_64-w64-mingw32-gcc'
cpp = '/usr/bin/x86_64-w64-mingw32-g++-posix'
ar = '/usr/x86_64-w64-mingw32/bin/ar'
strip = '/usr/x86_64-w64-mingw32/bin/strip'
exe_wrapper = 'wine'
pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config'

[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

[properties]
sys_root = '/usr/x86_64-w64-mingw32/'

The properties under the [binaries] section tell Meson which compilers and tools to use for cross-building. The properties under host_machine tells Meson some basic information about the target CPU architecture. Finally, sys_root under the properties section tells Meson where to search for libraries for the target platform. You'll notice this is the same directory we went to earlier to manually install the mingw libglfw3 and libglm packages.

Notice above that the g++ compiler we specify is specifically the POSIX version. This is because mingw g++ will compile with the win32 threading API by default, but Borealis uses POSIX threads.

The last configuration step is to tell Meson to statically link libraries for the Windows executable. While this step isn't technically necessary, it saves us the trouble of searching for a number of mingw DLL files to include next to the Windows executable. We enable static linking by editing the meson.build file for your project and including a link_args property with the ['-static'] argument inside the borealis_example executable definition. Example:

borealis_example = executable(
    'borealis_example',
    [ example_files, borealis_files ],
    dependencies : borealis_dependencies,
    link_args: ['-static'],
    install: true,
    include_directories: [ borealis_include, include_directories('example')],
    cpp_args: [ '-g', '-O2', '-DBOREALIS_RESOURCES="./resources/"' ]
)

You can see link_args defined under dependencies.

Now remove your old Linux build of your project and have Meson setup your project again with the cross-file we made:

rm -r build
meson build --cross-file windows.cross

When you run the meson command for the first time, you may see some errors from Wine if your Linux environment doesn't have a display supporting OpenGL. You can safely ignore these errors.

If everything works out the Meson output should include the following:

Native C++ compiler: c++ (gcc 7.5.0 "c++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0")
Cross C++ compiler: /usr/bin/x86_64-w64-mingw32-g++ (gcc 7.3.0)
Host machine cpu family: x86_64
Host machine cpu: x86_64
Target machine cpu family: x86_64
Target machine cpu: x86_64
Build machine cpu family: x86_64
Build machine cpu: x86_64
Cross dependency glfw3 found: YES 3.3.2
Cross dependency glm found: YES 0.9.9
Build targets in project: 1
Found ninja-1.8.2 at /usr/bin/ninja

Finally, build your project with ninja:

ninja -C build

ninja: Entering directory `build'
[ ... ]
Linking target borealis_example.exe.

Success! There should now be a borealis_example.exe file in the build directory which you can run on Windows.

The last step is to grab the 64bit glfw3 Windows binary from their website (https://www.glfw.org/download.html) and throw the glfw3.dll file next to your executable. You'll also need to copy the resources folder next to your executable so it can find the resources.

If everything worked out you should now be able to run your project on Windows!