Різниця між використанням Makefile та CMake для складання коду


288

Я кодую на C / C ++ і використовую (GNU) Makefile для складання коду. Я можу зробити те ж саме з CMake і отримати MakeFile. Однак яка різниця між використанням Makefile та CMake для компіляції коду?


2
cmake також може створювати файли для використання ніндзя
BЈовић

Відповіді:


403

Make (а точніше Makefile) - це складова система - вона керує компілятором та іншими інструментами побудови для створення вашого коду.

CMake - це генератор будівельних систем. Він може створювати Makefiles, він може створювати файли збирання Ninja, він може створювати проекти KDEvelop або Xcode, він може створювати рішення Visual Studio. З тієї ж відправної точки, той самий файл CMakeLists.txt. Отже, якщо у вас є проект, незалежний від платформи, CMake - це спосіб зробити його незалежним від побудови системи.

Якщо у вас є розробники Windows, які використовували розробники Visual Studio та Unix, які клянуться GNU Make, CMake - це один із способів.

Я завжди рекомендую використовувати CMake (або інший генератор будівельних систем, але CMake - це моє особисте уподобання), якщо ви плануєте, щоб ваш проект був багатоплатформним або широко використовувався. Сам CMake також надає деякі приємні функції, такі як виявлення залежності, управління інтерфейсом бібліотеки або інтеграція з CTest, CDash та CPack.

Використання генератора будівельних систем робить ваш проект більш стійким до майбутнього. Навіть якщо ви зараз GNU-Make-only, що робити, якщо згодом ви вирішите розширитись на інші платформи (будь то Windows чи щось вбудоване) або просто хочете використовувати IDE?


5
@rish Так, це суть. Зауважте, що існує більше способів програмування на Linux, ніж Makefiles - див., Наприклад, QtCreator, KDEvelop, Ninja. Для кожного з них це або "створити проект і тримати його в синхронізації з Makefile", або "повторно запустити CMake". І як згадується у відповіді, CMake також має інші функціональні можливості, як виявлення залежності (наприклад find_package()) або підтримка тестування / упаковки.
Ендже вже не пишається SO

3
Я читав, що CMake не може створювати нерекурсивні файли. Це все-таки правда?
Максим Єгорушкін

1
@Angew Нерекурсивний - це коли один раз викликається повне дерево залежності проекту. На відміну від рекурсивного, коли файл makefile верхнього рівня викликає файли підпроекту в певному порядку.
Максим Єгорушкін

3
Це важлива слабкість CMake - GNU make має свої зморшки, але якщо ви знайдете час, щоб вивчити це, він надзвичайно потужний і універсальний, і працює на величезній кількості платформ. Не маючи повного дерева залежностей для аналізу - головний недолік, просто Google для "рекурсивної роботи вважається шкідливою".
Ерік Алапя

1
@ ErikAlapää я детально прочитаю статтю, але з першого погляду - вони, здається, говорять про рекурсивну форму, де глибина рекурсії керується даними (тобто залежить від глибини каталогів джерела тощо). Це не так у CMake: загальна глибина виклику завжди становить 3, незалежно від структури проекту. Просто деякі біти делегуються підмайстру замість усіх в одному, але це ніяк не відображає структуру проекту. Плюс, субмакелі насправді не є «автономними», тому вони не страждають від проблеми «над / під залежність».
Ендже вже не пишається SO

39

Заява про те, що CMake є "генератором побудови" є поширеною помилковою думкою.

Це технічно неправильно; він просто описує, як це працює, але не те, що робить.

У контексті запитання вони роблять те саме: беруть купу файлів C / C ++ і перетворюють їх у двійкові.

Отже, яка реальна різниця?

  • CMake набагато більш високого рівня. Він призначений для компіляції C ++, для якого ви пишете набагато менше коду збірки, але також може використовуватися для побудови загальних цілей. makeтакож є деякі вбудовані правила C / C ++, але вони здебільшого марні.

  • CMakeробить два етапи складання: він генерує сценарій збірки низкоуровневой в ninjaабо makeабо багатьох інших генераторах, а потім запустити його. Усі фрагменти сценарію оболонки, які зазвичай складаються, Makefileвиконуються лише на етапі генерації. Таким чином, CMakeнарощування може бути на порядок швидше.

  • Граматика CMakeнабагато простіше підтримувати зовнішні інструменти, ніж виготовлення .

  • Одного разу makeбудує артефакт, він забуває, як він був побудований. З яких джерел він був побудований, які прапори компілятора? CMakeвідстежує його, makeзалишає це вам. Якщо одне з джерел бібліотеки було видалено з попередньої версії Makefile, makeне буде відновлено його.

  • Сучасний CMake(починаючи з версії 3. щось) працює в залежності від залежності "цілей". Ціль все ще є одним вихідним файлом (на жаль), але може мати перехідні ("загальнодоступні" / "інтерфейси" в термінах CMake). Ці перехідні залежності можуть бути піддані впливу або заховані від залежних пакетів. CMakeбуде керувати каталогами і для вас. З makeвами ви застрягли у файлі за файлом та керуйте каталогами вручну.

Ви можете щось закодувати, makeвикористовуючи файли прапорів, щоб прикрити останні два прогалини, але ви самостійно. makeмістить повну мову Тьюрінга (навіть дві, іноді три рахунки Гійла ), і всі вони жахливі.

Якщо чесно, ось що CMakeі makeспільне - їхні мови досить жахливі:

  • Вони не мають типів;
  • немає масивів, лише рядки, розділені пробілом, тим самим втече пекло;
  • ви зазвичай передаєте аргументи функціям, встановлюючи глобальні змінні; (це вирішується в сучасному CMake - змінні тепер можуть мати простори імен; ціль - це простір імен для його властивостей)
  • посилання на невизначену змінну за замовчуванням мовчки ігнорується;

щоб почати з.

Але CMakeви пишете набагато менше рядків коду.


1
Тут є хороша інформація, але одне зауваження є абсолютно неправильним: cmake має тип СПИСОК, оскільки при належних функціях СПИСОК, що має вирішальне значення для безлічі завдань системи побудови, невелика різниця: cmake.org/cmake/help/git-master/command /list.html
вирішенняJ

Я б не назвав це "повністю" неправильним, але дякую за виправлення.
Віктор Сергієнко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.