Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 2

Qt-interest Archive, March 2006
Linux-MinGW32 cross compiler for Qt4


Message 1 in thread

I spent a while last weekend putting together a i686-pc-linux x i686-mingw32
cross-compiler so that I can make Windows builds of my Qt4 app without Wine
or a Windows machine. Getting this to work was non-trivial, so I thought
I'd share what I did:

1. Download the source for binutils, gcc-core, gcc-g++, mingw-runtime,
and w32api from http://www.mingw.org.

(The ones I used were:

   binutils-2.16.91-20060119-1-src.tar.gz
   gcc-core-3.4.5-20060117-1-src.tar.gz
   gcc-g++-3.4.5-20060117-1-src.tar.gz
   mingw-runtime-3.9-src.tar.gz
   w32api-3.6-src.tar.gz

but I imagine that (some) other versions will also work.)

2. Put the source archives in the same directory and run this script.
Adjust BASE, TARGET, and PREFIX as appropriate. BASE is the directory
holding the source archives. TARGET is the name of the target platform
for the cross-compiler, and PREFIX is the directory to which you want
the whole mess installed. At this point, you might want to go get some
lunch, since your machine is going to be compiling for a while.

-------- begin script --------

#! /bin/bash -e

BASE=$PWD
TARGET=i686-mingw32
PREFIX=$HOME/projects/board/build/mingw

# find the archives
cd $BASE
BINUTILS=`ls binutils-*-src.tar.gz`
GCC_CORE=`ls gcc-core-*-src.tar.gz`
GCC_GXX=`ls gcc-g++-*-src.tar.gz`
MINGW_RUNTIME=`ls mingw-runtime-*-src.tar.gz`
W32API=`ls w32api-*-src.tar.gz`

PATH=$PATH:$PREFIX/bin

# unpack the archives
for i in $BINUTILS $GCC_CORE $GCC_GXX $MINGW_RUNTIME $W32API
do
   tar xzvf $i
done

# get the source directory names
CHOP="sed 's/-src\.tar\.gz//'"

BINUTILS=$BASE/`basename $BINUTILS -src.tar.gz`
GCC=$BASE/`basename $GCC_CORE -src.tar.gz | sed 's/-core//'`
MINGW_RUNTIME=$BASE/`basename $MINGW_RUNTIME -src.tar.gz`
W32API=$BASE/`basename $W32API -src.tar.gz`

# build binutils
cd $BINUTILS
./configure --target=$TARGET --prefix=$PREFIX
make
make install

# make mingw and w32api includes available
mkdir -vp $PREFIX/include
ln -s $PREFIX/include $PREFIX/$TARGET/include
cp -r $MINGW_RUNTIME/include/* $PREFIX/include
cp -r $W32API/include/* $PREFIX/include

# build gcc for C only
cd $GCC
./configure --prefix=$PREFIX --target=$TARGET --enable-threads --enable-languages=c
make
make install

# build w32api
cd $W32API
./configure --prefix=$PREFIX --target=$TARGET --host=$TARGET --build=$(./config.guess)
make
make install

# put libs where mingw runtime expects them
ln -s $W32API $BASE/w32api
mv $PREFIX/$TARGET/lib/* $PREFIX/lib
rmdir $PREFIX/$TARGET/lib
ln -s $PREFIX/lib $PREFIX/$TARGET/lib

# build mingw runtime
cd $MINGW_RUNTIME
find . -name configure -exec dos2unix \{\} \;
dos2unix config.guess config.sub mkinstalldirs
./configure --prefix=$PREFIX --target=$TARGET --host=$TARGET --build=$(./config.guess)
make
make install

# rebuild gcc for both C and C++
cd $GCC
./configure --prefix=$PREFIX --target=$TARGET --enable-threads --enable-languages=c,c++
make
make install

------- end script -------

If the script makes it to the end, you have a functioning cross-compiler
(probably).

3. Build and install Qt4 on a Windows machine using MinGW. (I'd like to be
able to do this with the cross-compiler, but I had no luck.)

4. Zip up C:\Qt (or wherever your put it) on the Windows machine, and
unpack it on the Linux machine.

5. You need to give qmake a spec file appropriate for the cross-compiler.
I made a new directory called 'win32-x-g++' under qt/mkspecs, copied the
qplatformdefs.h from the win32-g++ directory, and used this as my qmake.conf:

------ begin qmake.conf ------
#
# qmake configuration for win32-g++
#
# Written for MinGW
#

MAKEFILE_GENERATOR	= MINGW
TEMPLATE		= app
CONFIG			+= qt warn_on release link_prl copy_dir_files debug_and_release debug_and_release_target
QT			+= core gui
DEFINES			+= UNICODE QT_LARGEFILE_SUPPORT
QMAKE_COMPILER_DEFINES  += __GNUC__ WIN32

QMAKE_CC		= gcc
QMAKE_LEX		= flex
QMAKE_LEXFLAGS		= 
QMAKE_YACC		= byacc
QMAKE_YACCFLAGS		= -d
QMAKE_CFLAGS		=
QMAKE_CFLAGS_DEPS	= -M
QMAKE_CFLAGS_WARN_ON	= -Wall 
QMAKE_CFLAGS_WARN_OFF	= -w
QMAKE_CFLAGS_RELEASE	= -O2
QMAKE_CFLAGS_DEBUG	= -g
QMAKE_CFLAGS_YACC	= -Wno-unused -Wno-parentheses
QMAKE_CFLAGS_THREAD	= -mthreads

QMAKE_CXX		= i686-mingw32-g++
QMAKE_CXXFLAGS		= $$QMAKE_CFLAGS
QMAKE_CXXFLAGS_DEPS	= $$QMAKE_CFLAGS_DEPS
QMAKE_CXXFLAGS_WARN_ON	= $$QMAKE_CFLAGS_WARN_ON
QMAKE_CXXFLAGS_WARN_OFF	= $$QMAKE_CFLAGS_WARN_OFF
QMAKE_CXXFLAGS_RELEASE	= $$QMAKE_CFLAGS_RELEASE
QMAKE_CXXFLAGS_DEBUG	= $$QMAKE_CFLAGS_DEBUG
QMAKE_CXXFLAGS_YACC	= $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_THREAD	= $$QMAKE_CFLAGS_THREAD
QMAKE_CXXFLAGS_RTTI_ON	= -frtti
QMAKE_CXXFLAGS_RTTI_OFF	= -fno-rtti
QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions
QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -fno-exceptions

QMAKE_INCDIR		= /home/uckelman/projects/board/build/mingw/include
QMAKE_INCDIR_QT		= /home/uckelman/projects/board/build/qt/win-4.1.1/include
QMAKE_LIBDIR_QT		= /home/uckelman/projects/board/build/qt/win-4.1.1/lib

QMAKE_RUN_CC		= $(CC) -c $(CFLAGS) $(INCPATH) -o $obj $src
QMAKE_RUN_CC_IMP	= $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
QMAKE_RUN_CXX		= $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $obj $src
QMAKE_RUN_CXX_IMP	= $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<

QMAKE_LINK		= i686-mingw32-g++
QMAKE_LFLAGS		= -mthreads -Wl,-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mwindows
QMAKE_LFLAGS_RELEASE	= -Wl,-s
QMAKE_LFLAGS_DEBUG	= 
QMAKE_LFLAGS_CONSOLE	= -Wl,-subsystem,console
QMAKE_LFLAGS_WINDOWS	= -Wl,-subsystem,windows
QMAKE_LFLAGS_DLL        = -shared
QMAKE_LINK_OBJECT_MAX	= 10
QMAKE_LINK_OBJECT_SCRIPT= object_script

QMAKE_LIBS		=
QMAKE_LIBS_CORE         = -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lws2_32
#QMAKE_LIBS_CORE         = -lkernel32 -luser32 -luuid -lole32 -ladvapi32 -lws2_32
QMAKE_LIBS_GUI          = -lgdi32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lwinspool -lws2_32 -lole32 -luuid -luser32
QMAKE_LIBS_NETWORK      = -lws2_32
QMAKE_LIBS_OPENGL       = -lopengl32 -lglu32 -lgdi32 -luser32
QMAKE_LIBS_COMPAT       = -ladvapi32 -lshell32 -lcomdlg32 -luser32 -lgdi32 -lws2_32
QMAKE_LIBS_QT_ENTRY     = -lmingw32 -lqtmain

QMAKE_DIR_SEP		= /
QMAKE_COPY		= cp
QMAKE_COPY_DIR		= cp -r
QMAKE_MOVE		= mv
QMAKE_DEL_FILE		= rm -f
QMAKE_MKDIR		= mkdir -p
QMAKE_DEL_DIR		= rm -rf

QMAKE_MOC		= $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}moc
QMAKE_UIC		= $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}uic
QMAKE_IDC		= $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}idc

QMAKE_IDL		= midl
QMAKE_LIB		= i686-mingw32-ar -ru
QMAKE_RC		= i686-mingw32-windres

QMAKE_ZIP		= zip -r -9

QMAKE_STRIP		= i686-mingw32-strip
QMAKE_STRIPFLAGS_LIB 	+= --strip-unneeded
QMAKE_CHK_DIR_EXISTS	= if not exist
load(qt_config)
------ end qmake.conf ------

I found that I needed to set QMAKE_INCDIR, QMAKE_INCDIR_QT, and
QMAKE_LIBDIR_QT in qmake.conf.

7. Make sure that the bin directory for Qt4 (for Linux, not Windows!) and
the bin directory for your cross-compiler are in your path, *before* anything
else. (This is to prevent the wrong tools being used, in case you also have
Qt3 installed, e.g.) Set QTDIR to wherever you put the Windows build of Qt4.

8. Run 'qmake -spec win32-x-g++' on your project.

9. Run 'make' as usual.

Hopefully this will save someone a bit of time. (I used http://silmor.de/29
as a resource for getting started; very helpful, but not quite complete.)
 
-- 
 [ signature omitted ] 

Message 2 in thread

Joel Uckelman said:
> Hopefully this will save someone a bit of time. (I used
> http://silmor.de/29
> as a resource for getting started; very helpful, but not quite complete.)

Ok, I'll try to update the site with the info you sent. Anything in
particular that you missed?

I sometimes miss to give some hints, since I already avoid many of the
traps by instinct.



    Konrad

--
 [ signature omitted ]