Solusi yang saya temukan baru-baru ini adalah menggabungkan konsep build out-of-source dengan wrapper Makefile.
Dalam file CMakeLists.txt tingkat atas, saya menyertakan yang berikut untuk mencegah build in-source:
if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} )
message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." )
endif()
Lalu, saya membuat Makefile tingkat atas, dan termasuk yang berikut:
# -----------------------------------------------------------------------------
# CMake project wrapper Makefile ----------------------------------------------
# -----------------------------------------------------------------------------
SHELL := /bin/bash
RM := rm -rf
MKDIR := mkdir -p
all: ./build/Makefile
@ $(MAKE) -C build
./build/Makefile:
@ ($(MKDIR) build > /dev/null)
@ (cd build > /dev/null 2>&1 && cmake ..)
distclean:
@ ($(MKDIR) build > /dev/null)
@ (cd build > /dev/null 2>&1 && cmake .. > /dev/null 2>&1)
@- $(MAKE) --silent -C build clean || true
@- $(RM) ./build/Makefile
@- $(RM) ./build/src
@- $(RM) ./build/test
@- $(RM) ./build/CMake*
@- $(RM) ./build/cmake.*
@- $(RM) ./build/*.cmake
@- $(RM) ./build/*.txt
ifeq ($(findstring distclean,$(MAKECMDGOALS)),)
$(MAKECMDGOALS): ./build/Makefile
@ $(MAKE) -C build $(MAKECMDGOALS)
endif
Target default all
dipanggil dengan mengetik make
, dan memanggil target./build/Makefile
.
Hal pertama yang dilakukan target ./build/Makefile
adalah membuat build
direktori menggunakan $(MKDIR)
, yang merupakan variabel untuk mkdir -p
. Direktori build
adalah tempat kami akan melakukan pembangunan di luar sumber kami. Kami memberikan argumen -p
untuk memastikan bahwa mkdir
tidak berteriak kepada kami untuk mencoba membuat direktori yang mungkin sudah ada.
Hal kedua yang dilakukan target ./build/Makefile
adalah mengubah direktori ke build
direktori dan menjalankannya cmake
.
Kembali ke all
target, kami memohon $(MAKE) -C build
, di mana $(MAKE)
variabel Makefile dihasilkan secara otomatis make
. make -C
mengubah direktori sebelum melakukan apa pun. Karena itu, menggunakan $(MAKE) -C build
sama dengan melakukan cd build; make
.
Untuk meringkas, memanggil pembungkus Makefile ini dengan make all
atau make
setara dengan melakukan:
mkdir build
cd build
cmake ..
make
Target distclean
memanggil cmake ..
, lalu make -C build clean
, dan akhirnya, menghapus semua konten dari build
direktori. Saya percaya ini adalah persis apa yang Anda minta dalam pertanyaan Anda.
Bagian terakhir dari Makefile mengevaluasi apakah target yang disediakan pengguna adalah atau tidak distclean
. Jika tidak, itu akan mengubah direktori build
sebelum memanggilnya. Ini sangat kuat karena pengguna dapat mengetik, misalnya make clean
, dan Makefile akan mengubahnya menjadi setaracd build; make clean
.
Kesimpulannya, pembungkus Makefile ini, dalam kombinasi dengan konfigurasi CMake out-of-source wajib, membuatnya agar pengguna tidak perlu berinteraksi dengan perintah cmake
. Solusi ini juga menyediakan metode yang elegan untuk menghapus semua file output CMake dari build
direktori.
PS Di Makefile, kami menggunakan awalan @
untuk menekan output dari perintah shell, dan awalan @-
untuk mengabaikan kesalahan dari perintah shell. Saat menggunakan rm
sebagai bagian dari distclean
target, perintah akan mengembalikan kesalahan jika file tidak ada (mereka mungkin sudah dihapus menggunakan baris perintah dengan rm -rf build
, atau mereka tidak pernah dihasilkan di tempat pertama). Kesalahan pengembalian ini akan memaksa Makefile kami untuk keluar. Kami menggunakan awalan @-
untuk mencegahnya. Dapat diterima jika file sudah dihapus; kami ingin Makefile kami terus berjalan dan menghapus sisanya.
Hal lain yang perlu diperhatikan: Makefile ini mungkin tidak berfungsi jika Anda menggunakan sejumlah variabel variabel CMake untuk membangun proyek Anda, misalnya cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar"
,. Makefile ini mengasumsikan Anda memanggil CMake dengan cara yang konsisten, baik dengan mengetik cmake ..
atau dengan memberikan cmake
sejumlah argumen yang konsisten (yang dapat Anda sertakan dalam Makefile Anda).
Akhirnya, kredit di mana kredit jatuh tempo. Wrapper Makefile ini diadaptasi dari Makefile yang disediakan oleh Template Proyek Aplikasi C ++ .