ChatGPT解决这个技术问题 Extra ChatGPT

如何在 QMake .pro 文件中指定不同的调试/发布输出目录

我有一个 Qt 项目,我想在源代码树之外输出编译文件。

我目前有以下目录结构:

/
|_/build
|_/mylib
  |_/include
  |_/src
  |_/resources

根据配置(调试/发布),我想在 build/debug 或 build/release 目录下的 build 目录中输出结果文件。

我怎样才能使用 .pro 文件做到这一点?

Qt 处理调试和发布版本的方式随着时间的推移在内部发生了变化。所以我们发现之前的调试和发布之间的工作切换在后来的版本中中断了。请参阅我的解决方案,该解决方案目前适用于所有平台和所有 Qt 版本。 stackoverflow.com/questions/32046181/…
由于这是一个老问题,因此值得指出的是 better answers 的票数要少得多。

m
mosg

对于我的 Qt 项目,我在 *.pro 文件中使用了这个方案:

HEADERS += src/dialogs.h
SOURCES += src/main.cpp \
           src/dialogs.cpp

Release:DESTDIR = release
Release:OBJECTS_DIR = release/.obj
Release:MOC_DIR = release/.moc
Release:RCC_DIR = release/.rcc
Release:UI_DIR = release/.ui

Debug:DESTDIR = debug
Debug:OBJECTS_DIR = debug/.obj
Debug:MOC_DIR = debug/.moc
Debug:RCC_DIR = debug/.rcc
Debug:UI_DIR = debug/.ui

这很简单,但很好! :)


正是我需要的!并注意:为了让事情更容易切换,仅有条件地定义您的 DESTDIR,然后在所有其他路径中使用该值:OBJECTS_DIR = $${DESTDIR}/.obj。干杯!
介意解释这是如何使用/它做什么的?当我实施它时,它似乎没有任何效果。编辑:如果我将调试更改为调试(小写),它可以工作。我怀疑这是 Windows 与 unix 区分大小写的事情。
我投票它是因为它适用于 Windows。在 Linux(Ubuntu 15.04、Qt 5.5.0)上,我必须将 Debug 更改为 debug 并将 Release 更改为 release
这仅在您在 CONFIG 中只有发布或调试时才有效。如果两者都在配置中,则将使用后一个。
在所有平台上检查调试和发布版本的支持方法是调试 "CONFIG(debug, debug|release)" 和发布 "CONFIG(release, debug|release)" 。在某些情况下,其他所有内容都可能给您带来麻烦:在 CONFIG 变量中,可以包含 debug 和 release,最后一个条目是有效的。
M
Marek R

要更改目标 dll/exe 的目录,请在您的 pro 文件中使用:

CONFIG(debug, debug|release) {
    DESTDIR = build/debug
} else {
    DESTDIR = build/release
}

您可能还想更改其他构建目标的目录,例如目标文件和 moc 文件(查看 qmake variable reference 了解详细信息或 qmake CONFIG() function reference)。


但我发现在其中包含 $$OUT_PWD 更好,所以 DESTDIR=$$OUT_PWD/debug
@Ivo:啊!谢谢!我一直在到处寻找包含该路径的变量! :D
在此之后,您可以添加如下行:OBJECTS_DIR = $$DESTDIR/.obj MOC_DIR = $$DESTDIR/.moc RCC_DIR = $$DESTDIR/.qrc UI_DIR = $$DESTDIR/.ui CONFIG() 原来可以解决使用 release:debug: 的一些问题
这个比选定的答案效果更好。选择的一项有效,但如果同时配置了调试和发布,则保留第二组设置。
H
Hello W

我有一个更紧凑的方法:

release: DESTDIR = build/release
debug:   DESTDIR = build/debug

OBJECTS_DIR = $$DESTDIR/.obj
MOC_DIR = $$DESTDIR/.moc
RCC_DIR = $$DESTDIR/.qrc
UI_DIR = $$DESTDIR/.ui

您的答案是将编译器构建输出放在单独的目录中的最新方法。
您最近是否尝试过调试和发布?无论哪种配置,我的构建输出似乎总是在发布文件夹中;自从您发布此答案以来,qmake / Qt Creator 的行为可能已经改变......
尝试在发布模式下将“CONFIG -=debug”添加到 qmake 的附加参数中
A
ABCplus

执行此操作的正确方法如下(感谢 QT 支持团队):

CONFIG(debug, debug|release) {
    DESTDIR = build/debug
}
CONFIG(release, debug|release) {
    DESTDIR = build/release
}

OBJECTS_DIR = $$DESTDIR/.obj
MOC_DIR = $$DESTDIR/.moc
RCC_DIR = $$DESTDIR/.qrc
UI_DIR = $$DESTDIR/.u

更多信息:https://wiki.qt.io/Qt_project_org_faq#What_does_the_syntax_CONFIG.28debug.2Cdebug.7Crelease.29_mean_.3F_What_does_the_1st_argument_specify_and_similarly_what_is_the_2nd_.3F


S
Sulla

我使用 chalup 建议的相同方法,

ParentDirectory = <your directory>

RCC_DIR = "$$ParentDirectory\Build\RCCFiles"
UI_DIR = "$$ParentDirectory\Build\UICFiles"
MOC_DIR = "$$ParentDirectory\Build\MOCFiles"
OBJECTS_DIR = "$$ParentDirectory\Build\ObjFiles"

CONFIG(debug, debug|release) { 
    DESTDIR = "$$ParentDirectory\debug"
}
CONFIG(release, debug|release) { 
    DESTDIR = "$$ParentDirectory\release"
}

h
hyde

老问题,但仍然值得一个最新的答案。今天,当使用影子构建时,通常会执行 Qt Creator 所做的事情(在打开新项目时默认启用它们)。

对于每个不同的构建目标和类型,正确的 qmake 在不同的构建目录中使用正确的参数运行。那么这只是用简单的 make 构建的。

因此,想象中的目录结构可能如下所示。

/
|_/build-mylib-qt5-mingw32-debug
|_/build-mylib-qt5-mingw32-release
|_/build-mylib-qt4-msvc2010-debug
|_/build-mylib-qt4-msvc2010-release
|_/build-mylib-qt5-arm-debug
|_/build-mylib-qt5-arm-release
|_/mylib
  |_/include
  |_/src
  |_/resources

重要的是,qmake 在构建目录中运行:

cd build-mylib-XXXX
/path/to/right/qmake ../mylib/mylib.pro CONFIG+=buildtype ...

然后它会在 build 目录中生成 makefile,然后 make 也会在其下生成文件。只要 qmake 从未在源目录中运行(如果是,最好将其清理干净!),就没有不同版本混淆的风险。

像这样完成后,当前接受的答案中的 .pro 文件更加简单:

HEADERS += src/dialogs.h
SOURCES += src/main.cpp \
           src/dialogs.cpp

对于单个项目工作正常,但如果你有一个项目和一个库呢?然后,您需要一种依赖于构建类型的方式来包含库 afaics。
@Adversus我不确定你到底是什么意思,但也许 Qmake 变量 $(OUT_PWD) 是解决方案?
当我将我的问题应用于您的示例时,它变成:应用程序获取 mylib 的最干净的方式是什么?如果有一种“优雅”的方式来做到这一点,我会喜欢它,除了使用其他答案中的技术之外,我没有看到其他方法:使用构建类型和配置以智能方式填充 LIBS方式,抵消了影子构建的优势。
@Adversus 如果 mylib 是同一顶级项目下的子目录项目,我通常会添加一个 mylib.pri 文件,并将 other 子目录项目需要的所有内容放在那里,使用 Qmake 变量始终正确获取路径,即使它是影子构建。然后其他 subdir .pro 文件将仅具有 include(../mylib/mylib.pri)
谢谢,这就是我现在正在做的事情,如果有一个自动处理的解决方案会很好,比如当你有一个在 cmake 中有子项目的项目时,然后可以轻松地做出不同的 -整个树的源代码构建。
K
Kuba hasn't forgotten Monica

简短的回答是:你没有。

您应该在要构建的任何构建目录中运行 qmake,然后运行 make。因此,在 debug 目录中运行一次,在 release 目录中运行一次。

这就是构建您的项目的任何人都期望它工作的方式,这就是 Qt 本身设置构建的方式,这也是 Qt Creator 期望您的 .pro 文件的行为方式:它只是启动 qmake 然后 make 在为您的目标选择的配置构建文件夹。

如果您希望创建这些文件夹并在其中执行两个(或更多)构建,您将需要一个顶级 makefile,可能通过 qmake 从顶级项目文件创建。

拥有两个以上的构建配置并不少见,因此您不必要地承诺只区分构建和发布;您可能有不同优化级别的构建,等等。调试/发布二分法最好让其安息。


没有像 CMake 的 cmake -B build-dir 那样?
qmake 就像没有 -Bcmake:您首先 cd 进入所需的构建目录,然后在那里运行它 :) 而且,它通常很糟糕,不需要它:cmake 或 bust :)
完全同意第 2 部分
这不是正确的答案,您可以并且这是预期的。否则它是一些自制项目,而不是生产环境。在工业中,它预计在源文件目录之外有输出,因为它是 VCS 软件、团队集成等。
@Kubahasn'tforgottenMonica 我见过cmake在实践中做的唯一一件事是其他构建系统没有做的是增加我们新员工的培训时间,因为它太冗长了。此外,使用 cmake 有充分的理由,但 90% 的时间我看到团队花费时间来切换到它,这不是出于这些原因之一;这是因为他们不知道如何使用他们以前的构建系统并且读到 cmake 解决了他们所有的问题。 :)
S
Steve Besch

为输出可执行文件设置一个稍微不同的名称也很有用。你不能使用类似的东西:

release: Target = ProgramName
debug: Target = ProgramName_d

为什么它不起作用尚不清楚,但事实并非如此。但:

CONFIG(debug, debug|release) {
    TARGET = ProgramName
} else {
    TARGET = ProgramName_d
}

只要 CONFIG += 行在它之前,它就可以工作。


B
BuvinJ

新版本的 Qt Creator 在调试和发布之间还有一个“配置文件”构建选项。这是我检测到的方式:

CONFIG(debug, debug|release) {  DEFINES += DEBUG_MODE }
else:CONFIG(force_debug_info) { DEFINES += PROFILE_MODE }
else {                          DEFINES += RELEASE_MODE }

A
Ahmed Rashed

这是我用于不同调试/发布输出目录的 Makefile。这个 Makefile 在 Ubuntu linux 上测试成功。如果正确安装了 Mingw-w64,它应该可以在 Windows 上无缝运行。

ifeq ($(OS),Windows_NT)
    ObjExt=obj
    mkdir_CMD=mkdir
    rm_CMD=rmdir /S /Q
else
    ObjExt=o
    mkdir_CMD=mkdir -p
    rm_CMD=rm -rf
endif

CC     =gcc
CFLAGS =-Wall -ansi
LD     =gcc

OutRootDir=.
DebugDir  =Debug
ReleaseDir=Release


INSTDIR =./bin
INCLUDE =.

SrcFiles=$(wildcard *.c)
EXEC_main=myapp

OBJ_C_Debug   =$(patsubst %.c,  $(OutRootDir)/$(DebugDir)/%.$(ObjExt),$(SrcFiles))
OBJ_C_Release =$(patsubst %.c,  $(OutRootDir)/$(ReleaseDir)/%.$(ObjExt),$(SrcFiles))

.PHONY: Release Debug cleanDebug cleanRelease clean

# Target specific variables
release: CFLAGS += -O -DNDEBUG
debug:   CFLAGS += -g

################################################
#Callable Targets
release: $(OutRootDir)/$(ReleaseDir)/$(EXEC_main)
debug:   $(OutRootDir)/$(DebugDir)/$(EXEC_main)

cleanDebug:
    -$(rm_CMD) "$(OutRootDir)/$(DebugDir)"
    @echo cleanDebug done

cleanRelease:
    -$(rm_CMD) "$(OutRootDir)/$(ReleaseDir)"
    @echo cleanRelease done

clean: cleanDebug cleanRelease
################################################

# Pattern Rules
# Multiple targets cannot be used with pattern rules [https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html]
$(OutRootDir)/$(ReleaseDir)/%.$(ObjExt): %.c | $(OutRootDir)/$(ReleaseDir)
    $(CC) -I$(INCLUDE) $(CFLAGS) -c $< -o"$@"

$(OutRootDir)/$(DebugDir)/%.$(ObjExt):   %.c | $(OutRootDir)/$(DebugDir)
    $(CC) -I$(INCLUDE) $(CFLAGS) -c $< -o"$@"

# Create output directory
$(OutRootDir)/$(ReleaseDir) $(OutRootDir)/$(DebugDir) $(INSTDIR):
    -$(mkdir_CMD) $@

# Create the executable
# Multiple targets [https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html]
$(OutRootDir)/$(ReleaseDir)/$(EXEC_main): $(OBJ_C_Release)
$(OutRootDir)/$(DebugDir)/$(EXEC_main):   $(OBJ_C_Debug)
$(OutRootDir)/$(ReleaseDir)/$(EXEC_main) $(OutRootDir)/$(DebugDir)/$(EXEC_main):
    $(LD) $^ -o$@

u
user2189731

不确定是否有人会遇到像我这样的问题,但我会分享我的设置。我使用中央 proj.pri 文件来存储常规设置。我在每个子目录中都有 PKG.pro,它已经为调试模式设计。因此,当我尝试构建调试和发布时,我不想修改每个子目录中的每个 PKG.pro。我添加了相同的

DESTDIR = $${SOMEOTHERPATH}
release: DESTDIR = $${DESTDIR}/release
debug:   DESTDIR = $${DESTDIR}/debug

OBJECTS_DIR = $$DESTDIR/.obj
MOC_DIR = $$DESTDIR/.moc
RCC_DIR = $$DESTDIR/.qrc
UI_DIR = $$DESTDIR/.ui

这不起作用,因为在每个子目录中, DESTDIR 将再次被评估。它结束了双重调试或发布。为了避免这种情况,您必须只使用一个 DESTDIR 集,然后在每个子目录中,您可以包含这个 proj.pri 文件。这样,您无需编写一个 DIR 设置。并且需要“qmake CONFIG=debug”或“qmake CONFIG=release”来构建调试或发布。谁有更好的解决方案,请分享。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅