Cara menentukan direktori keluaran Debug / Rilis yang berbeda di file QMake .pro

106

Saya memiliki proyek Qt dan saya ingin mengeluarkan file kompilasi di luar pohon sumber.

Saat ini saya memiliki struktur direktori berikut:

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

Bergantung pada konfigurasinya (debug / rilis), saya ingin mengeluarkan file yang dihasilkan di dalam direktori build di bawah direktori build / debug atau build / release.

Bagaimana saya bisa melakukannya menggunakan file .pro?

Etienne Savard
sumber
Cara Qt memperlakukan debug dan rilis build berubah secara internal seiring waktu. Jadi kami menemukan bahwa peralihan kerja sebelumnya antara debug dan rilis rusak di versi yang lebih baru. Lihat solusi saya yang berfungsi di semua platform dan di semua versi Qt hingga saat ini. stackoverflow.com/questions/32046181/…
adlag
2
Karena ini adalah pertanyaan lama, ada baiknya menunjukkan bahwa ada jawaban yang lebih baik dengan suara yang jauh lebih sedikit.
wardw

Jawaban:

5

Jawaban singkatnya adalah: Anda tidak .

Anda harus menjalankannya qmakedengan diikuti makedi direktori build apa pun yang ingin Anda buat. Jadi, jalankan sekali dalam debugdirektori, sekali dalam releasedirektori.

Begitulah cara setiap orang yang membangun proyek Anda mengharapkannya untuk bekerja, dan begitulah Qt itu sendiri diatur untuk dibangun, itu juga bagaimana Qt Creator mengharapkan .profile Anda berperilaku: itu hanya dimulai qmakedan kemudian makedi folder build untuk konfigurasi yang dipilih target Anda.

Jika Anda ingin membuat folder ini dan menjalankan dua (atau lebih) build di dalamnya, Anda memerlukan makefile tingkat atas, yang mungkin dibuat dari file proyek tingkat atas melalui qmake.

Tidak jarang memiliki lebih dari dua konfigurasi build, jadi Anda tidak perlu berkomitmen untuk hanya membedakan antara build dan rilis; Anda mungkin memiliki build dengan tingkat pengoptimalan yang berbeda, dll . Dikotomi debug / rilis sebaiknya dibiarkan tenang.

Kembalikan Monica
sumber
151

Untuk proyek Qt saya, saya menggunakan skema ini di file * .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

Sederhana, tapi bagus! :)

mosg
sumber
18
Hanya yang saya butuhkan! Dan catatan: Untuk membuat sesuatu yang lebih mudah untuk beralih di sekitar, hanya mendefinisikan Anda DESTDIRs kondisional, dan kemudian menggunakan nilai bahwa dalam semua jalur lain: OBJECTS_DIR = $${DESTDIR}/.obj. Bersulang!
Xavier Holt
4
Pikiran menjelaskan bagaimana ini digunakan / apa fungsinya? Tampaknya tidak berpengaruh saat saya menerapkannya. edit: jika saya mengubah Debug menjadi debug (huruf kecil) itu berhasil. Saya menduga ini adalah masalah sensitivitas kasus windows vs unix.
notlesh
9
Saya memilihnya karena berfungsi di Windows. Di Linux (Ubuntu 15.04, Qt 5.5.0) saya harus mengubah Debugke debugdan Releaseke release.
Jepessen
Wth? Begitu banyak untuk lintas platform? @Jepretan ??
Nils
2
Ini hanya berfungsi jika Anda hanya memiliki rilis atau debug di CONFIG. Jika keduanya dalam konfigurasi, yang terakhir akan digunakan.
weeska
52

Untuk mengubah direktori target dll / exe, gunakan ini di file pro Anda:

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

Anda mungkin juga ingin mengubah direktori untuk target build lain seperti file objek dan file moc (periksa referensi variabel qmake untuk mengetahui detailnya atau referensi fungsi qmake CONFIG () ).

chalup
sumber
5
Tapi saya merasa jauh lebih baik untuk memasukkan $$ OUT_PWD dalam hal ini, jadi DESTDIR = $$ OUT_PWD / debug
Ivo
1
@Ivo: Ah! Terima kasih! Saya telah mencari di mana-mana variabel mana yang berisi jalur itu! : D
Cameron
1
Setelah ini, Anda dapat menambahkan baris seperti: OBJECTS_DIR = $$DESTDIR/.obj MOC_DIR = $$DESTDIR/.moc RCC_DIR = $$DESTDIR/.qrc UI_DIR = $$DESTDIR/.ui CONFIG()ternyata untuk menyelesaikan beberapa masalah penggunaan release:dandebug:
Carson Ip
Yang ini bekerja lebih baik daripada jawaban yang dipilih. Yang dipilih berfungsi, tetapi jika debug dan rilis dikonfigurasi, blok setelan kedua tetap ada.
Paulo Carvalho
42

Saya memiliki pendekatan yang lebih ringkas:

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

OBJECTS_DIR = $$DESTDIR/.obj
MOC_DIR = $$DESTDIR/.moc
RCC_DIR = $$DESTDIR/.qrc
UI_DIR = $$DESTDIR/.ui
Halo W.
sumber
2
Jawaban Anda adalah cara yang lebih baru untuk meletakkan output build compiler di direktori terpisah.
SIFE
1
Sudahkah Anda mencoba ini baru-baru ini untuk debug dan rilis? keluaran build saya sepertinya selalu berakhir di folder rilis, apa pun konfigurasinya; qmake / Qt Perilaku Pencipta mungkin telah berubah sejak Anda memposting jawaban ini ...
ssc
1
Coba tambahkan "CONFIG - = debug" ke argumen tambahan qmake dalam mode Rilis
Halo W
17

Cara yang benar untuk melakukan ini adalah sebagai berikut (terima kasih Tim Dukungan 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

Info lebih lanjut di sini: 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_.3

ABCplus
sumber
13

Saya menggunakan metode yang sama yang disarankan oleh 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"
}
Sulla
sumber
12

Pertanyaan lama, tapi tetap bernilai jawaban terkini. Saat ini adalah hal umum untuk melakukan apa yang dilakukan Qt Creator ketika shadow build digunakan (mereka diaktifkan secara default saat membuka proyek baru).

Untuk setiap target dan jenis build yang berbeda, hak qmaketersebut dijalankan dengan argumen yang benar dalam direktori build yang berbeda. Maka itu baru dibangun dengan sederhana make.

Jadi, struktur direktori imajiner mungkin terlihat seperti ini.

/
|_/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

Dan yang terpenting adalah, a qmakedijalankan di direktori build:

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

Kemudian itu menghasilkan makefiles di direktori build, dan kemudian makeakan menghasilkan file di bawahnya juga. Tidak ada risiko tercampurnya versi yang berbeda, selama qmake tidak pernah berjalan di direktori sumber (jika ya, lebih baik bersihkan dengan baik!).

Dan ketika dilakukan seperti ini, .profile dari jawaban yang diterima saat ini bahkan lebih sederhana:

HEADERS += src/dialogs.h
SOURCES += src/main.cpp \
           src/dialogs.cpp
hyde
sumber
Berfungsi dengan baik untuk satu proyek, tetapi bagaimana jika Anda memiliki proyek dan perpustakaan? Maka Anda memerlukan cara yang bergantung pada buildtype untuk menyertakan afaics library.
Adversus
@Adversus Saya tidak yakin apa sebenarnya yang Anda maksud, tetapi mungkin variabel Qmake $(OUT_PWD)adalah solusi?
hyde
Ketika saya menerapkan pertanyaan saya ke contoh Anda, itu menjadi: apa cara terbersih untuk mengambil aplikasi mylib? Saya ingin jika ada cara yang "anggun" untuk melakukan ini, saya tidak melihat cara lain selain menggunakan teknik dari jawaban lain: gunakan tipe build dan konfigurasi untuk mengisi LIBSdengan cara yang cerdas, meniadakan keuntungan dari shadow build.
Adversus
@Adversus Jika mylib adalah proyek subdir di bawah proyek tingkat atas yang sama, saya biasanya akan menambahkan file mylib.pri, dan meletakkan semua yang dibutuhkan proyek subdir lainnya di sana, menggunakan variabel Qmake untuk selalu mendapatkan jalur yang benar, bahkan jika itu adalah pembuatan bayangan. Kemudian file subdir .pro lainnya akan memilikiinclude(../mylib/mylib.pri)
hyde
terima kasih, itulah yang saya lakukan sekarang, akan lebih baik jika memiliki solusi di mana ini diurus secara otomatis, seperti ketika Anda memiliki proyek dengan subproyek di cmake dan kemudian dapat dengan mudah membuat perbedaan dari- sumber membangun seluruh pohon.
Adversus
3

Ini juga berguna untuk memiliki nama yang sedikit berbeda untuk keluaran yang dapat dieksekusi. Anda tidak dapat menggunakan sesuatu seperti:

release: Target = ProgramName
debug: Target = ProgramName_d

Mengapa itu tidak berhasil tidak jelas, tetapi tidak. Tapi:

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

Ini bekerja selama CONFIG +=garis sebelumnya.

Steve Besch
sumber
1

Versi baru Qt Creator juga memiliki opsi build "profil" antara debug dan rilis. Inilah cara saya mendeteksinya:

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

1. Temukan Debug / Rilis di CONFIG

Dapatkan arus (debug | rilis).

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

(Mungkin banyak, jadi pertahankan hanya yang terakhir ditentukan dalam build):

2. Atur DESTDIR

Gunakan itu memiliki nama subdir build

DESTDIR = $$PWD/build/$$build_subdir
automorfik
sumber
0

Ini adalah Makefile saya untuk direktori keluaran debug / rilis yang berbeda. Makefile ini telah berhasil diuji di Ubuntu linux. Ini harus bekerja dengan lancar di Windows asalkan Mingw-w64 diinstal dengan benar.

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$@
Ahmed Rashed
sumber