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 alldipanggil dengan mengetik make, dan memanggil target./build/Makefile .
Hal pertama yang dilakukan target ./build/Makefileadalah membuat builddirektori menggunakan $(MKDIR), yang merupakan variabel untuk mkdir -p. Direktori buildadalah tempat kami akan melakukan pembangunan di luar sumber kami. Kami memberikan argumen -puntuk memastikan bahwa mkdirtidak berteriak kepada kami untuk mencoba membuat direktori yang mungkin sudah ada.
Hal kedua yang dilakukan target ./build/Makefileadalah mengubah direktori ke builddirektori dan menjalankannya cmake.
Kembali ke alltarget, kami memohon $(MAKE) -C build, di mana $(MAKE)variabel Makefile dihasilkan secara otomatis make. make -Cmengubah direktori sebelum melakukan apa pun. Karena itu, menggunakan $(MAKE) -C buildsama dengan melakukan cd build; make.
Untuk meringkas, memanggil pembungkus Makefile ini dengan make allatau makesetara dengan melakukan:
mkdir build
cd build
cmake ..
make
Target distcleanmemanggil cmake .., lalu make -C build clean, dan akhirnya, menghapus semua konten dari builddirektori. 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 buildsebelum 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 builddirektori.
PS Di Makefile, kami menggunakan awalan @untuk menekan output dari perintah shell, dan awalan @-untuk mengabaikan kesalahan dari perintah shell. Saat menggunakan rmsebagai bagian dari distcleantarget, 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 cmakesejumlah 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 ++ .