Разница между использованием Makefile и CMake для компиляции кода
288
Я пишу код на C / C ++ и использую (GNU) Makefile для компиляции кода. Я могу сделать то же самое с CMake и получить MakeFile. Однако в чем разница между использованием Makefile и CMake для компиляции кода?
cmake также может создавать файлы для использования ниндзя
BЈовић
Ответы:
403
Make (точнее, Makefile) - это система сборки - она управляет компилятором и другими инструментами сборки для сборки вашего кода.
CMake - это генератор сборочных систем. Он может создавать Make-файлы, он может создавать файлы сборки 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?
@Rish Да, это суть. Однако обратите внимание, что в Linux существует больше способов программирования, чем в Makefiles - см., Например, QtCreator, KDEvelop, Ninja. Для каждого из них это либо «создать проект и синхронизировать его с Makefile», либо «перезапустить CMake». И, как упоминается в ответе, CMake имеет и другие функции, такие как обнаружение зависимостей (например find_package()) или поддержка тестирования / упаковки.
Angew больше не гордится SO
3
Я читал, что CMake не может создавать нерекурсивные make-файлы. Это все еще правда?
Максим Егорушкин
1
@Angew Нерекурсивный - это когда make вызывается один раз с полным деревом зависимостей проекта. В отличие от рекурсивного, когда make-файл верхнего уровня вызывает make-файлы подпроекта в определенном порядке.
Максим Егорушкин
3
Это важный недостаток CMake - GNU make имеет свои недостатки, но если вы потратите время на его изучение, он чрезвычайно мощный и универсальный и работает на огромном количестве платформ. Отсутствие полного дерева зависимостей для анализа является серьезным недостатком, просто Google для «рекурсивный make считается вредным».
Эрик Алапяя
1
@ ErikAlapää Я прочитаю статью подробно, но с первого взгляда - кажется, они говорят о рекурсивном коде, где глубина рекурсии определяется данными (т.е. зависит от глубины исходного каталога и т. Д.). С CMake это не так: общая глубина вызовов make всегда равна 3, независимо от структуры проекта. Просто некоторые биты делегируются субмаки-файлу вместо всех в одном, но это никак не отражает структуру проекта. Кроме того, субмаке-файлы на самом деле не являются «самодостаточными», поэтому они не страдают от проблемы чрезмерной / недостаточной зависимости.
Angew больше не гордится SO
39
Утверждение о том, что CMake является «генератором сборки», является распространенным заблуждением.
Это не технически неправильно; это просто описывает, КАК это работает, но не ЧТО это делает.
В контексте вопроса они делают одно и то же: берут кучу файлов C / C ++ и превращают их в двоичный файл.
Так в чем же разница?
CMake гораздо более высокого уровня. Он предназначен для компиляции C ++, для которой вы пишете гораздо меньше кода сборки, но также может использоваться для сборки общего назначения. makeтакже есть некоторые встроенные правила C / C ++, но они в основном бесполезны.
CMakeделает два этапа сборку: он генерирует сценарий сборки низкоуровневой в ninjaили makeили многих других генераторах, а затем запустить его. Все части сценариев оболочки, которые обычно складываются, Makefileвыполняются только на этапе генерации. Таким образом, CMakeсборка может быть на несколько порядков быстрее.
Грамматику CMakeгораздо проще поддерживать для внешних инструментов, чем для make .
После того, как makeстроит артефакт, он забывает о том , как он был построен. Из каких источников он был собран, какие флаги компилятора? CMakeотслеживает это, makeоставляет это до вас. Если один из исходных кодов библиотеки был удален с предыдущей версии Makefile, makeне будет перестраивать его.
Modern CMake(начиная с версии 3.something) работает с точки зрения зависимостей между «целями». Целевой объект по-прежнему является единственным файлом otput (к сожалению), но может иметь транзитивные («открытый» / «интерфейс» в терминах CMake) зависимости. Эти транзитивные зависимости могут быть открыты или скрыты от зависимых пакетов. CMakeбудет управлять каталогами для вас тоже. При этом makeвы застряли на уровне файлов за файлом и на уровне управления каталогами вручную.
Вы могли бы что-то кодировать, makeиспользуя файлы флагов, чтобы покрыть последние два пробела, но вы сами по себе. makeсодержит полный язык Тьюринга (даже два, иногда три, считая Guile ), и все они ужасны.
Если честно, это то, что CMakeи makeесть общего - их языки довольно ужасные:
У них нет типов;
нет массивов, только строки, разделенные пробелом, таким образом, выходящий из ада;
вы обычно передаете аргументы в функции, устанавливая глобальные переменные; (это решается в современном CMake - переменные теперь могут иметь пространства имен; цель - это пространство имен для своих свойств)
ссылка на неопределенную переменную по умолчанию игнорируется;
Здесь есть некоторая полезная информация, но одно замечание совершенно неверно: cmake имеет тип LIST, поскольку при наличии правильных функций LIST, которые имеют решающее значение для множества задач системы сборки, есть небольшая разница: cmake.org/cmake/help/git-master/command /list.html
solutionJ
Я бы не назвал это «полностью» неправильным, но спасибо за исправление.
Ответы:
Make (точнее, Makefile) - это система сборки - она управляет компилятором и другими инструментами сборки для сборки вашего кода.
CMake - это генератор сборочных систем. Он может создавать Make-файлы, он может создавать файлы сборки 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?
источник
find_package()
) или поддержка тестирования / упаковки.Утверждение о том, что CMake является «генератором сборки», является распространенным заблуждением.
Это не технически неправильно; это просто описывает, КАК это работает, но не ЧТО это делает.
В контексте вопроса они делают одно и то же: берут кучу файлов C / C ++ и превращают их в двоичный файл.
Так в чем же разница?
CMake гораздо более высокого уровня. Он предназначен для компиляции C ++, для которой вы пишете гораздо меньше кода сборки, но также может использоваться для сборки общего назначения.
make
также есть некоторые встроенные правила C / C ++, но они в основном бесполезны.CMake
делает два этапа сборку: он генерирует сценарий сборки низкоуровневой вninja
илиmake
или многих других генераторах, а затем запустить его. Все части сценариев оболочки, которые обычно складываются,Makefile
выполняются только на этапе генерации. Таким образом,CMake
сборка может быть на несколько порядков быстрее.Грамматику
CMake
гораздо проще поддерживать для внешних инструментов, чем для make .После того, как
make
строит артефакт, он забывает о том , как он был построен. Из каких источников он был собран, какие флаги компилятора?CMake
отслеживает это,make
оставляет это до вас. Если один из исходных кодов библиотеки был удален с предыдущей версииMakefile
,make
не будет перестраивать его.Modern
CMake
(начиная с версии 3.something) работает с точки зрения зависимостей между «целями». Целевой объект по-прежнему является единственным файлом otput (к сожалению), но может иметь транзитивные («открытый» / «интерфейс» в терминах CMake) зависимости. Эти транзитивные зависимости могут быть открыты или скрыты от зависимых пакетов.CMake
будет управлять каталогами для вас тоже. При этомmake
вы застряли на уровне файлов за файлом и на уровне управления каталогами вручную.Вы могли бы что-то кодировать,
make
используя файлы флагов, чтобы покрыть последние два пробела, но вы сами по себе.make
содержит полный язык Тьюринга (даже два, иногда три, считая Guile ), и все они ужасны.Если честно, это то, что
CMake
иmake
есть общего - их языки довольно ужасные:начать с.
Но
CMake
вы пишете гораздо меньше строк кода.источник