【问题标题】:How to specify different Debug/Release output directories in QMake .pro file如何在 QMake .pro 文件中指定不同的调试/发布输出目录
【发布时间】:2011-02-04 13:46:11
【问题描述】:

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

我目前的目录结构如下:

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

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

如何使用 .pro 文件做到这一点?

【问题讨论】:

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

标签: qt qmake


【解决方案1】:

对于我的 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

这很简单,但很好! :)

【讨论】:

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

要更改目标 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: 的一些问题
  • 这个比选定的答案效果更好。选择的一项有效,但如果同时配置了调试和发布,则保留第二组设置。
【解决方案3】:

我有一个更紧凑的方法:

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 的行为可能已经改变......
  • 在Release模式下尝试将“CONFIG -=debug”添加到qmake的附加参数中
【解决方案4】:

执行此操作的正确方法如下(感谢 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

【讨论】:

    【解决方案5】:

    我使用 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"
    }
    

    【讨论】:

      【解决方案6】:

      老问题,但仍然值得一个最新的答案。今天,当使用影子构建时,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 文件,并使用 Qmake 变量将所有 other 子目录项目需要的东西放在那里即使是影子构建,也要始终保持正确的路径。然后其他子目录 .pro 文件将简单地具有 include(../mylib/mylib.pri)
      • 谢谢,这就是我现在正在做的事情,如果有一个自动处理的解决方案会很好,比如当你有一个在 cmake 中有子项目的项目并且可以然后轻松地对整个树进行不同的外源构建。
      【解决方案7】:

      简短的回答是:你没有

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

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

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

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

      【讨论】:

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

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

      release: Target = ProgramName
      debug: Target = ProgramName_d
      

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

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

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

      【讨论】:

        【解决方案9】:

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

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

        【讨论】:

          【解决方案10】:

          这是我用于不同调试/发布输出目录的 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$@
          

          【讨论】:

            猜你喜欢
            • 2011-08-15
            • 2017-08-01
            • 1970-01-01
            • 2016-06-30
            • 2015-02-03
            • 2020-11-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多