Sự khác biệt giữa việc sử dụng Makefile và CMake để biên dịch mã


288

Tôi viết mã trên C / C ++ và sử dụng Makefile (GNU) để biên dịch mã. Tôi có thể làm tương tự với CMake và nhận MakeFile. Tuy nhiên, sự khác biệt giữa việc sử dụng Makefile và CMake để biên dịch mã là gì?


2
cmake cũng có thể tạo các tệp để sử dụng ninja
BЈовић

Câu trả lời:


403

Make (hay đúng hơn là Makefile) là một hệ thống xây dựng - nó điều khiển trình biên dịch và các công cụ xây dựng khác để xây dựng mã của bạn.

CMake là một trình tạo các hệ thống xây dựng. Nó có thể tạo Makefiles, nó có thể tạo các tệp xây dựng Ninja, nó có thể tạo các dự án KDEvelop hoặc Xcode, nó có thể tạo ra các giải pháp Visual Studio. Từ cùng một điểm bắt đầu, cùng một tệp CMakeLists.txt. Vì vậy, nếu bạn có một dự án độc lập với nền tảng, CMake là một cách để làm cho nó xây dựng độc lập với hệ thống.

Nếu bạn có các nhà phát triển Windows đã sử dụng cho Visual Studio và các nhà phát triển Unix, những người thề bằng GNU Make, CMake sẽ là một trong những cách để đi.

Tôi luôn khuyên bạn nên sử dụng CMake (hoặc một trình tạo hệ thống xây dựng khác, nhưng CMake là sở thích cá nhân của tôi) nếu bạn dự định dự án của bạn là đa nền tảng hoặc có thể sử dụng rộng rãi. Bản thân CMake cũng cung cấp một số tính năng hay như phát hiện phụ thuộc, quản lý giao diện thư viện hoặc tích hợp với CTest, CDash và CPack.

Sử dụng một trình tạo hệ thống xây dựng làm cho dự án của bạn có nhiều bằng chứng trong tương lai. Ngay cả khi bây giờ bạn chỉ là GNU-Make, điều gì sẽ xảy ra nếu sau này bạn quyết định mở rộng sang các nền tảng khác (có thể là Windows hoặc một cái gì đó được nhúng) hoặc chỉ muốn sử dụng IDE?


5
@rish Vâng, đó là ý chính. Tuy nhiên, xin lưu ý rằng có nhiều cách để lập trình trên Linux hơn Makefiles - xem ví dụ: QtCreator, KDEvelop, Ninja. Đối với mỗi trong số này, đó là "tạo một dự án và giữ nó đồng bộ với Makefile" hoặc "chạy lại CMake". Và, như câu trả lời đề cập, CMake cũng có chức năng khác, như khám phá phụ thuộc (ví dụ find_package()) hoặc hỗ trợ thử nghiệm / đóng gói.
Angew không còn tự hào về SO

3
Tôi đọc rằng CMake không thể tạo ra các tệp thực hiện không đệ quy. Điều đó có còn đúng không?
Maxim Egorushkin

1
@Angew Không đệ quy là khi make được gọi một lần với cây phụ thuộc dự án hoàn chỉnh. Trái ngược với đệ quy khi một tệp tạo tệp cấp cao nhất gọi các tệp tạo tệp dự án con theo thứ tự nhất định.
Maxim Egorushkin

3
Đây là một điểm yếu quan trọng của CMake - GNU make có các nếp nhăn, nhưng nếu bạn dành thời gian để tìm hiểu nó, nó cực kỳ mạnh mẽ và linh hoạt, và hoạt động trên một số lượng lớn nền tảng. Không có một cây phụ thuộc hoàn toàn để phân tích là một lỗ hổng lớn, chỉ cần google cho 'đệ quy làm cho được coi là có hại'.
Erik Alapää

1
@ ErikAlapää Tôi sẽ đọc bài viết chi tiết, nhưng từ cái nhìn đầu tiên - họ dường như đang nói về đệ quy làm cho độ sâu của đệ quy được điều khiển dữ liệu (nghĩa là phụ thuộc vào độ sâu thư mục nguồn, v.v.). Đó không phải là trường hợp của CMake: tổng chiều sâu của các yêu cầu luôn là 3, bất kể cấu trúc dự án. Chỉ là một số bit được ủy quyền cho một tệp con thay vì tất cả trong một, nhưng nó không phản ánh cấu trúc dự án theo bất kỳ cách nào. Thêm vào đó, các tệp con không thực sự "khép kín", vì vậy chúng không gặp phải vấn đề phụ thuộc quá mức.
Angew không còn tự hào về SO

39

Tuyên bố về CMake là một "trình tạo xây dựng" là một quan niệm sai lầm phổ biến.

Nó không sai về mặt kỹ thuật; nó chỉ mô tả làm thế nào nó hoạt động, nhưng không phải nó làm gì.

Trong bối cảnh của câu hỏi, họ làm điều tương tự: lấy một loạt các tệp C / C ++ và biến chúng thành một tệp nhị phân.

Vì vậy, sự khác biệt thực sự là gì?

  • CMake cao cấp hơn nhiều. Nó được thiết kế để biên dịch C ++, mà bạn viết mã xây dựng ít hơn nhiều, nhưng cũng có thể được sử dụng để xây dựng cho mục đích chung. makecũng có một số quy tắc C / C ++ tích hợp sẵn, nhưng chúng hầu như vô dụng.

  • CMakehiện một hai bước xây dựng: nó tạo ra một mức độ thấp xây dựng kịch bản trong ninjahoặc makehay nhiều máy phát điện khác, và sau đó bạn chạy nó. Tất cả các đoạn script shell thường được xếp chồng lên nhau Makefilechỉ được thực hiện ở giai đoạn tạo. Do đó, CMakexây dựng có thể là đơn đặt hàng cường độ nhanh hơn.

  • Ngữ pháp của CMakeviệc hỗ trợ các công cụ bên ngoài dễ dàng hơn nhiều so với thực hiện .

  • Sau khi makexây dựng một vật phẩm, nó quên đi cách nó được xây dựng. Những nguồn nó được xây dựng từ, những gì trình biên dịch cờ? CMaketheo dõi nó, makeđể lại cho bạn Nếu một trong các nguồn thư viện bị xóa kể từ phiên bản trước Makefile, makesẽ không xây dựng lại.

  • Hiện đại CMake(bắt đầu với phiên bản 3. một cái gì đó) hoạt động về mặt phụ thuộc giữa "mục tiêu". Một mục tiêu vẫn là một tệp otput duy nhất (đáng buồn), nhưng có thể có các phụ thuộc bắc cầu ("công khai" / "trong các điều khoản CMake). Những phụ thuộc quá độ này có thể được tiếp xúc hoặc ẩn khỏi các gói phụ thuộc. CMakesẽ quản lý thư mục cho bạn quá. Với make, bạn bị mắc kẹt ở cấp độ từng tệp và quản lý thư mục.

Bạn có thể mã hóa một cái gì đó makebằng cách sử dụng các tệp cờ để che hai khoảng trống cuối cùng, nhưng bạn chỉ có một mình. makekhông chứa một ngôn ngữ hoàn chỉnh Turing (thậm chí hai, đôi khi ba Guile đếm ), và tất cả chúng đều kinh khủng.

Thành thật mà nói, đây là những gì CMakemakecó điểm chung - ngôn ngữ của họ khá kinh khủng:

  • Họ không có loại;
  • không có mảng, chỉ có các chuỗi ngăn cách không gian, do đó thoát khỏi địa ngục;
  • bạn thường chuyển các đối số cho các hàm bằng cách đặt các biến toàn cục; (điều này đang được xử lý trong CMake hiện đại - các biến có thể có một không gian tên ngay bây giờ; một mục tiêu là một không gian tên cho các thuộc tính của nó)
  • tham chiếu đến một biến không xác định được âm thầm bỏ qua theo mặc định;

để bắt đầu với.

Nhưng trong CMakebạn viết ít dòng mã hơn nhiều.


1
Một số thông tin tốt ở đây, nhưng một nhận xét là hoàn toàn sai: cmake có loại LIST vì với các chức năng LIST phù hợp rất quan trọng đối với nhiều tác vụ của hệ thống xây dựng, một chút khác biệt: cmake.org/cmake/help/git-master/command /list.html
giải quyếtJ

Tôi sẽ không gọi nó là "hoàn toàn" sai, nhưng cảm ơn vì đã sửa chữa.
Victor Sergienko
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.