2

我有一个使用 Qt4 的项目,没有其他库和 QtSql(用于使用 SQLLite 数据库),我想为 x86_64 Windows 7 机器交叉编译它。这是我总结的 makefile(它只使用 .hpp 文件,除了 main.cpp,因为我使用了很多模板):

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 假设我已经成功完成了前四个步骤,我的疑问来自于在 5c 和 5d 步骤之间进行选择。在我的情况下,我应该使用什么以及如何使用?像 QtSql 这样的依赖会发生什么?和 moc?

此外,我应该按照教程中的说明定义 LD、AR 或 PKG_CONFIG 变量吗?我没有在我的原始 makefile 中指定链接器或汇编器。如果我应该这样做,为什么?

编辑我在这里读到了mingw使用模板时遇到的麻烦,我在我的项目中深入使用了它们。由于 MXEmingw在内部使用,我是否应该考虑其他替代方案(如直接在 Windows 中构建)而不是使用 MXE?

4

1 回答 1

2

我将在这里发布我自己的答案,但充满了细节,因为我非常迷茫,也许其他用户也处于类似的情况。

我将遵循下一个教程:http://mxe.cc/#tutorial假设我已经成功完成了前第四步,我的疑问来自于在 5c 和 5d 步骤之间进行选择。在我的情况下,我应该使用什么以及如何使用?

是的,您(我确实是在回答我自己的问题)可以使用 Makefile 来交叉编译静态链接的 Qt 项目。问题是,由于 Qt 是静态链接的,因此任何其他 Qt 依赖项也必须静态链接,这会创建一个潜在的长串库依赖项,以添加到您的 Makefile 中(并且您还需要知道要传递的正确选项到链接器)。问题是其中一些选项或库是特定于 Windows 的,因此,如果您以前从未为 Windows 编译过程序,那么您很难知道它们是什么以及它们的用途。

出于这个原因,您可以做的最好的事情是编写自己的.pro文件来创建一个使用qmake. 此时,如果您仍然想制作您的自定义 Makefile,您可以执行makefile生成的qmake并查看执行的命令,复制回来并在您的自定义 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因为它们是下降的依赖项之一。

无论如何,由于链接器,这个 makefile 不能完全编译,但要工作,您只需添加其他间接需要的库和选项(查看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 版本安装了mingw325.1.0 的gccforge,它就像一个魅力。

.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在这么多模板中找到我的 s。所以,我之前必须手动生成它们。我真正做的是修改我的原始makefile(我用来为Linux编译我的项目的那个),使用目标调用cross生成moc文件,然后qmake使用适当的选项自动调用。

于 2015-05-23T12:02:07.373 回答