web-dev-qa-db-fra.com

Différence entre utiliser Makefile et CMake pour compiler le code

Je code en C/C++ et utilise un Makefile (GNU) pour compiler le code. Je peux faire la même chose avec CMake et obtenir un MakeFile. Cependant, quelle est la différence entre utiliser Makefile et CMake pour compiler le code?

216
rish

Make (ou plutôt un Makefile) est un système de construction - il pilote le compilateur et d'autres outils de construction pour construire votre code.

CMake est un générateur de systèmes de construction. Il peut produire des Makefiles, des fichiers de construction Ninja, des projets KDEvelop ou XCode, des solutions Visual Studio. À partir du même point de départ, le même fichier CMakeLists.txt. Donc, si vous avez un projet indépendant de la plate-forme, CMake est également un moyen de le rendre indépendant du système de construction.

Si vous avez des développeurs Windows habitués aux développeurs Visual Studio et Unix qui ne jurent que par GNU Make, CMake est (l'un des) moyen (x) à suivre.

Je recommanderais toujours d'utiliser CMake (ou un autre générateur de système de construction, mais CMake est ma préférence personnelle) si vous souhaitez que votre projet soit multi-plateforme ou largement utilisable. CMake lui-même fournit également certaines fonctionnalités de Nice telles que la détection de dépendance, la gestion d'interface de bibliothèque ou l'intégration avec CTest, CDash et CPack.

L'utilisation d'un générateur de système de construction rend votre projet plus évolutif. Même si vous êtes actuellement GNU-Make-only, que se passera-t-il si vous décidez plus tard de développer d'autres plateformes (que ce soit Windows ou quelque chose de plus intégré), ou si vous voulez simplement utiliser un environnement de développement intégré?

317
Angew

L'affirmation selon laquelle CMake est un "générateur de build" est une idée fausse commune.

Ce n'est pas techniquement faux; il décrit simplement COMMENT cela fonctionne, mais pas CE QU'IL fait.

Dans le contexte de la question, ils font la même chose: prendre un tas de fichiers C/C++ et les transformer en binaires.

Alors, quelle est la vraie différence?

  • CMake est beaucoup plus haut niveau. Il est conçu pour compiler C++, pour lequel vous écrivez beaucoup moins de code de construction, mais peut également être utilisé pour une construction générale. make possède également des règles C/C++ intégrées, mais elles sont généralement inutiles.

  • CMake effectue une construction en deux étapes: il génère un script de construction de bas niveau dans ninja ou make ou de nombreux autres générateurs, puis vous l'exécutez. Tous les scripts Shell qui sont normalement empilés dans Makefile ne sont exécutés qu’au stade de la génération. Ainsi, CMake build peut être beaucoup plus rapide.

  • La grammaire de CMake est beaucoup plus facile à supporter pour les outils externes que make .

  • Une fois que make construit un artefact, il oublie comment il a été construit. De quelles sources a-t-il été construit, quels indicateurs du compilateur? CMake le suit, make le laisse à vous. Si l'une des sources de la bibliothèque a été supprimée depuis la version précédente de Makefile, make ne la reconstruira pas.

  • Moderne CMake (à partir de la version 3.quelque chose) fonctionne en termes de dépendances entre "cibles". Une cible est toujours un fichier otput unique (malheureusement), mais peut avoir des dépendances transitives ("public"/"interface" en termes CMake). Ces dépendances transitives peuvent être exposées ou masquées aux packages dépendants. CMake gérera également les répertoires. Avec make, vous êtes bloqué au niveau fichier par fichier et gestion des répertoires à la main.

Vous pouvez coder quelque chose dans make en utilisant des fichiers de drapeaux pour couvrir les deux dernières lacunes, mais vous êtes autonome. make contient un langage complet de Turing (même deux, parfois trois comptant Guile ), et ils sont tous horribles.

Pour être honnête, voici ce que CMake et make ont en commun: leurs langues sont plutôt horribles:

  • Ils n'ont pas de types;
  • pas de tableaux, seulement des chaînes séparées par des espaces, échappant ainsi à l'enfer;
  • vous passez normalement des arguments à des fonctions en définissant des variables globales; (Ceci est abordé dans CMake moderne - les variables peuvent maintenant avoir un espace de nom; une cible est un espace de nom pour ses propriétés)
  • la référence à une variable non définie est ignorée silencieusement par défaut;

commencer avec.

Mais dans CMake vous écrivez beaucoup moins de lignes de code.

12
Victor Sergienko