Génie civil & structural
Création d'un système de construction multiplateforme pour les projets C utilisant Cmake
Table of Contents
Pour construire des applications C qui compilent et fonctionnent de manière fiable sur Windows, macOS et Linux, il faut plus que du code source portable. Il faut un système de construction qui s'adapte à l'outillage natif de chaque plateforme. CMake, un générateur de système de construction open-source, résout cela en vous permettant de définir votre projet une fois dans un fichier de configuration simple et de produire ensuite des fichiers de construction spécifiques à chaque plateforme (Makefiles, fichiers de solution Visual Studio, projets Xcode, etc.). Cet article fournit un guide complet et pratique pour créer un système de construction multiplateforme pour les projets C avec CMake, couvrant tout, de la configuration de base aux techniques avancées comme la gestion de dépendance, les tests et la compilation croisée.
Qu'est-ce que C Make?
CMake est un système de méta-construction : il ne compile pas directement le code mais génère des fichiers d'entrée pour d'autres systèmes de construction. Vous décrivez votre projet dans des fichiers en utilisant un langage spécifique au domaine. CMake lit ensuite ces fichiers et affiche les instructions de construction appropriées pour la plate-forme cible.
Les principales caractéristiques de CMake sont les suivantes :
- Syntaxe plateform-agnostique: La même fonctionne sur Unix, Windows et macOS.
- Générateurs multiples: Prise en charge Marque, Ninja, Visual Studio, Xcode, et autres.
- Constructions hors source :[ Conserve les artefacts de construction séparés du code source.
- Extensibilité: Les modules, fonctions et macros permettent une logique de construction réutilisable.
- Découverte de paquets:[ localise les bibliothèques et les en-têtes installés.
- L'intégration avec CI/CD:[ fonctionne sans heurts dans les pipelines automatisés.
CMake est devenu le standard de facto pour le développement de plates-formes croisées dans l'écosystème C et C++, utilisé par des projets aussi variés que LLVM, MySQL, et l'ensemble de l'environnement de bureau KDE.
Avantages de l'utilisation de CMake pour le développement de la plateforme C
Adopter le CMake apporte plusieurs avantages concrets au-delà de la portabilité simple:
- Source unique de vérité: Écrire une fois la logique de construction et générer des fichiers pour chaque plate-forme, en éliminant les scripts shell fragiles ou les Makefiles spécifiques à la plate-forme.
- Intégration de l'IDE:[ Les équipes peuvent travailler dans Visual Studio, CLion, Xcode ou VS Code tout en partageant le même .
- Structure du projet modulaire:[ Utiliser pour diviser les grands projets en composantes gérables avec leurs propres dépendances.
- Logique conditionnelle:[ Appliquer des drapeaux, des fichiers sources ou des bibliothèques spécifiques à la plate-forme seulement lorsque cela est nécessaire, sans dupliquer des configurations entières.
- Gestion automatisée des dépendances:[ et simplifient l'utilisation de bibliothèques tierces.
- Test et emballage: CTest et CPack sont étroitement intégrés, ce qui rend trivial d'ajouter des essais et de créer des installateurs.
- Performance de construction: Le générateur Ninja combiné à CCache réduit considérablement les temps de reconstruction.
- Communauté active: Documents officiels et un écosystème prospère de modules et de tutoriels.
Commencer: mettre en place un projet C
Cette section passe par le flux de travail complet de l'installation à un exécutable compilé sur trois grandes plateformes.
1. Installer CMake
Téléchargez le dernier binaire de cmake.org ou utilisez le gestionnaire de paquets de votre système:
- Linux (Debian/Ubuntu):[
- macOS (Homebrew):
- Windows: Exécutez l'installation et assurez-vous que -Ajouter CMake au système PATH--Sélectionne.
Vérifier l'installation avec . La version 3.10 ou supérieure est recommandée pour les fonctionnalités discutées ici.
2. Écrire un minimum de C MakeLists.txt
Créez un fichier nommé dans votre racine de projet. Ci-dessous est un exemple minimal pour un projet C à source unique:
cmake_minimum_required(VERSION 3.10)
project(HelloWorld C)
add_executable(hello main.c)
Ventilation
- définit la version minimum de CMake. Cela permet également des mises à jour de politique qui améliorent le comportement.
- définit le nom et le langage du projet. Spécifier empêche CMake de scanner pour les compilateurs C++.
- dit à CMake que la cible devrait être construite à partir .
Un exemple un peu plus réaliste ajoute des drapeaux compilateurs et une dépendance en-tête seulement:
cmake_minimum_required(VERSION 3.15)
project(Calculator C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
add_executable(calc main.c parser.c)
target_include_directories(calc PRIVATE include)
Ici ajoute au chemin de recherche d'en-tête du compilateur uniquement pour la cible .
3. Générer des fichiers de construction
Créez un répertoire de construction et exécutez CMake:
mkdir build
cd build
cmake ..
Sur Linux/macOS, cela produit un Makefile par défaut. Sur Windows avec Visual Studio installé, il génère un fichier . Pour demander un générateur différent, utilisez .
Après génération, vous pouvez passer les options à la configuration :
cmake .. -DCMAKE_BUILD_TYPE=Release -DMY_FEATURE=ON
Ces variables sont stockées dans et réutilisées lors des opérations suivantes.
4. Construire le projet
Une fois les fichiers de compilation générés, compilez :
- [Fruit sur toutes les plates-formes et tous les générateurs]
- Studio visuel:
- CodeX:
La commande est multiplateforme et évite les invocations spécifiques à la plate-forme. Utilisez pour accélérer les constructions.
Techniques avancées de fabrication pour les projets du monde réel
Au-delà des bases, CMake offre des fonctionnalités qui rationalisent des constructions plus grandes ou plus complexes. Maîtriser ces dernières permettra de gagner du temps et de réduire les erreurs.
Gestion des dépendances avec find package
La commande localise les bibliothèques installées et définit les variables pour leurs chemins et fichiers de bibliothèque inclus. Modern CMake encourage à utiliser des cibles importées pour la propagation de dépendance propre:
find_package(SDL2 REQUIRED)
target_link_libraries(my_app PRIVATE SDL2::SDL2)
Si la bibliothèque ne fournit pas les fichiers de configuration de CMake, vous pouvez avoir besoin d'un module de recherche. Écrivez votre propre logiciel ou comptez sur des logiciels communautaires à cmake-developer.
Pour les dépendances sans installation à l'échelle du système, télécharge et intègre le code source au moment de la configuration:
include(FetchContent)
FetchContent_Declare(
zlib
GIT_REPOSITORY https://github.com/madler/zlib.git
GIT_TAG v1.3
)
FetchContent_MakeAvailable(zlib)
target_link_libraries(my_app PRIVATE zlib)
Cette approche assure des constructions reproductibles en épinglant des versions spécifiques.
Ajouter des essais avec CTest
CMake intègre les tests par CTest. Activez-le et définissez les tests dans votre :
enable_testing()
add_executable(test_parser test_parser.c)
target_link_libraries(test_parser PRIVATE parser_lib)
add_test(NAME ParserTest COMMAND test_parser)
Exécuter des essais avec:
ctest --output-on-failure
Pour des essais plus complets, envisager de combiner avec un cadre d'essai unitaire comme cmocka[ en reliant sa bibliothèque et en utilisant .
Compilation croisée
CMake simplifie la compilation croisée à travers fichiers-chaînes d'outils. Un fichier-chaînes d'outils définit l'architecture du compilateur, du sysroot et de la cible.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_SYSROOT /path/to/sysroot)
Puis invoquez CMake avec la chaîne d'outils:
cmake -DCMAKE_TOOLCHAIN_FILE=arm-cross.cmake ..
CMake utilisera automatiquement le compilateur croisé spécifié et cherchera le sysroot pour les bibliothèques. Cette technique fonctionne pour les systèmes embarqués, les plateformes mobiles et tout scénario où la machine de construction diffère de la machine cible. Se reporter au guide officiel Cross Compiling with CMake pour plus de détails.
Installation et emballage
Utilisez les commandes pour définir comment votre projet devrait être déployé :
install(TARGETS my_app DESTINATION bin)
install(FILES config.ini DESTINATION etc)
CPack génère ensuite des installateurs: DEB, RPM, NSIS, DMG, etc. Ajouter à la fin de votre :
include(CPack)
Exécutez pour produire un paquet Debian. Le package hérite de toutes les règles d'installation et permet la personnalisation via des variables comme .
Pièges communs et pratiques exemplaires
Même les développeurs expérimentés frappent les snags. Voici des problèmes fréquents et comment les éviter:
Piège : chemins de codage rigide
Ne jamais utiliser de chemins absolus dans . Utilisez et par rapport à l'arborescence source. Pour les emplacements des fichiers d'exécution, utilisez pour intégrer des chemins ou compter sur des répertoires d'installation.
Piège : Ignorer les expressions du générateur
Les expressions du générateur () évaluent au moment de la construction, et non pas de la configuration du temps. Elles sont essentielles pour les paramètres de configuration par configuration :
target_compile_definitions(my_app PRIVATE
$<$<CONFIG:Debug>:_DEBUG>
)
Cela ajoute seulement pour les constructions de Debug. Évitez d'utiliser parce que les générateurs multi-config (Visual Studio, Xcode) ne sont pas configurés au moment de la configuration.
Piège : Surutilisation excessive des commandes mondiales
Des commandes comme , et affectent toutes les cibles. Préférez des commandes spécifiques à la cible telles que , et pour une meilleure encapsulation.
Piège : Ne pas utiliser la bonne portée pour trouver package
Avec le CMake moderne, préférez et liez ensuite ses cibles. N'utilisez pas et définissez manuellement des répertoires de liens sauf si cela est absolument nécessaire.
Conclusion
En écrivant un seul ensemble d'instructions de construction, vous obtenez des performances natives, un support IDE et une gestion robuste de la dépendance dans tous les grands systèmes d'exploitation. Commencez par un simple et adoptez progressivement des fonctionnalités avancées – test, compilation croisée, packaging – à mesure que votre projet grandit. L'investissement dans l'apprentissage CMake rapporte chaque fois que vous construisez, testez ou déployez sur une plateforme différente sans réécrire une ligne de code de construction.