วิธีระบุไดเร็กทอรีเอาต์พุต Debug / Release ที่แตกต่างกันในไฟล์ QMake .pro


106

ฉันมีโปรเจ็กต์ Qt และต้องการส่งออกไฟล์คอมไพล์นอกแผนผังซอร์ส

ปัจจุบันฉันมีโครงสร้างไดเร็กทอรีต่อไปนี้:

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

ขึ้นอยู่กับคอนฟิกูเรชัน (debug / release) ฉันต้องการเอาต์พุตไฟล์ที่เป็นผลลัพธ์ภายในไดเร็กทอรี build ภายใต้ไดเร็กทอรี build / debug หรือ build / release

ฉันจะทำได้อย่างไรโดยใช้ไฟล์. pro


วิธีที่ Qt ปฏิบัติต่อการดีบักและรีลีสบิวด์มีการเปลี่ยนแปลงภายในเมื่อเวลาผ่านไป ดังนั้นเราจึงค้นพบว่าการทำงานก่อนหน้านี้สลับไปมาระหว่างการดีบักและรีลีสยากจนในเวอร์ชันที่ใหม่กว่า ดูโซลูชันของฉันที่ใช้ได้กับทุกแพลตฟอร์มและในเวอร์ชัน Qt ทั้งหมดจนถึงตอนนี้ stackoverflow.com/questions/32046181/…
adlag

2
เนื่องจากนี่เป็นคำถามเก่าจึงควรชี้ให้เห็นว่ามีคำตอบที่ดีกว่าพร้อมคะแนนโหวตน้อยกว่ามาก
wardw

คำตอบ:


4

คำตอบสั้น ๆ คือคุณทำไม่ได้

คุณควรเรียกใช้qmakeตามด้วยmakeในไดเร็กทอรีบิลด์ที่คุณต้องการสร้างดังนั้นให้รันครั้งเดียวในdebugไดเร็กทอรีหนึ่งครั้งในreleaseไดเร็กทอรี

นั่นเป็นวิธีที่ใครก็ตามที่สร้างโปรเจ็กต์ของคุณจะคาดหวังให้มันใช้งานได้และนั่นคือวิธีที่ Qt ถูกตั้งค่าเพื่อสร้างนั่นคือวิธีที่ Qt Creator คาดหวังว่า.proไฟล์ของคุณจะทำงาน: เพียงแค่เริ่มต้นqmakeจากนั้นmakeในโฟลเดอร์ build สำหรับการกำหนดค่าเป้าหมายที่คุณเลือก

หากคุณต้องการสร้างโฟลเดอร์เหล่านี้และสร้างสองโฟลเดอร์ (หรือมากกว่า) ในโฟลเดอร์เหล่านี้คุณจะต้องมี makefile ระดับบนสุดซึ่งอาจสร้างจากไฟล์โปรเจ็กต์ระดับบนสุดผ่าน qmake

ไม่ใช่เรื่องแปลกที่จะมีการกำหนดค่าบิวด์มากกว่าสองแบบดังนั้นคุณจึงตกลงที่จะแยกความแตกต่างระหว่างบิวด์กับรีลีสโดยไม่จำเป็น คุณอาจมีงานสร้างที่มีระดับการเพิ่มประสิทธิภาพที่แตกต่างกันเป็นต้นการแยกขั้วดีบัก / รีลีสควรอยู่อย่างสงบ


152

สำหรับโครงการ 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

เรียบง่าย แต่ดูดี! :)


18
สิ่งที่ฉันต้องการ! และหมายเหตุ: เพื่อให้ได้สิ่งที่ง่ายต่อการเปลี่ยนรอบเพียงกำหนดของคุณDESTDIRs เงื่อนไขและจากนั้นใช้ค่าในทุกเส้นทางอื่น ๆ OBJECTS_DIR = $${DESTDIR}/.objที่: ไชโย!
Xavier Holt

4
ใจอธิบายว่าสิ่งนี้ใช้อย่างไร / ใช้ทำอะไร? ดูเหมือนว่าจะไม่มีผลเมื่อฉันใช้มัน แก้ไข:ถ้าฉันเปลี่ยน Debug เป็น debug (ตัวพิมพ์เล็ก) มันใช้งานได้ ฉันสงสัยว่านี่เป็นสิ่งที่ไวต่อกรณีของ windows vs unix
notlesh

9
ฉันโหวตเพราะมันทำงานบน Windows บน Linux (Ubuntu 15.04, Qt 5.5.0) ฉันต้องเปลี่ยนDebugเป็นdebugและReleaseเป็นrelease.
Jepessen

Wth? ข้ามแพลตฟอร์มมากไหม @ เจปเซ่น ??
นิลส์

2
สิ่งนี้ใช้ได้เฉพาะเมื่อคุณมีรีลีสหรือดีบักใน CONFIG เท่านั้น หากทั้งสองอยู่ใน config ระบบจะใช้อันหลัง
weeska

52

หากต้องการเปลี่ยนไดเร็กทอรีสำหรับ dll / exe เป้าหมายให้ใช้สิ่งนี้ในไฟล์โปรของคุณ:

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

คุณอาจต้องการเปลี่ยนไดเร็กทอรีสำหรับบิลด์เป้าหมายอื่น ๆ เช่นอ็อบเจ็กต์ไฟล์และไฟล์ moc (ตรวจสอบการอ้างอิงตัวแปร qmakeสำหรับรายละเอียดหรือการอ้างอิงฟังก์ชัน qmake CONFIG () )


5
แต่ฉันพบว่ามันดีกว่ามากที่จะรวม $$ OUT_PWD ไว้ในนี้ดังนั้น DESTDIR = $$ OUT_PWD / debug
Ivo

1
@ อิโว: อ๊ะ! ขอบคุณ! ฉันมองหาทุกที่ว่าตัวแปรใดมีเส้นทางนั้น! : D
Cameron

1
หลังจากนี้คุณสามารถเพิ่มบรรทัดเช่น: OBJECTS_DIR = $$DESTDIR/.obj MOC_DIR = $$DESTDIR/.moc RCC_DIR = $$DESTDIR/.qrc UI_DIR = $$DESTDIR/.ui CONFIG()ปรากฎเพื่อแก้ปัญหาบางอย่างในการใช้งานrelease:และdebug:
Carson Ip

ข้อนี้ได้ผลดีกว่าคำตอบที่เลือก อันที่เลือกใช้งานได้ แต่ถ้ามีการกำหนดค่าการดีบักและรีลีสการตั้งค่าบล็อกที่สองจะยังคงอยู่
Paulo Carvalho

42

ฉันมีแนวทางที่กะทัดรัดกว่านี้:

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

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

2
คำตอบของคุณคือวิธีใหม่ล่าสุดในการใส่เอาต์พุตการสร้างคอมไพเลอร์ในไดเร็กทอรีแยกต่างหาก
SIFE

1
เมื่อเร็ว ๆ นี้คุณได้ลองใช้ทั้งการดีบักและรีลีสหรือไม่ ผลลัพธ์การสร้างของฉันดูเหมือนจะจบลงในโฟลเดอร์รีลีสเสมอไม่ว่าจะกำหนดค่าใด พฤติกรรมของผู้สร้าง qmake / Qt อาจเปลี่ยนไปเนื่องจากคุณโพสต์คำตอบนี้แม้ว่า ...
ssc

1
ลองเพิ่ม "CONFIG - = debug" ในอาร์กิวเมนต์เพิ่มเติมของ qmake ในโหมดเผยแพร่
สวัสดี W

17

วิธีที่ถูกต้องในการดำเนินการมีดังต่อไปนี้ (ขอบคุณทีมสนับสนุน 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


13

ฉันใช้วิธีเดียวกับที่ชลัพแนะนำ

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"
}

12

คำถามเก่า แต่ก็ยังคุ้มค่ากับคำตอบที่เป็นปัจจุบัน ทุกวันนี้เป็นเรื่องปกติที่จะทำในสิ่งที่ 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

และสิ่งที่ไม่กระตุ้นคือ a qmakeถูกเรียกใช้ในไดเร็กทอรี build:

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

จากนั้นจะสร้าง makefiles ใน build directory จากนั้น makeจะสร้างไฟล์ภายใต้มันด้วย ไม่มีความเสี่ยงที่เวอร์ชันต่างๆจะปะปนกันตราบใดที่ qmake ไม่เคยทำงานในไดเร็กทอรีต้นทาง (ถ้าเป็นเช่นนั้นควรทำความสะอาดให้ดีขึ้น!)

และเมื่อทำเช่นนี้.proไฟล์จากคำตอบที่ยอมรับในปัจจุบันจะง่ายกว่า:

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

ใช้งานได้ดีสำหรับโครงการเดียว แต่ถ้าคุณมีโครงการและห้องสมุดล่ะ? จากนั้นคุณต้องมีวิธีที่ขึ้นอยู่กับ buildtype ในการรวม afaics ของไลบรารี
Adversus

@Adversus ฉันไม่แน่ใจว่าคุณหมายถึงอะไรกันแน่ แต่ตัวแปร Qmake อาจ$(OUT_PWD)เป็นวิธีแก้ปัญหา?
hyde

เมื่อฉันใช้คำถามของฉันกับตัวอย่างของคุณคำถามจะกลายเป็น: วิธีที่สะอาดที่สุดในการรับใบสมัครmylibคืออะไร? ฉันต้องการถ้าจะมีวิธีที่ "สง่างาม" ในการทำเช่นนี้ฉันไม่เห็นวิธีอื่นนอกจากใช้เทคนิคจากคำตอบอื่น ๆ : ใช้ประเภทการสร้างและการกำหนดค่าเพื่อเติมเต็มLIBSด้วยวิธีที่ชาญฉลาด ข้อดีของการสร้างเงา
Adversus

@Adversus หาก mylib เป็นโปรเจ็กต์ย่อยภายใต้โปรเจ็กต์ระดับบนสุดเดียวกันฉันมักจะเพิ่มไฟล์ mylib.pri และใส่ทุกอย่างที่โปรเจ็กต์ย่อยอื่น ๆต้องการที่นั่นโดยใช้ตัวแปร Qmake เพื่อให้ได้พา ธ ที่ถูกต้องเสมอแม้ว่าจะเป็น Shadow build ก็ตาม จากนั้นไฟล์ subdir .pro อื่น ๆ ก็จะมีinclude(../mylib/mylib.pri)
hyde

ขอบคุณนั่นคือสิ่งที่ฉันกำลังทำอยู่ตอนนี้คงจะดีไม่น้อยหากมีวิธีแก้ไขปัญหานี้โดยอัตโนมัติเช่นเมื่อคุณมีโปรเจ็กต์ที่มีโปรเจ็กต์ย่อยเป็น cmake จากนั้นก็สามารถสร้างสิ่งที่แตกต่างออกไปได้อย่างง่ายดาย แหล่งที่มาของต้นไม้ทั้งต้น
Adversus

3

นอกจากนี้ยังมีประโยชน์ที่จะมีชื่อที่แตกต่างกันเล็กน้อยสำหรับเอาต์พุตที่เรียกใช้งานได้ คุณไม่สามารถใช้สิ่งที่ต้องการ:

release: Target = ProgramName
debug: Target = ProgramName_d

ทำไมมันไม่ทำงานไม่ชัดเจน แต่มันไม่ได้ แต่:

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

สิ่งนี้ใช้ได้ผลตราบเท่าที่CONFIG +=บรรทัดนำหน้า


1

Qt Creator เวอร์ชันใหม่ยังมีตัวเลือกการสร้าง "โปรไฟล์" ระหว่างการดีบักและการเผยแพร่ นี่คือวิธีที่ฉันตรวจพบ:

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

0

1. ค้นหา Debug / Release ใน CONFIG

รับปัจจุบัน (debug | release)

specified_configs=$$find(CONFIG, "\b(debug|release)\b")
build_subdir=$$last(specified_configs)

(อาจเป็นหลายรายการดังนั้นให้ระบุเฉพาะครั้งสุดท้ายในรุ่น):

2. ตั้งค่า DESTDIR

ใช้มันมีชื่อ subdir build

DESTDIR = $$PWD/build/$$build_subdir

0

นี่คือ Makefile ของฉันสำหรับไดเร็กทอรีเอาต์พุตดีบัก / รีลีสที่แตกต่างกัน Makefile นี้ผ่านการทดสอบบน Ubuntu linux เรียบร้อยแล้ว ควรทำงานบน Windows ได้อย่างราบรื่นหากติดตั้ง Mingw-w64 อย่างถูกต้อง

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$@
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.