Perbedaan antara menggunakan Makefile dan CMake untuk mengkompilasi kode

288

Saya kode pada C / C ++ dan menggunakan Makefile (GNU) untuk mengkompilasi kode. Saya dapat melakukan hal yang sama dengan CMake dan mendapatkan MakeFile. Namun, apa perbedaan antara menggunakan Makefile dan CMake untuk mengkompilasi kode?

Rish
sumber
2
cmake juga dapat menghasilkan file untuk menggunakan ninja
BЈовић

Jawaban:

403

Make (atau lebih tepatnya Makefile) adalah sistem build - ia menggerakkan kompiler dan alat bantu bangunan lain untuk membangun kode Anda.

CMake adalah generator sistem pembangunan. Dapat menghasilkan Makefiles, dapat menghasilkan file build Ninja, dapat menghasilkan proyek KDEvelop atau Xcode, dapat menghasilkan solusi Visual Studio. Dari titik awal yang sama, file CMakeLists.txt yang sama. Jadi jika Anda memiliki proyek platform-independen, CMake adalah cara untuk membuatnya membangun sistem juga.

Jika Anda memiliki pengembang Windows yang terbiasa dengan pengembang Visual Studio dan Unix yang bersumpah dengan GNU Make, CMake adalah salah satu cara untuk melakukannya.

Saya selalu merekomendasikan menggunakan CMake (atau generator buildsystem lain, tetapi CMake adalah pilihan pribadi saya) jika Anda ingin proyek Anda multi-platform atau dapat digunakan secara luas. CMake sendiri juga menyediakan beberapa fitur bagus seperti deteksi ketergantungan, manajemen antarmuka perpustakaan, atau integrasi dengan CTest, CDash dan CPack.

Menggunakan generator buildsystem membuat proyek Anda lebih tahan masa depan. Bahkan jika Anda hanya GNU-Make-only sekarang, bagaimana jika Anda kemudian memutuskan untuk memperluas ke platform lain (baik itu Windows atau sesuatu yang disematkan), atau hanya ingin menggunakan IDE?

Angew tidak lagi bangga dengan SO
sumber
5
@rish Ya, itulah intinya. Namun perlu dicatat, bahwa ada lebih banyak cara untuk memprogram di Linux daripada Makefiles - lihat misalnya QtCreator, KDEvelop, Ninja. Untuk masing-masing, itu "membuat proyek dan tetap sinkron dengan Makefile," atau "jalankan kembali CMake." Dan, seperti jawaban yang disebutkan, CMake memiliki fungsi lain juga, seperti penemuan ketergantungan (misalnya find_package()) atau dukungan pengujian / pengemasan.
Angew tidak lagi bangga dengan SO
3
Saya membaca bahwa CMake tidak dapat membuat makefile non-rekursif. Apakah itu masih benar?
Maxim Egorushkin
1
@Angew Non-rekursif adalah ketika make dipanggil sekali dengan pohon dependensi proyek lengkap. Berbeda dengan rekursif ketika makefile tingkat atas memanggil makefile sub-proyek dalam urutan tertentu.
Maxim Egorushkin
3
Ini adalah kelemahan penting dari CMake - GNU make memiliki kerutannya, tetapi jika Anda meluangkan waktu untuk mempelajarinya, ia sangat kuat dan serbaguna, dan bekerja pada sejumlah besar platform. Tidak memiliki pohon ketergantungan lengkap untuk dianalisis adalah cacat utama, hanya google untuk 'rekursif yang dianggap berbahaya'.
Erik Alapää
1
@ ErikAlapää Saya akan membaca artikel secara detail, tetapi dari pandangan pertama - mereka sepertinya berbicara tentang rekursif yang membuat kedalaman rekursi didorong oleh data (yaitu tergantung pada kedalaman direktori sumber, dll.). Itu tidak terjadi dengan CMake: kedalaman total doa make selalu 3, terlepas dari struktur proyek. Hanya saja beberapa bit didelegasikan ke submakefile alih-alih semuanya dalam satu, tetapi tidak mencerminkan struktur proyek dengan cara apa pun. Plus, submakefile tidak benar-benar "mandiri", sehingga mereka tidak mengalami masalah ketergantungan yang berlebihan.
Angew tidak lagi bangga dengan SO
39

Pernyataan tentang CMake menjadi "generator pembangkit" adalah kesalahpahaman yang umum.

Secara teknis tidak salah; itu hanya menjelaskan BAGAIMANA cara kerjanya, tetapi tidak APA yang berfungsi.

Dalam konteks pertanyaan, mereka melakukan hal yang sama: mengambil banyak file C / C ++ dan mengubahnya menjadi biner.

Jadi, apa perbedaan sebenarnya?

  • CMake jauh lebih tinggi levelnya. Ini dirancang untuk mengkompilasi C ++, yang mana Anda menulis lebih sedikit kode build, tetapi dapat juga digunakan untuk build tujuan umum. makememiliki beberapa aturan C / C ++ bawaan juga, tetapi kebanyakan tidak berguna.

  • CMakemembangun dua langkah: itu menghasilkan skrip pembangunan tingkat rendah di ninjaatau makeatau banyak generator lainnya, dan kemudian Anda menjalankannya. Semua potongan skrip shell yang biasanya ditumpuk Makefilehanya dieksekusi pada tahap generasi. Dengan demikian, CMakebuild bisa menjadi urutan besarnya lebih cepat.

  • Tata bahasanya CMakejauh lebih mudah untuk mendukung alat eksternal daripada make .

  • Setelah makemembangun artefak, ia lupa bagaimana itu dibangun. Sumber apa itu dibangun, apa bendera kompiler? CMakemelacaknya, makemenyerahkannya kepada Anda. Jika salah satu sumber pustaka dihapus sejak versi sebelumnya Makefile, maketidak akan membangunnya kembali.

  • Modern CMake(dimulai dengan versi 3.something) berfungsi dalam hal ketergantungan antara "target". Target masih berupa file otput tunggal (sayangnya), tetapi dapat memiliki dependensi transitif ("publik" / "antarmuka" dalam istilah CMake). Ketergantungan transitif ini dapat diekspos atau disembunyikan dari paket dependen. CMakeakan mengelola direktori untuk Anda juga. Dengan make, Anda terjebak pada level file per file dan kelola-direktori-dengan-tangan.

Anda bisa membuat kode sesuatu dalam makemenggunakan file flag untuk menutupi dua celah terakhir, tetapi Anda sendiri. makememang mengandung bahasa lengkap Turing (bahkan dua, terkadang tiga menghitung Tipu muslihat ), dan semuanya mengerikan.

Jujur saja, ini adalah kesamaan CMakedan makekesamaan - bahasa mereka cukup mengerikan:

  • Mereka tidak memiliki tipe;
  • tidak ada array, hanya string yang dipisahkan oleh ruang, sehingga lolos dari neraka;
  • Anda biasanya meneruskan argumen ke fungsi dengan mengatur variabel global; (ini sedang ditangani dalam CMake modern - variabel dapat memiliki namespaces sekarang; target adalah namespace untuk propertinya)
  • merujuk ke variabel yang tidak terdefinisi secara diam-diam diabaikan secara default;

memulai dengan.

Tetapi di dalam CMakekamu menulis lebih sedikit baris kode.

Victor Sergienko
sumber
1
Beberapa informasi bagus di sini, tetapi satu komentar sama sekali salah: cmake memiliki tipe LIST karena dengan fungsi LIST yang tepat yang sangat penting untuk banyak tugas sistem bangun, sedikit perbedaan: cmake.org/cmake/help/git-master/command /list.html
troubleshootingJ
Saya tidak akan menyebutnya "sepenuhnya" salah, tetapi terima kasih atas koreksi.
Victor Sergienko