Marc Wäckerlin
Für eine libertäre Schweiz

Cross Compile OpenSSL for Windows on Linux

May 7, 2014

This article explains how to configure and build the OpenSSL library on a Ubuntu Linux to run on 32bit or 64bit Windows. After you have set up your cross compile environment as described in my previous article, you are now ready to start compiling for example OpenSSL, which is a requirement for Qt5 that will be described in my next article.

To cross compile OpenSSL for Windows on an Ubuntu Linux using MinGW, you need to perform the following steps:

  1. Find and download the latest sources from https://www.openssl.org/source
  2. Unpack the file and change to that directory
  3. Chose your OpenSSL target name, which is different from the MinGW target name and is mingw for 32bit i686-w64-mingw32 and mingw64 for 64bit x86_64-w64-mingw32
  4. To configure for 32bit Windows, call ./Configure mingw shared --cross-compile-prefix=i686-w64-mingw32-
    Note: Without the addition shared, the required runtime DLLs are not built
  5. Run make and optionally make install (i.e. if you have added a --prefix=/install/path option to Configure)
  6. Note: The runtime DLLs are not installed to the installation path, you find them in your local path, try ls *.dll after your build
  7. There is a bug in OpenSSL that must be fixed manually: In the include file openssl/x509v3.h add just after line #define HEADER_X509V3_H on the top the following lines:
    #ifdef X509_NAME
    #undef X509_NAME
    #endif

It is possible to do everything fully automated, e.g. in a Jenkins build script:

MINGW=${MINGW:-x86_64-w64-mingw32}
WORKSPACE=${WORKSPACE:-$(pwd)}
BUILD_NUMBER=${BUILD_NUMBER:-0}
ARCH=${ARCH:-${MINGW%%-*}}

cd ${WORKSPACE}
source=https://www.openssl.org/source
file=$(wget -qO- $source | sed -n 's,.*<a *href="\(openssl-[0-9][^"]*\.tar\.gz\)".*,\1,p'  | head -1)
path=${file%.tar.gz}
wget -qO$file $source/$file
tar xf $file
cd $path
version=${path#openssl-}

case ${MINGW} in
    (*i?86*)
        TARGET=mingw
        ;;
    (*x86_64*)
        TARGET=mingw64
        ;;
    (*) false;;
esac

./Configure ${TARGET} shared --cross-compile-prefix=${MINGW}- --prefix=${WORKSPACE}/usr

make
make install
cp *.dll ${WORKSPACE}/usr/lib/

cd ${WORKSPACE}
zip -r ${path}~windows.${BUILD_NUMBER}_${ARCH}.zip usr

Build MinGW Targets in Docker

I support a maintained docker image that contains an Ubuntu based build environment and build scripts for several libraries and programs. This is i.e. QT and all it’s dependencies, and my own projects with all their dependencies:

List all available build scripts:

docker run -it –rm mwaeckerlin/mingw -c ‘ls /build-*.sh’

Show options for building OpenSSL:

docker run -it --rm mwaeckerlin/mingw /build-openssl.sh -h

Compile latest OpenSSL in the current working directory:

docker run -it --rm -v $(pwd):/workdir -u $(id -u) mwaeckerlin/mingw /build-openssl.sh -d

Build ICU version 57-1 in the current working directory:

docker run -it --rm -v $(pwd):/workdir -u $(id -u) mwaeckerlin/mingw /build-icu.sh -d -v 57-1

Just Download Built Archives

You can download already built images for 32bit and 64bit on my repository: https://dev.marc.waeckerlin.org/repository/windows/

comments title

[…] hacks have gone, cross-compilation is very simple. This is my first example of a 3rd-party library. Next article will talk about cross compiling […]

What’s the purpose of editing those two lines?

You mean the «undef»? This macro is defined in more than one files. At the second definition, the compiler complains. So I first undefine it, then it can be redefined later in the file.

Editing the two lines is no more necessary.