ChatGPT解决这个技术问题 Extra ChatGPT

我可以在没有 qmake 或 Qt Creator 的情况下使用 Qt 吗?

我想使用 Qt 进行编程,但我不想使用特殊的编译器或 IDE,例如 Qt Creator 和 qmake。我想和 Kate 一起写,用 g++ 编译。

我可以编译一个使用 Qt 和 g++ 的程序吗?如何用 g++ 编译它?

我可以理解不想使用 Qt Creator,但为什么不使用 qmake? qmake 所做的只是为您生成一个 Makefile;如果您不使用 qmake,则必须自己编写相同的 Makefile,更糟糕的是,您必须为要在其下编译的每个平台手动维护不同的 Makefile。使用 qmake,您只需要创建一个 .pro 文件,而不必记住 MSVC Makefile 与 gnu Makefile 的区别等等。
因为我想知道编译过程中发生了什么,而不是使用自动工具。使用 qmake 或 Qt Creator 更容易,但我喜欢手动完成这项任务。
如果您想了解 make 的工作原理,您仍然可以查看 qmake 生成的 Makefile。
我们当中有很多人甚至没有使用 Makefile——毕竟还有其他构建系统。特别是 SCons 和 bjam 非常受欢迎。我开发了一个最近开始使用 Qt 的中型客户端应用程序,我不可能将我们的整个构建系统切换到 qmake - 特别是当 qmake 在找出依赖关系和决定何时它必须重新生成您的 Makefile。
@JeremyFriesner 一个更好的答案(晚了几年)可能是:我已经有一个构建工具(make 或其他)并且不想要一个负责我的工具链的库。

j
jpalecek

你当然可以。虽然使用 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

此外,如果您使用 Qt 的扩展语法(如信号和插槽等),则需要手动运行 moc。那是唯一的“强制性”特殊编译器。
这个答案并没有告诉您如何运行 moc(它非常需要证明这一点)
f
feedc0de

您当然不必使用 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 项目文件使用起来非常简单,我强烈建议您使用它们。请记住,qmakeg++ 一样是一个命令行工具。此外,它实际上可以通过提供 -project 选项为您创建一个框架项目文件,因此您可以开始

qmake -project
qmake
make

你就完成了。在实践中,我发现生成的项目文件可能缺少我可能正在使用的任何额外 Qt 库的声明,因此您可能必须添加如下行

QT += opengl

例如,如果您包含了类似 QGLWidget 的内容。


出于所有意图和目的,如果没有 QMake,Qt 将毫无用处。不错的答案。
这个答案具有误导性。 Qmake 是一个构建工具,独立于 moc。您可以从不同的构建工具成功且轻松地调用 moc。例如,我在 Visual Studio 和 SCons 中完成了这项工作。在这两个方面都可以轻松透明地处理它,以便您可以正常进行,就好像 moc 不存在一样。
@JBentley:答案很清楚,如果没有 qmake,您将必须“确定哪些文件需要将 moc 应用于它们,然后在它们上运行 moc”。我目前在一家公司工作,我们有自己的构建系统,它在没有 qmake 帮助的情况下调用 moc
@Troubadour 是的,但是您还说“您不使用 [qmake] 是在自找麻烦”,并且“我会认真建议您使用 [.pro 项目文件]”。我没有说你的答案是错误的,只是误导。在“我可以在没有 qmake 或 Qt Creator 的情况下使用 Qt 吗?”的上下文中,您暗示不使用 qmake 是困难和/或麻烦的。实际上,答案的第一个评论者得出的结论是“没有 QMake,Qt 毫无用处”。事实上,qmake 只是几个合法且高度可用的替代方案之一。
“Q_OBJECT ...此语法不是常规的 C++”。它只是一个宏,它是完全有效的 C++。宏所做的只是声明一堆函数。 moc 编译提供了定义。
Q
Quent42340

这是我不使用 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


我意识到这是旧的,但这个答案正是我正在尝试在我当前的项目中做的。但是,我正在努力理解一些逻辑。首先,第 36 行:ifneq ($(BUILD),$(notdir $(CURDIR))) 似乎检查了 makefile 是否从构建目录执行,如果不是,它似乎在第 71 行调用另一个 @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile。为什么?相反,在第 93 行的 else 之后以 all: 目标开始的所有内容都是我所期望的。我希望OP会回应...
A
AechoLiu

Qt 项目需要一些预编译器,如 moc、uic、...等。 Qt Creator + qmake 可以方便地做这些事情并为 g++ 或 msvc 编译器生成一个 makefile。


M
Mikeh Miiikeh

我喜欢使用 Vim 和 Qt Designer 的简化版本使用 Qt 进行编程......最后一个帮助我制作窗口原型......然后我将 Qt Designer 的层次结构转换为我在 Vim 上手动编码的窗口标题......

结果是我所有的代码都由我自己维护......没有.ui,没有ui_.cpp ..没有ui指针......所以我可以自由地操作我的代码。