我有一个项目,它使用Qt4,没有额外的库和QtSql(用于使用SQLLite数据库),我想在x86_64 Windows 7机器上交叉编译它。这是我总结的makefile(除了main.cpp,它只使用.hpp文件,因为我使用了很多模板):
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 $@
我将遵循下一个教程:http://mxe.cc/#tutorial假设我成功地完成了前四步,我的怀疑来自于在第五步和第五步之间的选择。在我的情况下,我应该使用什么?如何使用?像QtSql这样的依赖会发生什么?而moc呢?
另外,我应该定义LD, AR或PKG_CONFIG变量,如教程所说?我没有在原始的makefile中指定链接器或汇编器。以防万一,为什么?
EDIT我在这里读到mingw
在使用模板时遇到了麻烦,我在我的项目中深入使用了它们。由于MXE在内部使用mingw
,我是否应该考虑其他替代方案(如直接在Windows中构建)而不是使用MXE?
我将在这里发布我自己的答案,但详细说明,因为我很迷路,也许其他用户也有类似的情况。
我将遵循下一个教程:http://mxe.cc/#tutorial假设我已经成功地完成了第一个第四步,我的怀疑来自于5c和5d步骤之间的选择。在我的情况下,我应该使用什么?如何使用?
是的,你(我确实,我在回答我自己的问题),可以使用Makefile交叉编译一个静态链接的Qt项目。问题是,由于Qt是静态链接的,任何其他Qt依赖项也必须静态链接,这将创建一个潜在的长串库依赖项,以添加到您的Makefile中(并且您还需要知道传递给链接器的正确选项)。问题是其中一些选项或库不是Windows专用的,所以,如果你以前从未为Windows编译过程序,你很难知道它们是什么以及它们是用来做什么的。
由于这个原因,你能做的最好的事情就是写你自己的.pro
文件,用qmake
创建一个工作的Makefile。此时,如果您仍然想要创建自定义Makefile,您可以执行由qmake
生成的makefile
,并查看执行的命令,以复制回来并在自定义Makefile中进行实验。
无论如何,我将发布我到达的最远的makefile
(在这篇文章的后面,我将展示我的*.pro
文件是如何工作的)。它编译成功了,但是在链接时崩溃了,因为有很多未解决的依赖,我没有能力修复,如上所述(我的mxe安装在'/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.
像QtSql这样的依赖会发生什么?
如您所见,您将依赖项视为其他普通库:使用-l
选项指定它,但现在使用Wl,-Bstatic
(说明链接器必须是静态的),并使用-L
选项指定交叉编译库的确切位置,如上面的代码所示。此外,在makefile
中,我添加了-lwinmm
和-loleut32
,因为它们是下降的依赖项之一。
qmake
生成的makefile
)。无论如何,configuration
的主要问题都在上面的makefile
中显示。
和moc?
工具moc
是一个预处理器,因此,机器独立(AFAIK)。因此,您可以使用moc的本地安装将moc
传递给您的文件。无论如何,MXE当然也安装了一个平台特定的moc
:
MXE_MOC=$(MXE_USR)/qt/bin/moc
mymoc1: header1.hpp
$(MXE_MOC) $< -o $@
但是我不认为MXE的moc
和你的有什么重要的区别,除了可能MXE版本更现代(我不知道)。
另外,我应该定义LD, AR或PKG_CONFIG变量,如教程所说?
没有必要。如果你不显式地使用它们,你就不需要定义它们。
我读到mingw在使用模板时遇到了麻烦,我在我的项目中深入使用了它们。
假。当前的MXE版本安装了gcc
5.1.0的mingw32
forge,效果非常好。
那.pro
文件呢?
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
如你所见,我说qmake
不生成moc
文件(选项-nomoc
),因为出于某种奇怪的原因,qmake
无法在这么多模板中找到我的Q_OBJECT
。所以,我之前必须手动生成它们。我真正做的是修改我的原始makefile(我用来编译Linux项目的那个),目标调用cross
生成moc
文件,然后使用适当的选项自动调用qmake
。