Building with MXE
This document describes a way to use MXE under Linux to cross-compile statically linked fldigi binaries for Windows systems. Some may find this approach to be easier than using MinGW directly.
- Installing and configuring MXE
- Building the hamlib library
- Building fldigi and other applications
Installing and configuring MXE
- Select a directory to hold the root of the MXE distribution tree. In this document, the name of this directory is assumed to be the value of the environment variable $TOP. (/opt or your home directory are common choices for this, but any place on your filesystem where you have write privileges will do.)
- cd to that directory and clone the MXE distribution tree there:
cd $TOP git clone https://github.com/mxe/mxe.git
- cd to the root of the MXE distribution tree and make some MXE packages needed for fldigi development. Downloading and building these packages may take a while.
cd $TOP/mxe make gcc make boost make gettext make gdb make glib make gnutls make portaudio make libsamplerate make libsndfile make pthreads make jpeg make libpng make fltk
If you encounter any problems so far, the MXE tutorial can help.
- Define these environment variables, which will be used by some MXE utilities and build scripts:
export PREFIX="$TOP/mxe/usr" export LINKCFG="--enable-static --disable-shared" ## This caused the buildmxe.sh script to fail...MXE recommends NOT using --build in this type of compile #export CROSSCFG="--build=i686-w64-mingw32.static --host=i686-w64-mingw32.static" # SO I used this for my CROSSCFG environment and the compilation is successful. export CROSSCFG="--host=i686-w64-mingw32.static" export PKGCFG="PKG_CONFIG=$PREFIX/bin/i686-w64-mingw32.static-pkg-config" export PATH=$TOP/mxe/usr/bin/:$PATH
Building the hamlib library
The hamlib library should be built as an MXE package, so it will be available to be statically linked to any applications that may need it.
- Inform MXE that a package named hamlib will exist, by inserting a table row as shown here in $TOP/mxe/index.html.
<tr> <td class="package">hamlib</td> <td class="website"><a href="http://n0nb.users.sourceforge.net/">Hamlib</a></td> </tr>
It's nice to insert the row so that alphabetical order among the package names is maintained. At this time, that would mean putting hamlib's row between those for guile and harfbuzz. The text value of the "package" cell is important; the website URL there is for informational purposes.
- There needs to be a file named hamlib.mk in the $TOP/mxe/src directory to inform MXE about how to download and compile the hamlib package. Here is an example to start with. Edit it according to what you want to do; the definitions of $(PKG)_VERSION, $(PKG)_CHECKSUM, and $(PKG)_FILE are the only things you are likely to need to change.
# This file is part of MXE. # See index.html for further information. PKG := hamlib $(PKG)_IGNORE := $(PKG)_VERSION := 3.1~git $(PKG)_CHECKSUM := 1ead6cf82c5eaca2706aa456e3d10e50f8e790d46bd12969c59bf3a9e87624bb $(PKG)_SUBDIR := hamlib-$($(PKG)_VERSION) $(PKG)_FILE := hamlib-$($(PKG)_VERSION)-2a51974-20151111.tar.gz $(PKG)_URL := http://n0nb.users.sourceforge.net/$($(PKG)_FILE) $(PKG)_DEPS := gcc libxml2 libtool libltdl define $(PKG)_UPDATE echo 'TODO: write update script for $(PKG).' >&2; echo $($(PKG)_VERSION) endef define $(PKG)_BUILD cd '$(1)' && ./configure \ $(MXE_CONFIGURE_OPTS) \ --disable-winradio \ --without-cxx-binding \ --enable-static \ --disable-shared $(MAKE) -C '$(1)' -j '$(JOBS)' install bin_PROGRAMS= sbin_PROGRAMS= noinst_PROGRAMS= endef
Building hamlib from a remote repository
Choose an online source for the hamlib source tarball that you want to use; for example, http://n0nb.users.sourceforge.net/hamlib-3.1~git-2a51974-20151111.tar.gz. Edit hamlib.mk so that URL is the value of the $(PKG)_URL variable. The name of the root directory of the untarred source tree must be the value of the $(PKG)_SUBDIR variable (typically the concatenation of the package name and the version; in this case, hamlib-3.1~git).
The value of the $(PKG)_CHECKSUM variable must be the SHA256 hash of the tarball file. If you don't know what it is, you can get MXE to compute it and update the hamlib.mk file for you by invoking
from the directory $TOP/mxe. Or, if you already have a local copy of the tarball, you can use openssl SHA256 to compute it, and edit the hash value into the hamlib.mk file yourself.
With the variables in hamlib.mk defined appropriately, get MXE to download and build the hamlib library by invoking, from directory $TOP/mxe:
If there are errors, the location of the log file containing the text output from the compilation process will be displayed.
Building hamlib from local source
It may be that you want to do development of hamlib code locally on your own machine instead of downloading a tarball from a remote site, but MXE deals with compressed tar archives and their SHA256 checksums and not source code trees directly. To build the hamlib library from your local source tree whose root directory is named, say, hamlib.3.2-new, you can do the following:
- Create a tarball hamlib.3.2-new.tar.gz of your hamlib source tree
- Make sure the hamlib.mk definitions reflect the name of that source tree root and the tarball, e.g.
$(PKG)_VERSION := 3.2-new $(PKG)_FILE := hamlib-$($(PKG)_VERSION).tar.gz
- Compute the SHA256 hash of the tarball and also edit that as the definition of $(PKG)_CHECKSUM in hamlib.mk
- Copy the tarball to the mxe package download directory $TOP/mxe/package
- Delete the 0-length hamlib sentinel file, $TOP/mxe/usr/i686*/installed/hamlib, if it exists
- Build the hamlib library by invoking make hamlib from the top level MXE directory $TOP/mxe.
(Deleting the 0-length sentinel file is essential to force a recompilation, if hamlib has already previously been built by MXE. Also note that the value of $(PKG)_URL in hamlib.mk is irrelevant in this context since we are directly copying the tarball, not downloading it.)
A shell script to automate this process can look something like this:
#!/bin/bash # Crosscompile your local source package as a library under mxe. # Invoke this script from the directory containing the root of # your source tree, $PKG LIBNAME=hamlib VER=3.2-new PKG=$LIBNAME-$VER TARBALL=$PKG.tar.gz MXE=$TOP/mxe MKFILE=$MXE/src/$LIBNAME.mk # tar the source tree tar czf $TARBALL $PKG # copy it to mxe/pkg cp $TARBALL $MXE/pkg # compute hash of tarball. Yes this could all be done with make update-checksum-hamlib HASH=`openssl sha256 $MXE/pkg/$TARBALL | sed 's/^[^ ]* //'` # edit checksum in $MKFILE to be the new hash TMPFILE=`mktemp` cat $MKFILE \ | sed 's/^$(PKG)_CHECKSUM := [0-9a-f]*/$(PKG)_CHECKSUM := '$HASH'/' \ > $TMPFILE cat $TMPFILE > $MKFILE rm $TMPFILE # delete any installed/$LIBNAME sentinel file, to force recompile rm -f $MXE/usr/i686-w64-mingw32.static/installed/$LIBNAME # do the crosscompile cd $MXE make $LIBNAME
Building fldigi and other applications
Building self-installing statically linked setup.exe's of fldigi and other possibly hamlib-dependent applications using MXE now is pretty easy, with the help of NSIS (packaged as nsis on Debian-based systems). The current fldigi distribution source tarball includes a scripts/buildmxe.sh script that does that. Invoke this script from the root directory of your fldigi source tree, and the self-installing setup.exe will be placed in that same directory.
#!/bin/bash #======================================================================= # make the mxe-mingw32 executable with statically linked hamlib ./configure \ $PKGCFG \ $CROSSCFG \ --without-asciidoc \ --with-ptw32=$PREFIX/i686-w64-mingw32.static \ --with-libiconv-prefix=$PREFIX/iconv \ --enable-static \ --with-libintl-prefix=$PREFIX/gettext \ PTW32_LIBS="-lpthread -lpcreposix -lpcre -lregex -lhamlib -lws2_32" \ FLTK_CONFIG=$PREFIX/bin/i686-w64-mingw32.static-fltk-config \ make $PREFIX/bin/i686-w64-mingw32.static-strip src/fldigi.exe $PREFIX/bin/i686-w64-mingw32.static-strip src/flarq.exe make nsisinst mv src/*setup.exe . ls -l *setup.exe
Other packages may provide similar scripts, or this one can be modified to suit.