wiki:Documentation/HOWTO/BuildWithMXE
Last modified 8 months ago Last modified on 05/21/16 16:32:04

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.


  1. Installing and configuring MXE
  2. Building the hamlib library
    1. Building hamlib from a remote repository
    2. Building hamlib from local source
  3. 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

make update-checksum-hamlib

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:

make hamlib

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.