Selama pengembangan, saya suka mengubah kompiler, mode build, versi ketergantungan, melakukan analisis statis, mengukur kinerja, mengumpulkan cakupan, membuat dokumentasi, dll. Dan saya sangat menyukai CMake karena memungkinkan saya melakukan apa pun yang saya inginkan.
Banyak orang mengkritik CMake, dan seringkali memang sepantasnya demikian, namun jika Anda melihatnya, tidak semuanya begitu buruk, dan baru-baru ini tidak buruk sama sekali, dan arah pengembangannya cukup positif.
Dalam catatan ini, saya ingin memberi tahu Anda cara mengatur pustaka header di C++ di sistem CMake untuk mendapatkan fungsionalitas berikut:
Perakitan;
Tes jalan otomatis;
Pengukuran cakupan kode;
Instalasi;
Dokumentasi otomatis;
Pembuatan kotak pasir online;
Analisis statis.
Siapapun yang sudah paham kelebihan dan C-make bisa langsung saja unduh templat proyek dan mulai menggunakannya.
Kami terutama akan berbicara tentang cara mengatur skrip CMake, sehingga akan dibahas secara detail. Siapapun dapat melihat sisa file secara langsung di halaman proyek templat.
Pertama-tama, Anda perlu meminta versi sistem CMake yang diperlukan. CMake terus berkembang, tanda tangan perintah, dan perilaku dalam kondisi berbeda pun berubah. Agar CMake segera memahami apa yang kita inginkan darinya, kita perlu segera mencatat persyaratan kita terhadapnya.
cmake_minimum_required(VERSION 3.13)
Kemudian kami akan menentukan proyek kami, namanya, versi, bahasa yang digunakan, dll. (lihat. ΠΊΠΎΠΌΠ°Π½Π΄Ρ project).
Dalam hal ini kami menunjukkan bahasanya CXX (dan ini berarti C++) sehingga CMake tidak tegang dan mencari kompiler bahasa C (secara default, CMake menyertakan dua bahasa: C dan C++).
project(Mylib VERSION 1.0 LANGUAGES CXX)
Di sini Anda dapat langsung memeriksa apakah proyek kita termasuk dalam proyek lain sebagai subproyek. Ini akan sangat membantu di masa depan.
Opsi pertama adalah MYLIB_TESTING β untuk menonaktifkan pengujian unit. Ini mungkin diperlukan jika kami yakin semuanya beres dengan pengujian, tetapi kami hanya ingin, misalnya, menginstal atau mengemas proyek kami. Atau proyek kami disertakan sebagai subproyek - dalam hal ini, pengguna proyek kami tidak tertarik untuk menjalankan pengujian kami. Anda tidak menguji dependensi yang Anda gunakan, bukan?
Selain itu, kami akan membuat opsi terpisah MYLIB_COVERAGE untuk mengukur cakupan kode melalui pengujian, namun memerlukan alat tambahan, sehingga perlu diaktifkan secara eksplisit.
Tentu saja, kami adalah programmer yang keren plus, jadi kami menginginkan tingkat diagnostik waktu kompilasi yang maksimal dari compiler. Tidak ada seekor tikus pun yang lolos.
Library kami hanya terdiri dari file header saja, artinya kami tidak memiliki exhaust apapun berupa library statis maupun dinamis. Di sisi lain, untuk menggunakan perpustakaan kami secara eksternal, perpustakaan tersebut perlu diinstal, harus dapat dideteksi di sistem dan terhubung ke proyek Anda, dan pada saat yang sama header yang sama, serta mungkin beberapa header tambahan, melekat padanya properti.
Untuk tujuan ini, kami membuat perpustakaan antarmuka.
add_library(mylib INTERFACE)
Kami mengikat header ke perpustakaan antarmuka kami.
Penggunaan CMake yang modern, modis, dan awet muda menyiratkan bahwa header, properti, dll. ditransmisikan melalui satu sasaran tunggal. Jadi cukuplah untuk mengatakannya target_link_libraries(target PRIVATE dependency), dan semua header yang terkait dengan target dependency, akan tersedia untuk sumber milik target target. Dan Anda tidak membutuhkannya [target_]include_directories. Hal ini akan ditunjukkan di bawah dalam analisis Skrip CMake untuk pengujian unit.
Perintah ini mengaitkan header yang kita butuhkan dengan perpustakaan antarmuka kita, dan jika perpustakaan kita terhubung ke target mana pun dalam hierarki CMake yang sama, maka header dari direktori akan dikaitkan dengannya ${CMAKE_CURRENT_SOURCE_DIR}/include, dan jika perpustakaan kita diinstal pada sistem dan terhubung ke proyek lain menggunakan perintah find_package, maka header dari direktori akan dikaitkan dengannya include relatif terhadap direktori instalasi.
Mari kita tetapkan standar bahasa. Tentu saja yang terakhir. Pada saat yang sama, kami tidak hanya menyertakan standar tersebut, tetapi juga memperluasnya kepada mereka yang akan menggunakan perpustakaan kami. Hal ini dicapai karena properti himpunan memiliki kategori INTERFACE (Lihat. perintah target_compile_features).
Mari buat alias untuk perpustakaan kita. Apalagi untuk kecantikan akan berada di βnamespaceβ khusus. Ini akan berguna ketika modul yang berbeda muncul di perpustakaan kita, dan kita akan menghubungkannya secara independen satu sama lain. Seperti di Busta misalnya.
Memasang header kami ke dalam sistem. Semuanya sederhana di sini. Kami mengatakan bahwa folder dengan semua header harus masuk ke direktori include relatif terhadap lokasi pemasangan.
Selanjutnya, kami memberi tahu sistem build bahwa kami ingin dapat memanggil perintah di proyek pihak ketiga find_package(Mylib) dan mendapatkan gol Mylib::mylib.
Mantra selanjutnya harus dipahami seperti ini. Saat berada di proyek pihak ketiga kami memanggil perintah find_package(Mylib 1.2.3 REQUIRED), dan versi sebenarnya dari perpustakaan yang diinstal tidak akan kompatibel dengan versi tersebut 1.2.3CMake secara otomatis akan menghasilkan kesalahan. Artinya, Anda tidak perlu melacak versi secara manual.
Jika tes dinonaktifkan secara eksplisit menggunakan pilihan yang sesuai atau proyek kita adalah subproyek, yaitu terhubung ke proyek CMake lain menggunakan perintah add_subdirectory, kami tidak bergerak lebih jauh dalam hierarki, dan skrip yang menjelaskan perintah untuk membuat dan menjalankan pengujian tidak berjalan.
Pertama-tama, kami menemukan paket dengan kerangka pengujian yang diperlukan (ganti dengan yang favorit Anda).
find_package(doctest 2.3.3 REQUIRED)
Mari buat file yang dapat dieksekusi dengan tes. Biasanya saya menambahkan langsung ke biner yang dapat dieksekusi hanya file yang berisi fungsi tersebut main.
add_executable(mylib-unit-tests test_main.cpp)
Dan saya menambahkan file yang tesnya sendiri akan dijelaskan nanti. Tapi Anda tidak perlu melakukan itu.
Kami menghubungkan dependensi. Harap dicatat bahwa kami hanya menautkan target CMake yang kami perlukan ke biner kami dan tidak memanggil perintah target_include_directories. Judul dari kerangka pengujian dan dari kami Mylib::mylib, serta parameter build (dalam kasus kami, ini adalah standar bahasa C++) yang berhasil mencapai tujuan ini.
Terakhir, kami membuat target dummy, yang "build"-nya setara dengan menjalankan pengujian, dan menambahkan target ini ke build default (atribut bertanggung jawab untuk ini ALL). Ini berarti bahwa build default memicu pengujian untuk dijalankan, yang berarti kita tidak akan pernah lupa untuk menjalankannya.
add_custom_target(check ALL COMMAND mylib-unit-tests)
Selanjutnya, kami mengaktifkan pengukuran cakupan kode jika opsi yang sesuai ditentukan. Saya tidak akan menjelaskan secara detail, karena ini lebih berkaitan dengan alat untuk mengukur cakupan dibandingkan dengan CMake. Penting untuk dicatat bahwa berdasarkan hasil akan tercipta gol coverage, yang memudahkan untuk mulai mengukur cakupan.
Selanjutnya, kami memeriksa apakah pengguna telah menyetel variabel bahasa. Jika ya, maka kami tidak menyentuhnya, jika tidak, kami mengambil bahasa Rusia. Kemudian kita konfigurasikan file sistem Doxygen. Semua variabel yang diperlukan, termasuk bahasa, ada di sana selama proses konfigurasi (lihat. ΠΊΠΎΠΌΠ°Π½Π΄Ρ configure_file).
Lalu kita membuat tujuan doc, yang akan mulai menghasilkan dokumentasi. Karena menghasilkan dokumentasi bukanlah kebutuhan terbesar dalam proses pengembangan, target tidak akan diaktifkan secara default; target harus diluncurkan secara eksplisit.
if (Doxygen_FOUND)
if (NOT MYLIB_DOXYGEN_LANGUAGE)
set(MYLIB_DOXYGEN_LANGUAGE Russian)
endif()
message(STATUS "Doxygen documentation will be generated in ${MYLIB_DOXYGEN_LANGUAGE}")
configure_file(Doxyfile.in Doxyfile)
add_custom_target(doc COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
endif ()
Di sini kita menemukan Python ketiga dan membuat target wandbox, yang menghasilkan permintaan yang sesuai dengan API layanan Kotak tongkat, dan menyuruhnya pergi. Responsnya dilengkapi dengan tautan ke kotak pasir yang sudah selesai.
Memberikan kemampuan untuk menonaktifkan build dan target pengujian unit check. Akibatnya, pengukuran cakupan kode dengan pengujian dimatikan (lihat. MYLIB_COVERAGE).
Pengujian juga secara otomatis dinonaktifkan jika proyek terhubung ke proyek lain sebagai subproyek menggunakan perintah add_subdirectory.
Layanan ini digunakan untuk ini Kotak tongkat. Saya tidak tahu seberapa fleksibel server mereka, tapi menurut saya peluang ini tidak boleh disalahgunakan.
Faktanya, CMake versi 3.13 hanya diperlukan untuk menjalankan beberapa perintah konsol yang dijelaskan dalam bantuan ini. Dari sudut pandang sintaksis skrip CMake, versi 3.8 sudah cukup jika pembangkitan dipanggil dengan cara lain.
Setelah ini, analisis statis akan diluncurkan secara otomatis setiap kali sumber dikompilasi dan dikompilasi ulang. Tidak perlu melakukan apa pun tambahan.
Dentang
Dengan bantuan alat yang luar biasa scan-build Anda juga dapat menjalankan analisis statis dalam waktu singkat:
CMake adalah sistem yang sangat kuat dan fleksibel yang memungkinkan Anda menerapkan fungsionalitas untuk setiap selera dan warna. Dan, meskipun sintaksisnya terkadang meninggalkan banyak hal yang diinginkan, iblis tetap tidak seburuk yang dilukiskannya. Gunakan sistem build CMake untuk kepentingan masyarakat dan kesehatan.