Cross compile Windows Applications
Posted on 2012-04-09
There is a nice repository on build.opensuse.org which provides some useful packages to cross compile from linux, and I’m going to describe a simple setup using cmake and Qt:
First install openSUSE 12.1 into a virtual machine (unless you want to do it on a real machine).
Then add the extra repositories and install the needed packages (as root):
1 2 3 4 |
zypper ar http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_12.1/windows:mingw:win32.repo
zypper install mingw32-cross-gcc mingw32-cross-gcc-c++ mingw32-libjpeg-devel mingw32-libpng-devel mingw32-libqt4 mingw32-libqt4-devel mingw32-libtiff-devel mingw32-zlib-devel
zypper ar http://download.opensuse.org/repositories/devel:/tools:/building/openSUSE_12.1/devel:tools:building.repo
zypper install cmake-2.8.7 binutils git
|
- The second repository is needed for an updated cmake-2.8.7 which includes http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6ddb1e5b9a3eff941ad12d29609839871fe518ed
- binutils includes “strings” which is needed in one of the scripts below.
Then login with your normal user, and prepare the cmake toolchain file:
~/toolchain-windows.cmake:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32/sys-root/mingw)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
SET(QT_QMAKE_EXECUTABLE /usr/i686-w64-mingw32/bin/qmake CACHE INTERNAL "" FORCE)
SET(QT_MOC_EXECUTABLE /usr/i686-w64-mingw32/bin/moc CACHE INTERNAL "" FORCE)
SET(QT_RCC_EXECUTABLE /usr/i686-w64-mingw32/bin/rcc CACHE INTERNAL "" FORCE)
SET(QT_UIC_EXECUTABLE /usr/i686-w64-mingw32/bin/uic CACHE INTERNAL "" FORCE)
|
Now checkout your favorite project which uses cmake+qt and build it with cmake in a subdirectory:
1 2 3 4 5 6 |
git clone -b stefan-wip git://stbuehler.de/qcross.git
cd qcross
mkdir winbuild
cd winbuild
cmake -DCMAKE_TOOLCHAIN_FILE=~/toolchain-windows.cmake ..
make
|
The resulting binaries will need some DLLs; with the two scripts below (chmod +x) they should be easy to install into a directory:
1 |
$ installapp ~/qcross/winbuild ~/app/qcross
|
Now all the needed files should be in ~/app/qcross.
bin/installexe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#!/bin/bash
if [ -z "$1" -o -z "$2" ]; then
echo "Syntax: $0 <source> <targetdir> [optionall dll dirs]" 1>&2
exit 1
fi
SOURCE=$1
shift
TARGET=$1
shift
DLLSOURCE=/usr/i686-w64-mingw32/sys-root/mingw/
if [ ! -f "$SOURCE" ]; then
echo "source '$SOURCE' doesn't exist"
fi
mkdir -p "$TARGET"
walk() {
b="$(basename $1)"
d="$TARGET/$b"
if [ -f "$d" -a ! "$d" -ot "$1" ]; then
echo "Skipping '$b' [current version already present]"
else
echo "Installing '$b'"
cp -a "$1" "$TARGET/"
# Hack to find dependencies
strings "$1" | grep '\.dll' | while read dll
do
DLL=`find "$DLLSOURCE" "$@" -name "$dll" -print -quit`
if [ ! -z "$DLL" -a -f "$DLL" ]; then
walk "$DLL"
fi
done
fi
}
walk "$SOURCE"
exit 0
|
bin/installapp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/bin/bash
if [ -z "$1" -o -z "$2" ]; then
echo "Syntax: $0 <sourcedir> <targetdir>" 1>&2
exit 1
fi
SOURCE=$1
shift
TARGET=$1
shift
for exe in $(find "$SOURCE" -name '*.exe' | grep -v CMakeFiles); do
echo "Installing executable $exe -> $TARGET"
installexe "$exe" "$TARGET" "$TARGET" "$@"
done
|