Using MXE under Slackware Linux...

I have been cross compiling source code for Windows with MXE for four years now, using a Virtual Machine (VM) specifically setup for this purpose. When the need came to revisit cross compiling, specifically when I wanted to provide 32bit and 64bit binaries of the great AAC encoder fdkaac for Windows 10 I took the opportunity to rebuild my VM and make a clean MXE installation. And, Gentle Reader, this is in the middle of the world wide COVID-19 lockdown so I have decided to document the whole process as well so that others will hopefully profit from my example and will not have to fumble around with the dark magic of cross compiling, as I did in the early days! Let me know, using the email link at the base of this page, if I have been successful in this goal...

Install MXE, create fdkaac binaries...

The heading above makes it all look very easy but, Gentle Reader, we have a little bit of hard work to do before actually outputting the required binaries. The full path to our goal will actually require the following three steps:

  1. Create a suitable Virtual Machine: Since I am rebuilding this VM I will be using an April 2020 snapshot of Slackware -current which is creeping towards a 15.0 release at the moment. My old Ubuntu 18.04 VM will finally go to the bit bucket.
  2. Install a fully featured version of MXE: This involves not only installing the MXE scripts from git but also installing a base compiler set suitable for generating both 32bit and 64bit static Windows binaries.
  3. Cross compile and package the fdkaac binaries: Not only actually doing the cross compile but also creating a decent archive and then comprehensively testing both binaries under my Windows 10 VM. These packages are being released to the public and I do not want to look like an idiot!

And so, courtesy of the global lockdown, the reasonably complex documentation now commences. Remember that that are really only three steps required although I confess that some of these steps are a little complex and time consuming. On my own machine, while writing it all up as I went, the whole process took an entire morning to accomplish although perhaps I am becoming slower as well as older...

Create a suitable Virtual Machine...

When I started seriously cross compiling with MXE I realised from the outset that this would be better done in a Virtual Machine and thus isolated from my day to day computing needs. For some time I used Ubuntu 18.04 as a VM in part because it was easy to setup and run and in part because I still had strong connections with the Ubuntu world. However with this rebuild and write up I have switched to a snapshot of the development version of Slackware taken early in April 2020. It is a solid investment of time and effort to get this set up correctly but a well worthwhile investment. Any Linux distro could be used and at least some of the special steps I have taken with this VM should translate well to your own choice of distro and VM:

I had to restrain myself from doing my usually obsessive compulsive setup of Slackware as this VM is a highly focussed one with a single purpose: to easily cross compile applications for use in the world of Windows. And I can give you a sneak preview, Gentle Reader, in telling you that in this goal my Slackware VM performed well above expectations!

Install a fully featured version of MXE...

After the work of setting up a VM dedicated to MXE the setup of MXE itself was pretty light work! The scripts live in a git repository and can be installed to $HOMEas follows:

cd $HOME
git clone https://github.com/mxe/mxe.git

I have never bothered with a system installation of MXE, although this can be done, as a single user VM has always been enough. Now a basic set of tools can be installed and we will be installing the basics for two targets:

  1. i686-w64-mingw32.static: This target will allow for the compilation of 32bit, static binaries. By static I mean that no external dlls will be built and the binary itself should be completely self contained.
  2. x86_64-w64-mingw32.static: This target will allow for the compilation of 64bit, static binaries. By static I mean that no external dlls will be built and the binary itself should be completely self contained.

With this hopefully understood a basic set of tools for both targets can be installed. Note that I use MXE_PLUGIN_DIRS=plugins/gcc9 which will allow for the use of gcc 9.3.0 rather than the older, default offering:

cd $HOME/mxe
make cc MXE_TARGETS='i686-w64-mingw32.static x86_64-w64-mingw32.static' MXE_PLUGIN_DIRS=plugins/gcc9

When the long installation process is done the path to your MXE executables will need to be prepended to your $PATH. I add the following to ~/.bashrc although there are a few other options here:

# Prepend MXE to the system $PATH:
export PATH="$HOME/mxe/usr/bin:$PATH"

Now either source this file or perhaps just reboot, but before doing this you should add the non-default gcc 9 choice to MXE's settings.mk file. This gcc 9 option can be painlessly added as follows:

echo 'override MXE_PLUGIN_DIRS += plugins/gcc9' >> $HOME/mxe/settings.mk

There are several options in this file worth experimenting with but, Gentle Reader, I will leave that to you because now with setup complete we can prepare to actually start cross compiling.

Cross compile and package the fdkaac binaries...

So finally to the actual process of cross compiling the amazing AAC encoder fdkaac for use on Windows 10! fdkaac requires both libiconv and fdk-aac for a successful compile so another trip to MXE itself to prepare these libraries. Note that if you have not added the gcc 9 option to your MXE configuration file you will also need to append MXE_PLUGIN_DIRS=plugins/gcc9 to the this command:

cd $HOME/mxe
make fdk-aac libiconv MXE_TARGETS='i686-w64-mingw32.static x86_64-w64-mingw32.static'

Again there are two targets being used here: one for 32bit Windows (i686) and one for 64bit Windows (x86_64). The following commands will now download, compile and finally package the 32bit fdkaac. Note that every line with the '#' mark at the begining of the line is a hopefully helpful note:

#--------------------------#	
# Create the 32bit fdkaac  #
#--------------------------#	
cd $HOME/Desktop
wget --content-disposition https://github.com/nu774/fdkaac/archive/1.0.0.tar.gz
tar xvf fdkaac-1.0.0.tar.gz && cd fdkaac-1.0.0 
autoreconf -fiv
./configure CFLAGS="-O3 -march=i686 -mtune=i686" \
            --host=i686-w64-mingw32.static \
            --with-libiconv-prefix=$HOME/mxe/usr/i686-w64-mingw32.static
make -j 8
strip --strip-unneeded fdkaac.exe

cd $HOME/Desktop
zip -j fdkaac-1.0.0-win32-ads.zip fdkaac-1.0.0/{fdkaac.exe,README,COPYING}
rm -rfv $HOME/Desktop/{fdkaac-1.0.0.tar.gz,fdkaac-1.0.0}

Now how cool is that! The resulting file will be on your desktop as fdkaac-1.0.0-win32-ads.zip ready for installation to either a 32bit or a 64bit Windows 10 installation. But perhaps you are after a 64bit copy of fdkaac, which will be suitable for a 64bit Windows 10 installation only? Note the small differences in the syntax below where the 64bit fdkaac is now built:

#--------------------------#	
# Create the 64bit fdkaac  #
#--------------------------#	
cd $HOME/Desktop
wget --content-disposition https://github.com/nu774/fdkaac/archive/1.0.0.tar.gz
tar xvf fdkaac-1.0.0.tar.gz && cd fdkaac-1.0.0 
autoreconf -fiv
./configure CFLAGS="-O3 -fPIC" \
            --host=x86_64-w64-mingw32.static \
            --with-libiconv-prefix=$HOME/mxe/usr/x86_64-w64-mingw32.static
make -j 8
strip --strip-unneeded fdkaac.exe

cd $HOME/Desktop
zip -j fdkaac-1.0.0-win64-ads.zip fdkaac-1.0.0/{fdkaac.exe,README,COPYING}
rm -rfv $HOME/Desktop/{fdkaac-1.0.0.tar.gz,fdkaac-1.0.0}

And thus it is all done! I have tested the resulting binaries on my 64bit Windows VM and they both work perfectly. For those readers of this page who are perhaps simply after binaries to use with Foobar2000 and friends and could not be bothered building their own I have placed the two files here... It is my hope however that at least some readers of this page have seen that the dark magic of cross compiling does not have to really be so dark nor indeed so difficult to accomplish. Perhaps some will even be guided a little by the steps I have taken and carefully documented above as they move onto even bigger cross compiling projects?