Sebagai permulaan, ada beberapa nama konvensional untuk direktori yang tidak dapat Anda abaikan, ini didasarkan pada tradisi lama dengan sistem file Unix. Ini adalah:
trunk
├── bin : for all executables (applications)
├── lib : for all other binaries (static and shared libraries (.so or .dll))
├── include : for all header files
├── src : for source files
└── doc : for documentation
Mungkin ide yang baik untuk tetap menggunakan tata letak dasar ini, setidaknya di tingkat atas.
Tentang memisahkan file header dan file sumber (cpp), kedua skema cukup umum. Namun, saya cenderung lebih suka menyimpannya bersama, itu hanya lebih praktis pada tugas sehari-hari untuk memiliki file bersama. Selain itu, jika semua kode berada di bawah satu folder tingkat atas, yaitu trunk/src/
folder, Anda dapat melihat bahwa semua folder lain (bin, lib, include, doc, dan mungkin beberapa folder uji) di tingkat atas, selain direktori "build" untuk build di luar sumber, adalah semua folder yang berisi tidak lebih dari file yang dihasilkan dalam proses build. Dan dengan demikian, hanya folder src yang perlu di-backup, atau lebih baik lagi, disimpan di bawah sistem / server kontrol versi (seperti Git atau SVN).
Dan ketika datang untuk menginstal file header Anda pada sistem tujuan (jika Anda ingin mendistribusikan perpustakaan Anda), CMake memiliki perintah untuk menginstal file (secara implisit membuat target "install", untuk melakukan "make install") yang dapat Anda gunakan untuk meletakkan semua header ke dalam /usr/include/
direktori. Saya hanya menggunakan makro cmake berikut untuk tujuan ini:
# custom macro to register some headers as target for installation:
# setup_headers("/path/to/header/something.h" "/relative/install/path")
macro(setup_headers HEADER_FILES HEADER_PATH)
foreach(CURRENT_HEADER_FILE ${HEADER_FILES})
install(FILES "${SRCROOT}${CURRENT_HEADER_FILE}" DESTINATION "${INCLUDEROOT}${HEADER_PATH}")
endforeach(CURRENT_HEADER_FILE)
endmacro(setup_headers)
Di mana SRCROOT
variabel cmake yang saya setel ke folder src, dan INCLUDEROOT
variabel cmake yang saya konfigurasikan ke mana pun ke header harus pergi. Tentu saja, ada banyak cara lain untuk melakukan ini, dan saya yakin cara saya bukanlah yang terbaik. Intinya, tidak ada alasan untuk membagi header dan sumber hanya karena hanya header yang perlu dipasang di sistem target, karena sangat mudah, terutama dengan CMake (atau CPack), untuk memilih dan mengkonfigurasi header untuk diinstal tanpa harus menyimpannya di direktori terpisah. Dan inilah yang saya lihat di sebagian besar perpustakaan.
Kutipan: Kedua saya ingin menggunakan Kerangka Pengujian Google C ++ untuk pengujian unit kode saya karena tampaknya cukup mudah digunakan. Apakah Anda menyarankan untuk menggabungkannya dengan kode saya, misalnya dalam folder "inc / gtest" atau "contrib / gtest"? Jika digabungkan, apakah Anda menyarankan untuk menggunakan skrip fuse_gtest_files.py untuk mengurangi jumlah atau file, atau membiarkannya apa adanya? Jika tidak digabungkan, bagaimana ketergantungan ini ditangani?
Jangan menggabungkan dependensi dengan perpustakaan Anda. Ini umumnya adalah ide yang sangat buruk, dan saya selalu membencinya ketika saya terjebak mencoba membangun perpustakaan yang melakukan itu. Ini harus menjadi pilihan terakhir Anda, dan waspadalah terhadap jebakan. Seringkali, orang menggabungkan dependensi dengan pustaka mereka baik karena mereka menargetkan lingkungan pengembangan yang buruk (misalnya, Windows), atau karena mereka hanya mendukung versi lama (tidak digunakan lagi) pustaka (ketergantungan) yang dimaksud. Masalah utamanya adalah dependensi yang dibundel Anda mungkin berbenturan dengan versi yang sudah terinstal dari pustaka / aplikasi yang sama (misalnya, Anda memaketkan gtest, tetapi orang yang mencoba membuat pustaka Anda sudah memiliki versi gtest yang lebih baru (atau lebih lama) yang sudah terpasang, lalu keduanya mungkin bentrok dan membuat orang itu sakit kepala parah). Jadi, seperti yang saya katakan, lakukan dengan risiko Anda sendiri, dan saya akan mengatakan hanya sebagai pilihan terakhir. Meminta orang-orang untuk menginstal beberapa dependensi sebelum dapat mengkompilasi perpustakaan Anda adalah kejahatan yang jauh lebih kecil daripada mencoba menyelesaikan bentrokan antara dependensi yang dibundel dan instalasi yang ada.
Kutipan: Dalam hal tes menulis, bagaimana biasanya ini diatur? Saya berpikir untuk memiliki satu file cpp untuk setiap kelas (test_vector3.cpp misalnya) tetapi semua dikompilasi menjadi satu biner sehingga semuanya dapat dijalankan bersama dengan mudah?
Satu file cpp per kelas (atau kelompok kecil kelas dan fungsi kohesif) lebih biasa dan praktis menurut saya. Namun, yang pasti, jangan mengkompilasi semuanya menjadi satu biner hanya agar "semuanya dapat dijalankan bersama". Itu ide yang sangat buruk. Secara umum, ketika datang ke pengkodean, Anda ingin membagi-bagi sebanyak mungkin hal yang masuk akal untuk dilakukan. Dalam kasus pengujian unit, Anda tidak ingin satu biner menjalankan semua pengujian, karena itu berarti bahwa sedikit perubahan apa pun yang Anda buat pada apa pun di perpustakaan Anda kemungkinan besar akan menyebabkan kompilasi ulang hampir total dari program pengujian unit tersebut. , dan itu hanya beberapa menit / jam yang hilang menunggu kompilasi ulang. Tetap berpegang pada skema sederhana: 1 unit = 1 program pengujian unit. Kemudian,
Kutipan: Karena pustaka paling hebat umumnya dibangun menggunakan cmake dan make, saya berpikir masuk akal jika proyek saya juga dibangun seperti ini? Jika saya memutuskan untuk menggunakan tata letak proyek berikut:
Saya lebih suka menyarankan tata letak ini:
trunk
├── bin
├── lib
│ └── project
│ └── libvector3.so
│ └── libvector3.a products of installation / building
├── docs
│ └── Doxyfile
├── include
│ └── project
│ └── vector3.hpp
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
│
├── src
│ └── CMakeLists.txt
│ └── Doxyfile.in
│ └── project part of version-control / source-distribution
│ └── CMakeLists.txt
│ └── vector3.hpp
│ └── vector3.cpp
│ └── test
│ └── test_vector3.cpp
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
│
├── build
└── test working directories for building / testing
└── test_vector3
Beberapa hal yang perlu diperhatikan di sini. Pertama, sub-direktori dari direktori src Anda harus mencerminkan sub-direktori dari direktori include Anda, ini hanya untuk menjaga agar semuanya tetap intuitif (juga, cobalah untuk menjaga struktur sub-direktori Anda tetap datar (dangkal), karena folder bersarang dalam sering kali lebih merepotkan dari apa pun). Kedua, direktori "include" hanyalah direktori instalasi, isinya hanyalah header apa pun yang diambil dari direktori src.
Ketiga, sistem CMake dimaksudkan untuk didistribusikan melalui sub-direktori sumber, bukan sebagai satu file CMakeLists.txt di tingkat atas. Ini membuat segala sesuatunya tetap lokal, dan itu bagus (dengan semangat memecah-belah menjadi beberapa bagian). Jika Anda menambahkan sumber baru, header baru, atau program pengujian baru, yang Anda perlukan hanyalah mengedit satu file CMakeLists.txt kecil dan sederhana di sub-direktori yang dimaksud, tanpa memengaruhi apa pun. Ini juga memungkinkan Anda untuk merestrukturisasi direktori dengan mudah (CMakeList bersifat lokal dan terdapat dalam sub-direktori yang sedang dipindahkan). CMakeList tingkat atas harus berisi sebagian besar konfigurasi tingkat atas, seperti menyiapkan direktori tujuan, perintah khusus (atau makro), dan menemukan paket yang diinstal pada sistem. CMakeList tingkat yang lebih rendah hanya berisi daftar header, sumber,
Kutipan: Bagaimana tampilan CMakeLists.txt sehingga dapat membuat hanya pustaka atau pustaka dan pengujian?
Jawaban dasarnya adalah bahwa CMake memungkinkan Anda mengecualikan target tertentu dari "semua" (yang dibuat saat Anda mengetik "make"), dan Anda juga dapat membuat kumpulan target tertentu. Saya tidak bisa melakukan tutorial CMake di sini, tetapi cukup mudah untuk mengetahuinya sendiri. Namun, dalam kasus khusus ini, solusi yang disarankan adalah, tentu saja, menggunakan CTest, yang hanya merupakan sekumpulan perintah tambahan yang dapat Anda gunakan dalam file CMakeLists untuk mendaftarkan sejumlah target (program) yang ditandai sebagai unit- tes. Jadi, CMake akan menempatkan semua pengujian dalam kategori build khusus, dan itulah yang Anda minta, jadi, masalah terpecahkan.
Kutipan: Saya juga telah melihat beberapa proyek yang memiliki direktori iklan build bin. Apakah build terjadi di direktori build lalu binari dipindahkan ke direktori bin? Apakah binari untuk pengujian dan pustaka berada di tempat yang sama? Atau akan lebih masuk akal untuk menyusunnya sebagai berikut:
Memiliki direktori build di luar source (build "out-of-source") adalah satu-satunya hal yang waras untuk dilakukan, ini adalah standar de facto saat ini. Jadi, tentunya, miliki direktori "build" yang terpisah, di luar direktori source, seperti yang direkomendasikan oleh CMake, dan seperti yang dilakukan oleh setiap programmer yang pernah saya temui. Adapun direktori bin, yah, itu adalah konvensi, dan mungkin ide yang bagus untuk tetap menggunakannya, seperti yang saya katakan di awal posting ini.
Kutipan: Saya juga ingin menggunakan doxygen untuk mendokumentasikan kode saya. Apakah mungkin untuk menjalankan ini secara otomatis dengan cmake and make?
Iya. Ini lebih dari mungkin, itu luar biasa. Tergantung pada seberapa mewah yang ingin Anda dapatkan, ada beberapa kemungkinan. CMake memiliki modul untuk Doxygen (yaitu, find_package(Doxygen)
) yang memungkinkan Anda untuk mendaftarkan target yang akan menjalankan Doxygen pada beberapa file. Jika Anda ingin melakukan hal-hal yang lebih mewah, seperti memperbarui nomor versi di Doxyfile, atau secara otomatis memasukkan tanggal / stempel pengarang untuk file sumber dan sebagainya, itu semua mungkin dengan sedikit kung-fu CMake. Umumnya, melakukan ini akan melibatkan Anda menyimpan sumber Doxyfile (misalnya, "Doxyfile.in" yang saya letakkan di tata letak folder di atas) yang memiliki token untuk ditemukan dan diganti dengan perintah parsing CMake. Di file CMakeLists level atas saya , Anda akan menemukan salah satu bagian dari CMake kung-fu yang melakukan beberapa hal mewah dengan cmake-doxygen bersama-sama.