wiki:Documentation/HOWTO/BuildOnMinGW
Last modified 16 months ago Last modified on 11/12/15 18:18:03

Building on MinGW

This document describes how to build fldigi binaries for Windows systems (2000 or later). Fldigi developers prefer to use a toolchain that runs on Linux and compiles for Windows, and so this is the approach shown here.

For the sufficiently motivated and determined, it should be possible to build on Windows using the mingw and msys packages. An outline of steps needed to build on Windows can be found in an Icarus Project blog (note you will have to build a number of required packages for fldigi from source).

The cross-compiler used here is mingw-gcc and the build instructions have been tested with the version packaged (as mingw32) in recent releases of debian and Ubuntu. For openSUSE, the cross-compiler package is mingw32-cross-gcc-c++ in its most recent release.


  1. Build dependencies
    1. debian and Ubuntu
    2. openSUSE
  2. Libraries and Packages
    1. zlib
    2. libpng
    3. sndfile
    4. samplerate
    5. pthreads-win32
    6. PortAudio
    7. libtool
    8. hamlib
    9. xmlrpc-c
    10. FLTK
    11. libbfd
  3. Getting the source
  4. Compiling fldigi
    1. debian and Ubuntu
    2. openSUSE
    3. building with Hamlib (all platforms)
  5. Creating an installer
    1. debian and Ubuntu
    2. openSUSE


Build dependencies

debian and Ubuntu

The developers maintain their debian and Ubuntu win32 build tree as follows:

  • Source trees are kept in separate directories under /usr/local/src/win32
  • Binaries are installed in separate directories under /usr/local/win32
  • Symbolic links are made in /usr/local/win32/bin and /usr/local/win32/lib/pkgconfig
  • A PKG_CONFIG argument is passed to the configure scripts of libraries that require pkg-config

We assume that you will use the same or a similar arrangement. Define these variables or substitute their values whenever you encounter them in the build instructions:

AR=i586-mingw32msvc-ar
CC=i586-mingw32msvc-gcc
RANLIB=i586-mingw32msvc-ranlib
SRC=/usr/local/src/win32
PREFIX=/usr/local/win32
CROSSCFG="--build=i686-pc-linux-gnu --host=i586-mingw32msvc"
LINKCFG="--enable-static --disable-shared"
PKGCFG="PKG_CONFIG=$PREFIX/bin/i586-mingw32msvc-pkg-config"

Once you have installed the cross-compiler, prepare the installation tree:

mkdir -p $PREFIX/bin $PREFIX/lib/pkgconfig

Place the following script in $PREFIX/bin/i586-mingw32msvc-pkg-config (the name is important) and give it execute permissions. Remember to set $PREFIX in the script code to the same value that you will use for everything else.

#!/bin/sh

PREFIX=/usr/local/win32
export PKG_CONFIG_LIBDIR=$PREFIX/lib/pkgconfig
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH_MINGW32MSVC

exec pkg-config "$@"

openSUSE

The developers maintain the openSUSE win32 build tree as follows:

  • mingw32-configure and mingw32-make are used each time configure or make are referenced in the build instructions
  • Packages are obtained from http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_<Release_Version>/
    Add this repository to the system configuration (see "zypper lr -d").
  • Source trees can be kept in separate directories under /usr/local/src/win32 (or in the build account's homedir)
  • The PKG_CONFIG argument /usr/bin/i686-w64-mingw32-pkg-config is passed to the configure scripts of libraries that require use of pkg-config
  • The supplied pre-built mingw32-foo and mingw32-foo-devel libraries are used (the openSUSE MinGW repository is missing only hamlib, xmlrpc-c and FLTK)
  • Developer-built mingw32 libraries are installed in the /usr/i686-w64-mingw32/sys-root/mingw directory tree

It is assumed you will use the same or a similar arrangement (such as when building with the win64 build tree). All of the environment variables and cross-compiler arguments described in the debian and Ubuntu section above are defined for you in openSUSE by the use of mingw32-configure and mingw32-make,
with the exception of:

 LINKCFG="--enable-static --disable-shared"

You must supply LINKCFG when needed.

If you would like to examine the mingw32 variables and cross-compiler arguments for yourself, use:

 rpm --eval "%_mingw32_configure"
 rpm --eval "%_mingw32_make"

Ensure the following list of pre-built packages are installed from the MinGW repository:

 mingw32-zlib mingw32-zlib-devel mingw32-libpng mingw32-libpng-devel
 mingw32-libsndfile mingw32-libsndfile-devel mingw32-libsamplerate mingw32-libsamplerate-devel
 mingw32-pthreads mingw32-pthreads-devel mingw32-portaudio mingw32-portaudio-devel
 mingw32-libtool mingw32-libltdl mingw32-cross-nsis

Then skip ahead to building hamlib, xmlrpc-c and FLTK.


Libraries and Packages

zlib

  1. Obtain the latest release of zlib and extract it in $SRC.
  2. Build and install with:
    CC=$CC AR=$AR RANLIB=$RANLIB ./configure --prefix=$PREFIX/zlib --static
    make && make install
    
  3. Create libz.a symlink:
    ln -s $PREFIX/zlib/lib/libz.a $PREFIX/lib/libz.a
    
  4. Create zlib-devel includes directory:
    mkdir $PREFIX/zlib/include
    cp -p zconf.h $PREFIX/zlib/include
    cp -p zlib.h $PREFIX/zlib/include
    

libpng

  1. Obtain the latest release of libpng and extract it in $SRC (You will need to have already built and installed zlib).
  2. Build and install with:
    ./configure --prefix=$PREFIX/png $CROSSCFG $LINKCFG \
    CPPFLAGS=-I${PREFIX}/zlib/include LDFLAGS=-L${PREFIX}/zlib/lib $PKGCFG
    make && make install
    
  3. Create pkg-config symlinks:
    cd $PREFIX/lib/pkgconfig
    ln -s $PREFIX/png/lib/pkgconfig/libpng15.pc .
    ln -s ./libpng15.pc libpng.pc
    

sndfile

  1. Obtain the latest libsndfile release and extract it in $SRC.
  2. Build and install with:
    ./configure --prefix=$PREFIX/sndfile $CROSSCFG $LINKCFG $PKGCFG
    make && rm -f tests/*dll
    make install
    
  3. Create pkg-config symlinks:
    (cd $PREFIX/lib/pkgconfig; ln -s ../../sndfile/lib/pkgconfig/* .)
    

samplerate

  1. Obtain the latest libsamplerate release and extract it in $SRC.
  2. Build and install with:
    ./configure --prefix=$PREFIX/samplerate $CROSSCFG --disable-fftw --disable-sndfile $LINKCFG
    make && make install
    
  3. Create pkg-config symlinks:
    (cd $PREFIX/lib/pkgconfig; ln -s ../../samplerate/lib/pkgconfig/* .)
    

pthreads-win32

  1. Download the latest release of pthreads-win32 and extract it in $SRC.
  2. Build and install it with:
    make CROSS=i586-mingw32msvc- clean GC-inlined
    mkdir -p $PREFIX/ptw32/include $PREFIX/ptw32/lib
    cp pthread.h sched.h semaphore.h $PREFIX/ptw32/include
    cp libpthreadGC2.a pthreadGC2.dll $PREFIX/ptw32/lib
    

If building on debian 6.0.1 with MinGW 4.4.4, the cross-compiler seems to be missing pthread.h and the libpthread.a library, which will cause configure not to find pthreads for hamlib and fldigi itself. Build and install with:

make CROSS=i586-mingw32msvc- clean GC-inlined
cp -p pthread.h sched.h semaphore.h $PREFIX/include
cp -p libpthreadGC2.a pthreadGC2.dll $PREFIX/lib
ln -s $PREFIX/lib/libpthreadGC2.a $PREFIX/lib/libpthread.a

Install the newly built pthreads library where the cross-compiler will find them:

sudo ln -s $PREFIX/include/pthread.h /usr/i586-mingw32msvc/include/pthread.h
sudo ln -s $PREFIX/include/sched.h /usr/i586-mingw32msvc/include/sched.h
sudo ln -s $PREFIX/include/semaphore.h /usr/i586-mingw32msvc/include/semaphore.h
sudo ln -s $PREFIX/lib/libpthreadGC2.a /usr/i586-mingw32msvc/lib/libpthread.a
sudo ln -s /usr/i586-mingw32msvc/lib/libpthread.a /usr/i586-mingw32msvc/lib/libpthreadGC2.a

and create the package configuration data for the pthreads library installed in $PREFIX:

cat << _EOF > $PREFIX/lib/pkgconfig/pthreadGC2.pc
prefix=/usr/local/win32
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: pthreadGC2
Description: Library to interface with win32 threads model
Requires: 
Version: 2.8.0
Libs: -L${libdir} -lpthreadGC2
Cflags: -I${includedir}
_EOF
ln -s $PREFIX/lib/pkgconfig/pthreadGC2.pc $PREFIX/lib/pkgconfig/pthread.pc

PortAudio

  1. Obtain the latest PortAudio "v19" trunk snapshot and extract it in $SRC.
  2. If you wish to build PortAudio with support for multiple host APIs (WMME and DirectSound are recommended), you will need to apply mingw-portaudio.patch. This patch has been submitted upstream (2009-11-01) and may be included in the snapshot by the time you read this. For DirectSound support you will need to obtain the dsound.h header from the latest stable version of Wine and apply mingw-dsound.patch. Create $PREFIX/directx/include and copy your patched dsound.h there.
  3. Build and install with:
    ./configure --prefix=$PREFIX/portaudio $CROSSCFG $LINKCFG --with-winapi=wmme,directx \
    --with-dxdir=$PREFIX/directx
    make && make install
    
    Omit the --with-winapi and --with-dxdir switches if you only want WMME, in which case you don't need dsound.h or the aforementioned patches.

Including the DirectSound switches does not work with debian 6.0.1, Wine + libwine-dev 1.0.1-3.1 and pa_snapshot from April 2011, so omit the winapi and dxdir switches until further notice.

  1. Create pkg-config symlinks:
    (cd $PREFIX/lib/pkgconfig; ln -s ../../portaudio/lib/pkgconfig/* .)
    

libtool

  1. Obtain the latest release of libtool and extract it in $SRC.

If you care to build a library identical to the non-cross-compiler library, download both the orig.tar.gz and debian.tar.gz files from http://packages.debian.org/sid/libltdl-dev. Extract the orig.tar.gz file in $SRC then move into the $SRC/libtool-2.4 directory and issue:

tar xzvf libtool-2.4-2.debian.tar.gz
for i in `ls debian/patches/*.patch`; do
patch -p1 < $i
done
autoconf
  1. Build and install with:
    ./configure --prefix=$PREFIX/libtool $CROSSCFG $LINKCFG
    make && make install
    
  2. Create pkg-config and lib symlinks:
    ln -s $PREFIX/libtool/include/* $PREFIX/include
    ln -s $PREFIX/libtool/lib/* $PREFIX/lib
    

hamlib

  1. Obtain the latest release of hamlib and extract it in $SRC.
  2. Build and install with:
    ./configure --prefix=$PREFIX/hamlib $CROSSCFG $LINKCFG \
    --without-rigmatrix --without-rpc-backends --without-winradio --without-gnuradio --without-usrp \
    --without-cxx-binding --without-perl-binding --without-tcl-binding --without-python-binding
    make && make install
    

    a. If building on debian 6.0.1 with MinGW 4.4.4, you must build and install the libtool package (the cross-compiler seems to be missing libtool, which will cause configure to terminate). Prepare to build with:
    sudo ln -s $PREFIX/libtool/include/ltdl.h /usr/i586-mingw32msvc/include/ltdl.h
    sudo ln -s $PREFIX/libtool/include/libltdl /usr/i586-mingw32msvc/include/libltdl
    sudo ln -s $PREFIX/libtool/lib/libltdl.a /usr/i586-mingw32msvc/lib/libltdl.a
    

    Apply a one-line patch to lib/w32termios.h to prevent an incompatible redefinition of usleep():
    *** lib/win32termios.h.orig	2011-03-12 09:57:08.000000000 -0500
    --- lib/win32termios.h	2011-04-08 22:58:17.917938701 -0400
    ***************
    *** 139,145 ****
      void termios_interrupt_event_loop( int , int );
      void termios_setflags( int , int[] );
      struct termios_list *find_port( int );
    ! int usleep(unsigned int usec);
      int fcntl(int fd, int command, ...);
      const char *get_dos_port(const char *);
      void set_errno(int);
    --- 139,145 ----
      void termios_interrupt_event_loop( int , int );
      void termios_setflags( int , int[] );
      struct termios_list *find_port( int );
    ! //int usleep(unsigned int usec);
      int fcntl(int fd, int command, ...);
      const char *get_dos_port(const char *);
      void set_errno(int);
    

    Apply a three-line patch to include/config.h.in to prevent a redefinition of sleep() (due to pthread.h itself including config.h):
    *** include/config.h.in.orig	2011-04-08 22:54:32.634257118 -0400
    --- include/config.h.in	2011-04-11 15:54:44.912874571 -0400
    ***************
    *** 384,395 ****
    --- 384,398 ----
      #if defined(HAVE_SSLEEP) && !defined(HAVE_SLEEP)
      #ifdef HAVE_WINBASE_H
      #include <windows.h>
      #include <winbase.h>
      #endif
    + #if !defined(DEFINED_SLEEP)
      /* TODO: what about SleepEx? */
      static inline unsigned int sleep (unsigned int nb_sec) { Sleep(nb_sec*1000); return 0; }
    + #define DEFINED_SLEEP 1
    + #endif
      #endif
      
      #ifndef HAVE_GETTIMEOFDAY
      #ifdef HAVE_SYS_TIME_H
      #include <sys/time.h>
    

    And finally build and install with:
    ./configure --prefix=$PREFIX/hamlib $CROSSCFG $LINKCFG \
    --without-rigmatrix --without-rpc-backends --without-winradio --without-usrp \
    --without-cxx-binding --without-perl-binding --without-python-binding
    make && make install
    make install-pkgconfigDATA
    

    In the latest hamlib, there is no gnuradio and without-tcl-binding is the default. The build will terminate when it attempts to compile rigctrl.exe with shared libraries. This can be ignored since all of the libraries are complete at that point although the pkgconfig script hamlib.pc must be installed with a manually applied "make target".

    b. If building on openSUSE:
    mingw32-configure --disable-shared --enable-static --without-rigmatrix \
    --without-rpc-backends --without-winradio --without-usrp --without-cxx-binding \
    --without-perl-binding --without-python-binding
    

    Apply a one-line patch to include/config.h (getaddrinfo() exists in -lws2_32 and is defined in ws2tcpip.h):
    *** include/config.h.orig       2011-04-26 20:41:49.000000000 -0400
    --- include/config.h    2011-04-26 21:21:57.000000000 -0400
    ***************
    *** 61,66 ****
    --- 61,67 ----
      
      /* Define to 1 if you have the `getaddrinfo' function. */
      /* #undef HAVE_GETADDRINFO */
    + #define HAVE_GETADDRINFO 1
      
      /* Define to 1 if you have the `getopt' function. */
      #define HAVE_GETOPT 1
    

    And finally build and install with:
    mingw32-make && sudo mingw32-make install
    sudo mingw32-make install-pkgconfigDATA
    
    Then skip step 3.
  1. Create pkg-config symlinks:
    (cd $PREFIX/lib/pkgconfig; ln -s ../../hamlib/lib/pkgconfig/* .)
    

xmlrpc-c

  1. Obtain the latest stable snapshot of xmlrpc-c and extract it in $SRC.
  2. Apply mingw-xmlrpc-c.patch and run autoconf.

This is done by moving into the $SRC/xmlrpc-c-1.x.y directory and issuing:

patch -p1 < ../mingw-xmlrpc-c.patch
autoconf

Part of the patch may have already been incorporated into xmlrpc-c. Use the default "[n]" response to any query from patch.

  1. Build and install with:
    AR=$AR RANLIB=$RANLIB ./configure --prefix=$PREFIX/xmlrpc $CROSSCFG \
    --disable-wininet-client --disable-curl-client --disable-libwww-client
    make BUILDTOOL_CC=gcc BUILDTOOL_CCLD=gcc CFLAGS_PERSONAL=-U_UNIX
    make install
    
    1. If building on openSUSE:
      mingw32-configure --disable-wininet-client --disable-curl-client \
      --disable-libwww-client
      mingw32-make BUILDTOOL_CC=gcc BUILDTOOL_CCLD=gcc CFLAGS_PERSONAL=-U_UNIX
      sudo mingw32-make install
      
      Then skip step 4.
  1. Create xmlrpc-c-config symlink:
    ln -s ../xmlrpc/bin/xmlrpc-c-config $PREFIX/bin
    

FLTK

  1. Obtain the latest release of FLTK 1.1.x (1.1.9 or later) and extract it in $SRC.
  2. Apply mingw-fltk.patch to force MinGW compilation and avoid building the demos, and run autoconf.

This is done by moving into the $SRC/fltk-1.1.x directory and issuing

patch -p1 < ../mingw-fltk.patch
autoconf
  1. Build and install with:
    ./configure --prefix=$PREFIX/fltk $CROSSCFG $LINKCFG --enable-threads
    make && make install
    
    1. The latest MinGW uses gcc-4 which no longer supports -mno-cygwin.

The FLTK configure.in assumes both Cygwin and MinGW need -mno-cygwin. If FLTK is configured with enable-cygwin, the assumption is a native build environment instead. Since the latest mingw32-gcc is a full cross-compiler, the MinGW build environment is a native environment (in this case Windows instead of Cygwin).

The FLTK 1.1.x source includes a local copy of libpng 1.2.40 and is coded to use the libpng 1.2.x API. The latest MinGW provides libpng 1.5.2 whose API is incompatible with libpng 1.2.x. Until FLTK 1.1.x is updated to reflect the libpng 1.5.x API changes, use the older local copy of libpng.

If building on openSUSE:

mingw32-configure --disable-shared --enable-threads --enable-cygwin --enable-localpng
mingw32-make && sudo mingw32-make install

Then skip step 4.

  1. Create the fltk-config symlink:
    ln -s ../fltk/bin/fltk-config $PREFIX/bin
    

libbfd

For the most recent debian (6.0.1 or later) and openSUSE, this package is included in mingw32. Skip building this library.

  1. Download the latest release of the GNU binutils and extract it in $SRC. Change to the bfd subdirectory.
  2. Build and install with:
    ./configure --prefix=$PREFIX/bfd $CROSSCFG $LINKCFG --disable-nls
    make && make install
    

Getting the source

Get the fldigi source as described in the Debian build instructions.

Compiling fldigi

debian and Ubuntu

Refer to the Debian build instructions for some general information about running configure. For MinGW you will need some additional flags:

  • Normal "release" binaries:
    ./configure $CROSSCFG --disable-nls --with-ptw32=$PREFIX/ptw32 $PKGCFG \
    FLTK_CONFIG=$PREFIX/bin/fltk-config XMLRPC_C_CONFIG=$PREFIX/bin/xmlrpc-c-config
    
  • Debug binaries:
    ./configure $CROSSCFG --disable-nls --enable-debug --with-ptw32=$PREFIX/ptw32 \
    --with-bfd=$PREFIX/bfd $PKGCFG FLTK_CONFIG=$PREFIX/bin/fltk-config \
    XMLRPC_C_CONFIG=$PREFIX/bin/xmlrpc-c-config
    

openSUSE

Prepare the MinGW libraries for static linking (as root):

cd /usr/i686-w64-mingw32/sys-root/mingw/lib
ln -s ./libjpeg.dll.a libjpeg.a
ln -s ./libportaudio.dll.a libportaudio.a
ln -s ./libpng15.dll.a libpng15.a
ln -s ./libsndfile.dll.a libsndfile.a
ln -s ./libsamplerate.dll.a libsamplerate.a
ln -s ./libz.dll.a libz.a
ln -s ./libltdl.dll.a libltdl.a
  • Normal binaries (there is currently an issue with xmlrpc-c, so disable it for now):
    mingw32-configure --enable-static --disable-nls \
    GNU1FLAGS="-Wl,-Bstatic" --without-xmlrpc
    
  • Debug binaries:
    mingw32-configure --enable-static --enable-debug --disable-nls \
    GNU1FLAGS="-Wl,-Bstatic" --without-xmlrpc
    

building with Hamlib (all platforms)

If you have enabled hamlib, you should also run this additional command to relink fldigi.exe such that hamlib can discover its rig backend symbols at runtime:

make hamlib-static

Creating an installer

Instead of the traditional make install you will likely want to create an executable installer for the newly created binaries. The source tree contains a script that can do this. To use it you will need to install NSIS (packaged as nsis on Debian and Ubuntu) and run:

make nsisinst

debian and Ubuntu

The installer will attempt to find the DLL files that are required by fldigi. At the time of writing, these are pthreadGC2.dll and mingwm10.dll.

The former will be automatically found in the directory that you passed to configure's --with-ptw32 switch.

You must distribute the same pthreadGC2.dll used to cross-compile fldigi for MinGW (especially if you have built your own pthreads-win32).

The latter is known to be packaged in /usr/share/doc/mingw32-runtime/mingwm10.dll.gz on debian and Ubuntu systems and the installer will look for it there. If it is located elsewhere on your system, you must copy it to the source tree (e.g., src/) manually.

NSIS will complain if either DLL is missing but still create an installer. The installer will be created in the build directory (usually src/).

openSUSE

The pthreadGC2.dll file needed by fldigi can be found in /usr/i686-w64-mingw32/sys-root/mingw/bin.