Cmake vs faire des exemples de codes?

Je me demandais s’il y avait un exemple de code pour Makefile ( make ) et CMakeLists.txt ( cmake ) qui font la même chose (la seule différence étant que l’un est écrit dans make et l’autre dans cmake ).

J’ai essayé de chercher “cmake vs make”, mais je n’ai jamais trouvé de comparaison de code. Il serait très utile de comprendre les différences, même pour un cas simple.

Le Makefile suivant crée un exécutable nommé prog partir des sources prog1.c, prog2.c, prog3.c and main.c prog est lié à libmystatlib.a et libmydynlib.so qui sont également construits à partir des sources. De plus, prog utilise la bibliothèque libstuff.a dans stuff/lib et son en-tête dans stuff/include . Le Makefile crée par défaut une cible de publication, mais offre également une cible de débogage:

 #Makefile CC = gcc CPP = g++ RANLIB = ar rcs RELEASE = -c -O3 DEBUG = -c -g -D_DEBUG INCDIR = -I./stuff/include LIBDIR = -L./stuff/lib -L. LIBS = -lstuff -lmystatlib -lmydynlib CFLAGS = $(RELEASE) PROGOBJS = prog1.o prog2.o prog3.o prog: main.o $(PROGOBJS) mystatlib mydynlib $(CC) main.o $(PROGOBJS) $(LIBDIR) $(LIBS) -o prog debug: CFLAGS=$(DEBUG) debug: prog mystatlib: mystatlib.o $(RANLIB) libmystatlib.a mystatlib.o mydynlib: mydynlib.o $(CPP) -shared mydynlib.o -o libmydynlib.so %.o: %.c $(CC) $(CFLAGS) $(INCDIR) $< -o $@ %.o: %.cpp $(CPP) $(CFLAGS) $(INCDIR) -fPIC $< -o $@ 

Voici un CMakeLists.txt qui fait (presque) exactement la même chose, avec quelques commentaires pour souligner les similitudes avec le Makefile:

 #CMakeLists.txt cmake_minimum_required(VERSION 2.8) # stuff not directly project(example) # related to building include_directories(${CMAKE_SOURCE_DIR}/stuff/include) # -I flags for comstackr link_directories(${CMAKE_SOURCE_DIR}/stuff/lib) # -L flags for linker set(PROGSRC prog1.c prog2.c prog3.c) # define variable add_executable(prog main.c ${PROGSRC}) # define executable target prog, specify sources target_link_libraries(prog mystatlib mydynlib stuff) # -l flags for linking prog target add_library(mystatlib STATIC mystatlib.c) # define static library target mystatlib, specify sources add_library(mydynlib SHARED mydynlib.cpp) # define shared library target mydynlib, specify sources #extra flags for linking mydynlib set_target_properties(mydynlib PROPERTIES POSITION_INDEPENDENT_CODE TRUE) #alternatively: #set_target_properties(mydynlib PROPERTIES COMPILE_FLAGS "-fPIC") 

Dans cet exemple simple, les différences les plus importantes sont les suivantes:

  • CMake reconnaît quels compilateurs utiliser pour quel type de source. En outre, il appelle la bonne séquence de commandes pour chaque type de cible. Par conséquent, il n'y a pas de spécification explicite de commandes comme $ (CC) ..., $ (RANLIB) ... et ainsi de suite.

  • Tous les drapeaux habituels du compilateur / éditeur de liens traitant de l'inclusion de fichiers d'en-tête, de bibliothèques, etc. sont remplacés par des commandes indépendantes de la plate-forme / du système de construction.

  • Les indicateurs de débogage sont inclus en définissant la variable CMAKE_BUILD_TYPE sur "Debug" ou en la transmettant à CMake lors de l'appel du programme: cmake -DCMAKE_BUILD_TYPE:STRING=Debug .

  • CMake offre également l'inclusion indépendante de la plate-forme du drapeau '-fPIC' (via la propriété POSITION_INDEPENDENT_CODE) et bien d'autres. Néanmoins, des parameters plus obscurs peuvent être implémentés à la main dans CMake aussi bien que dans un Makefile (en utilisant COMPILE_FLAGS et des propriétés similaires). Bien sûr, CMake commence vraiment à briller lorsque des bibliothèques tierces (comme OpenGL) sont incluses de manière portable.

  • Le processus de construction comporte une étape si vous utilisez un fichier Makefile, à savoir make au niveau de la ligne de commande. Pour CMake, il y a deux étapes: Premièrement, vous devez configurer votre environnement de génération (en tapant cmake dans votre répertoire de construction ou en exécutant un client d'interface graphique). Cela crée un Makefile ou quelque chose d'équivalent, selon le système de construction de votre choix (par exemple, sur Unix ou VC ++ ou MinGW + Msys sur Windows). Le système de génération peut être transmis à CMake en tant que paramètre; Toutefois, CMake fait des choix raisonnables par défaut en fonction de la configuration de votre système. Deuxièmement, vous effectuez la construction réelle dans le système de construction sélectionné.

Les sources et les instructions de compilation sont disponibles sur https://github.com/rhoelzel/make_cmake .

Prenez un logiciel qui utilise CMake comme système de compilation (vous pouvez choisir parmi de nombreux projets opensource). Obtenez le code source et configurez-le à l’aide de CMake. Lisez les fichiers makefiles obtenus et profitez-en.

Une chose à garder à l’esprit est que ces outils ne correspondent pas à un seul. La différence la plus évidente est que CMake parsing les dépendances entre différents fichiers (par exemple, en-tête C et fichiers source), alors que make laisse cela aux auteurs du fichier makefile.

Si cette question concerne un exemple de sortie Makefile du fichier CMakeList.txt , veuillez vérifier les sources cmake-backend et en générer un. Si ce n’est pas le cas, j’ajoute à la réponse de @Roberto que j’essaie de simplifier en cachant les détails.

Fonction CMake

Alors que Make est un outil flexible pour les règles et les recettes, CMake est une couche d’abstraction qui ajoute également la fonctionnalité de configuration.

Mon simple CMakeLists.txt ressemblera à ceci,

 cmake_minimum_required(VERSION 2.8) project(example) file(GLOB testapp_SOURCES *.cc) add_executable(testapp ${testapp_SOURCES}) 

Notez que CMake cache la how la construction peut être effectuée. Nous avons seulement spécifié what sont les entrées et les sorties.

Le CMakeLists.txt contient la liste des appels de fonctions définis par cmake .

(Fonction CMake) Vs Créer des règles

Dans Makefile les rules and recipes sont utilisées à la place des functions . En plus de la function , les rules and recipes offrent un chaînage. Mon Makefile minimaliste ressemblera à ceci,

 -include "executable.mk" TARGETS=testapp.bin all:${TARGETS} 

Alors que l’ executable.mk ressemblera à ceci,

 SOURCES=$(wildcard *.cpp) OBJECTS=$(SOURCES:.cpp=.o) DEPS=$(SOURCES:.cpp=.d) %.bin:$(OBJECTS) $(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LIBS) .PHONY: all clean clean: $(RM) $(OBJECTS) $(DEPS) $(TARGETS) -include $(DEPS) 

À partir de zéro, je commencerai par un Makefile comme celui-ci,

 all: testapp.bin testapp.bin:sourcea.o sourcb.o $(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LIBS) .PHONY: all clean clean: $(RM) $(OBJECTS) testapp.bin 

J’ai obtenu cet extrait et l’ai modifié. Notez que certaines règles implicites sont ajoutées à ce fichier, qui peuvent être trouvées dans la documentation de makefile. Certaines variables implicites sont également pertinentes ici.

Notez que Makefile fournit la recipe détaillée montrant how la construction peut être effectuée. Il est possible d’écrire executable.mk pour conserver les détails définis dans un fichier. De cette façon, le fichier makefile peut être réduit comme je l’ai montré précédemment.

Variables internes dans CMake et Make

Maintenant que nous sums un peu avancés, dans CMake nous pouvons définir un indicateur de compilation comme celui-ci,

 set(CMAKE_C_FLAGS "-Wall") 

Veuillez en savoir plus sur les variables par défaut de CMake dans le fichier CMakeCache.txt . Le code CMake ci-dessus sera équivalent au code Make ci-dessous,

 CFLAGS = -Wall 

Notez que CFLAGS est une variable interne dans Make , de la même manière, CMAKE_C_FLAGS est une variable interne dans CMake .

append include et chemin de bibliothèque dans CMake

Nous pouvons le faire en utilisant cmake fonctions.

 target_include_directories(testapp PRIVATE "myincludes") list(APPEND testapp_LIBRARIES mytest mylibrarypath ) target_link_libraries(testapp ${testapp_LIBRARIES}) 

Vs ajoutant include et chemin de bibliothèque dans Make

Nous pouvons append include et des bibliothèques en ajoutant des lignes comme ci-dessous,

 INCLUDES += -Imyincludes LIBS += -Lmylibrarypath -lmytest 

Notez que les lignes ci-dessus peuvent être générées à partir des outils de génération automatique ou de pkg-config. (mais Makefile ne dépend pas des outils de configuration automatique)

CMake configure / tweek

Normalement, il est possible de générer un fichier config.h comme auto-config outils d’ auto-config en utilisant la fonction configure_file . Il est possible de faire plus de fonctions personnalisées d’écriture de truc. Et enfin, nous pouvons sélectionner une configuration comme celle-ci,

 cmake --build . --config "Release" 

Il est possible d’append une option configurable à l’aide de la fonction d’ option .

Makefile configure / tweak

Si nous avons besoin de le comstackr avec un indicateur de débogage, nous pouvons appeler le make like,

 make CXXFLAGS=NDEBUG 

Je pense que les variables internes, les Makefile-rules et les CMake-functions sont un bon début pour la comparaison, bonne chance avec plus de recherches.