我想使用 Qt 进行编程,但我不想使用特殊的编译器或 IDE,例如 Qt Creator 和 qmake。我想和 Kate 一起写,用 g++ 编译。
我可以编译一个使用 Qt 和 g++ 的程序吗?如何用 g++ 编译它?
你当然可以。虽然使用 qmake 或 CMake 更方便,但您可以这样做:
CXXFLAGS += -Ipath_to_your_qt_includes
LDFLAGS += -Lpath_to_your_qt_libs
LDLIBS += -lqt-mt (for Qt3)
或者
LDLIBS += -lQtCore -lQtGui (for Qt4, add what you need)
my_prog: my_prog.cpp
(在生成文件中)
更新 - 调用 moc
:
引自 moc manpage:
如果您只使用 GNU make,这里有一个有用的 makefile 规则: m%.cpp: %.h moc $< -o $@
我个人将输出命名为 %.moc.cpp
(而不是 m%.cpp
)。然后在 my_prog.moc.cpp
上添加 my_prog
的依赖项
my_prog: my_prog.cpp my_prog.moc.cpp
uic 也是如此。这里的情况更复杂,因为你必须为头文件和源文件生成规则,并且你必须添加对头文件的依赖以确保它在源代码编译之前生成。像这样的东西可能会起作用:
my_prog: my_prog.o my_prog.moc.o my_prog.ui.o
$(CXX) $(LDFLAGS) -o my_prog $^ $(LDLIBS)
my_prog.o: my_prog.cpp my_prog.ui.h
您当然不必使用 QtCreator 来编写 Qt 程序。
您也不必使用 qmake
,但不使用它是在自找麻烦。
要在 Qt 中做任何有趣的事情,您最终将不可避免地继承 QObject
。所有这些子类都需要在其定义中使用 Q_OBJECT
宏来启用信号/槽语法。此语法不是常规的 C++,不能使用 g++ 进行编译。包含带有 Q_OBJECT
的类定义的文件必须通过 Qt 的 meta-object compiler 运行,该 meta-object compiler 称为 moc
。这意味着您必须确定哪些文件需要应用 moc
,然后对它们运行 moc
,然后使用 g++
编译生成的 cpp 文件。这就是 Qt 提供 qmake
的原因。它会在 Makefile 中为您生成正确的规则。
Qt .pro 项目文件使用起来非常简单,我强烈建议您使用它们。请记住,qmake
与 g++
一样是一个命令行工具。此外,它实际上可以通过提供 -project
选项为您创建一个框架项目文件,因此您可以开始
qmake -project
qmake
make
你就完成了。在实践中,我发现生成的项目文件可能缺少我可能正在使用的任何额外 Qt 库的声明,因此您可能必须添加如下行
QT += opengl
例如,如果您包含了类似 QGLWidget
的内容。
qmake
,您将必须“确定哪些文件需要将 moc
应用于它们,然后在它们上运行 moc”。我目前在一家公司工作,我们有自己的构建系统,它在没有 qmake
帮助的情况下调用 moc
。
这是我不使用 qmake 的任何 Qt 项目的 makefile:
#---------------------------------------------------------------------------------
# Compiler executables
#---------------------------------------------------------------------------------
CC := gcc
CXX := g++
#---------------------------------------------------------------------------------
# Options for code generation
#---------------------------------------------------------------------------------
DEFINES := -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
CFLAGS := -g -Wall $(DEFINES)
CXXFLAGS:= $(CFLAGS)
LDFLAGS := -g -Wl
#---------------------------------------------------------------------------------
# Any extra libraries you wish to link with your project
#---------------------------------------------------------------------------------
LIBS := -lQtGui -lQtCore -lpthread
#---------------------------------------------------------------------------------
# Some more include paths
#---------------------------------------------------------------------------------
INCPATHS:= -I/usr/share/qt4/mkspecs/default -I/usr/include/QtGui -I/usr/include/QtCore
#---------------------------------------------------------------------------------
# Source folders and executable name
#---------------------------------------------------------------------------------
TARGET := $(shell basename $(CURDIR))
BUILD := build
SOURCES := source
INCLUDES:= source include
#---------------------------------------------------------------------------------
# Source files
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(INCLUDES),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
HFILES := $(foreach dir,$(INCLUDES),$(notdir $(wildcard $(dir)/*.h)))
#---------------------------------------------------------------------------------
# Use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(HFILES:.h=.moc.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) $(INCPATHS)
#---------------------------------------------------------------------------------
.PHONY: $(BUILD) clean install uninstall
#------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET)
#---------------------------------------------------------------------------------
install:
@cp -u $(TARGET) /usr/bin/$(TARGET)
@echo installed.
#---------------------------------------------------------------------------------
uninstall:
@rm -f /usr/bin/$(TARGET)
@echo uninstalled.
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
# Makefile targets
#---------------------------------------------------------------------------------
all: $(OUTPUT)
#---------------------------------------------------------------------------------
$(OUTPUT): $(OFILES)
@echo built ... $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) -o $@ $(LIBS)
#---------------------------------------------------------------------------------
%.o: %.c
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(C) $(CFLAGS) $(INCLUDE) -c $< -o $@
#---------------------------------------------------------------------------------
%.o: %.cpp
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@
#---------------------------------------------------------------------------------
%.moc.cpp: %.h
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@moctool $< $(DEFINES) $(INCLUDE) -o $@
#---------------------------------------------------------------------------------
%.moc.o: %.moc.cpp
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
在这里,moctool 是一个帮助非 QObject 标头的简单工具,这里是它的源代码:
https://github.com/Quent42340/EasyLib/blob/master/tools/moctool/source/main.cpp
ifneq ($(BUILD),$(notdir $(CURDIR)))
似乎检查了 makefile 是否从构建目录执行,如果不是,它似乎在第 71 行调用另一个 @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
。为什么?相反,在第 93 行的 else
之后以 all:
目标开始的所有内容都是我所期望的。我希望OP会回应...
Qt 项目需要一些预编译器,如 moc、uic、...等。 Qt Creator + qmake 可以方便地做这些事情并为 g++ 或 msvc 编译器生成一个 makefile。
我喜欢使用 Vim 和 Qt Designer 的简化版本使用 Qt 进行编程......最后一个帮助我制作窗口原型......然后我将 Qt Designer 的层次结构转换为我在 Vim 上手动编码的窗口标题......
结果是我所有的代码都由我自己维护......没有.ui,没有ui_.cpp ..没有ui指针......所以我可以自由地操作我的代码。
不定期副业成功案例分享
moc
(它非常需要证明这一点)