Reputation: 12259
I've a project which uses Qt4 with no additional libraries and QtSql (for working with a SQLLite database) and I want to cross-compile it for a x86_64 Windows 7 machine. That's my summarized makefile (it uses only .hpp files, apart from main.cpp, since I make use of lots of templates):
CXX=g++-4.8
CXXFLAGS=-std=c++11 -pedantic -Wall -pedantic-errors -Wextra
IPATH=-I/usr/include/qt4/ -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtSql
LDFLAGS=-lQtGui -lQtSql -lQtCore
OBJS=main.o
HEADERS=mymoc1.hpp mymoc2.hpp other-headers
all: myexec
myexec: $(OBJS)
$(CXX) $(CXXFLAGS) $(OBJS) -o $@ $(LDFLAGS)
main.o: main.cpp $(HEADERS)
$(CXX) -c $(CXXFLAGS) $< -o $@ $(IPATH)
mymoc1.hpp: the-header-needing-moc.hpp
moc $< -o $@
mymoc2.hpp: other-header-needing-moc.hpp
moc $< -o $@
I am going to follow the next tutorial: http://mxe.cc/#tutorial Supposing I've complete succesfully the first fourth steps, my doubt comes from choosing between 5c and 5d steps. What shall I use and how in my case? What does it happen with dependences like QtSql? And with moc?
Additionally, should I define LD, AR or PKG_CONFIG variables as the tutorial says? I didn't specify the linker or the assembler in my original makefile. And in case I should, why?
EDIT I've read here that mingw
has troubles working with templates, and I make a deep use of them in my project. Since MXE uses mingw
internally, should I consider other alternatives (like build in Windows directly) instead of using MXE?
Upvotes: 2
Views: 285
Reputation: 12259
I'm going to post my own answer here, but full of details, because I was very lost and perhaps other users are in similar conditions.
I am going to follow the next tutorial: http://mxe.cc/#tutorial Supposing I've complete successfully the first fourth steps, my doubt comes from choosing between 5c and 5d steps. What shall I use and how in my case?
Yes, you (me indeed, I'm answering my own question), can use Makefile to cross-compile a statically-linked Qt project. The problem is, as Qt is statically linked, any other Qt dependencies must be statically linked as well, and this create a potential long string of library dependencies to be added in your Makefile (and you also need to know the correct options to be passed to the linker). The problem is some of these option or libraries are beside windows-specific, so, if you have never compiled a program for Windows before, it's hard you to know what are they and what they are used for.
For this reason the best thing you can do is to write your own .pro
file to create a working Makefile with qmake
. At this point, if you do still want to make your custom Makefile, you can execute the makefile
generated by qmake
and see the executed commands, to copy back and experiment in your custom Makefile.
Anyway, I'll post the farest makefile
I reach (later in this post I'll show how my working *.pro
file looks like). It compiled successfully, but it crash when linking, because there was a lot of unresolved dependences I hadn't be capable to fix as said above (my mxe installation is in `/usr/local/mxe):
ifndef CROSS
CROSS=x86_64
endif
CROSS_ID=$(CROSS)-w64-mingw32.static
MXE_BASE=/usr/local/mxe/usr
MXE_USR=$(MXE_BASE)/$(CROSS_ID)
MXE_INCL=$(MXE_USR)/include
MXE_QTINCL=$(MXE_USR)/qt/include
MXE_LIB=$(MXE_USR)/lib
MXE_QTLIB=$(MXE_USR)/qt/lib
LDIFLAGS=-I$(MXE_INCL) -I$(MXE_QTINCL)/QtCore -I$(MXE_QTINCL)/QtGui -I$(MXE_QTINCL)/QtSql
LDLFLAGS=-L$(MXE_LIB) -L$(MXE_QTLIB)
LDLIBS=-Wl,-Bstatic -lwinmm -loleut32 -lQtGui -lQtSql -lQtCore
CXX=$(MXE_PATH)/bin/$(CROSS_ID)-g++
CXXFLAGS=-std=c++11 -pedantic -pedantic-errors -Wall
OBJS=main.o
MOC_HEADERS=mymoc1.hpp mymoc2.hpp
HEADERS=$(MOC_HEADERS) myheaders
APP=myapp.exe
all: $(APP)
$(APP): $(OBJS)
$(CXX) $(CXXFLAGS) $(OBJS) -o $@ $(LDLFLAGS) $(LDLIBS)
main.o: main.cpp $(HEADERS)
$(CXX) $(CXXFLAGS) $< -o $@ $(LDIFLAGS)
mymoc1: header1.hpp
moc $< -o $@
mymoc2: header2.hpp
moc $< -o $@
# Thee ways of call it:
# make # CROSS=x86_64 by default as shown in the first line.
# make CROSS=x86_64 # Make it explicit.
# make CROSS=i686 # Choose 32 bit.
What does it happen with dependencies like QtSql?
As you see, you treat your dependencies as other normal libraries: specifying it with -l
options, but now with Wl,-Bstatic
(to say the linker the linking must be static), and specifying with -L
options the exact place of the cross-compiled libraries as shown in the code above. Additionally, in that makefile
I added -lwinmm
and -loleut32
because they were ones of the falling dependencies.
Anyway, this makefile don't fully compile because of the linker, but to work, you shall only to add the other indirectly required libraries and options (seeying the qmake
generated makefile
). Anyway, the main configuration
issues are all of them shown in the makefile
above.
And with moc?
The tool moc
is a preprocessor, and thus, machine independent (AFAIK). So, you can pass moc
to your files using the local installation of moc. Anyway, MXE, of course, also installs a platform-specific moc
:
MXE_MOC=$(MXE_USR)/qt/bin/moc
mymoc1: header1.hpp
$(MXE_MOC) $< -o $@
But I don't think there's important differences between the moc
of MXE and yours, except perhaps the MXE version is more modern (I don't know).
Additionally, should I define LD, AR or PKG_CONFIG variables as the tutorial says?
It isn't necessary. If you don't explicitly use them, you don't need to define them.
I've read that mingw has troubles working with templates, and I make a deep use of them in my project.
False. The current MXE version installs the mingw32
forge of gcc
5.1.0, which works like a charm.
And what about the .pro
file?
MXE = /usr/local/mxe/usr/$$CROSS
MXE_INCL = $$MXE/include
MXE_LIB = $$MXE/lib
MXE_QT = $$MXE/qt
MXE_QTINCL = $$MXE_QT/include
MXE_QTLIB = $$MXE_QT/lib
TARGET = myapp # .exe no required.
OBJS = main.o
MOC_HEADERS = mymoc1.hpp mymoc2.hpp
HEADERS = $$MOC_HEADERS other-headers
SOURCES = main.cpp
QMAKE_CXX = $${CROSS}-g++
QMAKE_CXXFLAGS = -static -std=c++11 -pedantic -pedantinc-errors -Wall
QMAKE_LFLAGS += -Xlinker -Bstatic
INCLUDE_PATH += $$MXE_QTINCL $$MXE_QTINCL/QtGui $$MXE_QTINCL/QtSql
TEMPLATE = app
CONFIG += qt release
QT += core gui sql
LIBS += -L$$MXE_QTLIB -L$$MXE_LIB
# Call it (for x86_64):
# /usr/local/mxe/usr/x86_64-w64-mingw32.static/qt/bin/qmake\
# -makefile -o cross_makefile -nomoc CROSS=x86_64 myapp.pro
# make -f cross_makefile
As you see, I'm saying qmake
to don't generate moc
files (option -nomoc
), because for some strange reason, qmake
is not capable to find my Q_OBJECT
s among so many templates. So, I had to generate them manually before. What I really did was to modify my original makefile (the one I use to compile my project for Linux) with a target call cross
which generates the moc
files and then call automatically qmake
with the proper options.
Upvotes: 2