Outils pour utilisateurs

Outils du site


prog:cmake

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
prog:cmake [2023/07/26 11:50] – [Cas courants] : ajout de add_library rootprog:cmake [2024/08/30 15:13] (Version actuelle) – Ajout des commandes externes aux targets root
Ligne 2: Ligne 2:
  
 ====Compilation==== ====Compilation====
 +
 +Pré-requis sous Linux
 +
 +''sudo apt-get install libssl-dev''.
 +
 +Compilation
  
 <code bash> <code bash>
Ligne 7: Ligne 13:
 cd cmake cd cmake
 cmake -B build cmake -B build
-cmake --build build +cmake --build build --parallel 16 
-cmake --install build+sudo cmake --install build
 </code> </code>
  
Ligne 20: Ligne 26:
  
 <code bash> <code bash>
 +# Etape de configuration.
 CXXFLAGS="..." cmake -S . -B build -DCMAKE_BUILD_TYPE="Release" CXXFLAGS="..." cmake -S . -B build -DCMAKE_BUILD_TYPE="Release"
 +# Etape de compilation.
 cmake --build build/ --target all --parallel --config "Release" cmake --build build/ --target all --parallel --config "Release"
 </code> </code>
Ligne 31: Ligne 39:
 En compilant pour ''Visual Studio'', ''-DCMAKE_CXX_FLAGS'' écrase la valeur qu'aurait dû générer ''cmake'' (''/DWIN32 /D_WINDOWS /W3 /GR /EHsc'' par défaut). En compilant pour ''Visual Studio'', ''-DCMAKE_CXX_FLAGS'' écrase la valeur qu'aurait dû générer ''cmake'' (''/DWIN32 /D_WINDOWS /W3 /GR /EHsc'' par défaut).
  
-En utilisant ''CXXFLAGS'', les flags sont ajoutés au début (''%%...%% /DWIN32 /D_WINDOWS /W3 /GR /EHsc'').+En utilisant la variable d'environnement ''CXXFLAGS'', les flags sont ajoutés au début (''%%...%% /DWIN32 /D_WINDOWS /W3 /GR /EHsc'').
  
 [[https://stackoverflow.com/questions/44284275/passing-compiler-options-cmake|Passing compiler options cmake]] {{ :prog:cmake:passing_compiler_options_cmake_-_stack_overflow_05_10_2022_11_12_25_.html |Archive du 31/05/2017 le 05/10/2022}} [[https://stackoverflow.com/questions/44284275/passing-compiler-options-cmake|Passing compiler options cmake]] {{ :prog:cmake:passing_compiler_options_cmake_-_stack_overflow_05_10_2022_11_12_25_.html |Archive du 31/05/2017 le 05/10/2022}}
 </WRAP> </WRAP>
  
 +  * Effacer le cache et regénérer les CMakeLists.txt
  
-  * Différences entre les générateurs+Il faut effacer le fichier ''CMakeCache.txt'' et le dossier ''CMakeFiles'' dans le dossier de compilation. Cela permet de conserver les binaires / fichiers objets déjà compilés.
  
-En fonction des générateurs (''Unix Makefiles'' pour Linux et ''Visual Studio 17 2022'' pour Windows), il existe plusieurs types de build (''CMAKE_BUILD_TYPE'') :+  * Différences entre les générateurs
  
-  - Debug +Certaines générateurs (''Unix Makefiles'' et ''Ninja'') ne supportent qu'un seul type de compilation à la fois. Il faut définir le type de compilation avec ''CMAKE_BUILD_TYPE''.
-  - Release +
-  - RelWithDebInfo, +
-  - MinSizeRel+
  
-''Debug'' est évidemment ''Debug'' et les 3 autres sont dans la catégorie ''Release''.+D'autres générateurs (''Visual Studio''''Xcode''''Ninja Multi-Config'') acceptent plusieurs types de compilation. Il faut passer par ''CMAKE_CONFIGURATION_TYPES'' qui vaut par défaut ''Debug;Release;MinSizeRel;RelWithDebInfo''.
  
-''CMAKE_BUILD_TYPE'' doit être passé dans le premier appel au ''cmake -S . -B build''. C'est indispensable pour ''Unix Makefiles'' car le générateur ne supporte qu'un seul type de build à la foisC'est facultatif pour ''Visual Studio XX YYYY'' car il supporte plusieurs configurations à la fois. Cependant, il est quand même conseillé de l'utiliser à chaque fois pour la cohérence.+''CMAKE_BUILD_TYPE'' est indispensable lors de la génération des CMakeLists.txt pour les générateurs mono-build.
  
-''%%--%%config'' doit être passé pour chaque ''%%cmake --build build%%'' pour ''Visual Studio XX YYYY'' mais est facultatif pour ''Unix Makefiles''. Il est aussi conseillé de toujours le spécifier.+''%%--%%config'' est indispensable lors de la compilation pour les générateurs multi-build.
  
 ====Cross compilation pour Android==== ====Cross compilation pour Android====
Ligne 65: Ligne 71:
 </code> </code>
  
-La version de ''CMAKE_SYSTEM_VERSION'' doit correspondre à minSdkVersion du fichier ''build.gradle''.+La version de ''CMAKE_SYSTEM_VERSION'' doit correspondre à ''minSdkVersion'' du fichier ''build.gradle''.
  
 [[https://developer.android.com/ndk/guides/cmake|CMake]] {{ :prog:cmake:cmake_android_ndk_android_developers_26_09_2022_13_53_29_.html |Archive du 25/04/2022 le 26/09/2022}} [[https://developer.android.com/ndk/guides/cmake|CMake]] {{ :prog:cmake:cmake_android_ndk_android_developers_26_09_2022_13_53_29_.html |Archive du 25/04/2022 le 26/09/2022}}
 +
 =====CMakeLists.txt===== =====CMakeLists.txt=====
 ====Cas courants==== ====Cas courants====
 +
 +Voir une version à jour avec tous les commentaires dans [[https://github.com/bansan85/cmake-library/tree/main/library/lib|cmake-library]].
  
 ===add_library=== ===add_library===
Ligne 77: Ligne 86:
 <code cmake> <code cmake>
 add_library(Librairie sources.cpp sources.hpp CMakeLists.txt) add_library(Librairie sources.cpp sources.hpp CMakeLists.txt)
 +add_library(NameSpace::Librairie ALIAS Librairie)
 +set(Librairie_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sources.cpp
 +                  ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
 +set(Librairie_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/sources.h)
 +target_sources(
 +  Librairie
 +  PRIVATE ${Librairie_SRC}
 +  PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/ FILES ${Librairie_HEADER})
 </code> </code>
  
Ligne 93: Ligne 110:
 ''INTERFACE'' : ''Librairie2'' n'est pas nécessaire pour compiler ''Librairie'' mais est nécessaire pour qu'un exécutable puisse se lier à ''Librairie''. Cela est surtout nécessaire pour faire une librairie header-only. ''INTERFACE'' : ''Librairie2'' n'est pas nécessaire pour compiler ''Librairie'' mais est nécessaire pour qu'un exécutable puisse se lier à ''Librairie''. Cela est surtout nécessaire pour faire une librairie header-only.
  
-  * Depuis un binaire+  * Depuis une librairie dynamique précompilée
  
 <code cmake> <code cmake>
Ligne 115: Ligne 132:
  
 ''IMPORTED_IMPLIB'' : uniquement pour Windows et des librairies ''SHARED''. Le fichier ''.dll'' ne contient pas les symboles. Il lui faut donc le ''.lib'' associé. Attention, le fichier ''.lib'' associé au ''.dll'' (''SHARED'') n'est pas le même que le ''.lib'' compilé en ''STATIC''. ''IMPORTED_IMPLIB'' : uniquement pour Windows et des librairies ''SHARED''. Le fichier ''.dll'' ne contient pas les symboles. Il lui faut donc le ''.lib'' associé. Attention, le fichier ''.lib'' associé au ''.dll'' (''SHARED'') n'est pas le même que le ''.lib'' compilé en ''STATIC''.
 +
 ===Librairie header-only=== ===Librairie header-only===
  
-Follow guide:+Suivre les guides :
  
 Exemple sans ''find_package'' : [[http://mariobadr.com/creating-a-header-only-library-with-cmake.html|Creating a header only library with cmake]] {{ :prog:cmake:mario_badr_creating_a_header-only_library_with_cmake_2021-07-11_08_48_29_.html |Archive du 2017 le 11/07/2021}} Exemple sans ''find_package'' : [[http://mariobadr.com/creating-a-header-only-library-with-cmake.html|Creating a header only library with cmake]] {{ :prog:cmake:mario_badr_creating_a_header-only_library_with_cmake_2021-07-11_08_48_29_.html |Archive du 2017 le 11/07/2021}}
Ligne 135: Ligne 153:
  
 ===Activation de l'optimisation global du lieur=== ===Activation de l'optimisation global du lieur===
 +
 Le LTCG (Link Time Code Generation) est identique à l'option lto (Link Time Optimization) de gcc. Le LTCG (Link Time Code Generation) est identique à l'option lto (Link Time Optimization) de gcc.
  
Ligne 162: Ligne 181:
 Ajouter à ''cmake'': Ajouter à ''cmake'':
  
-''-DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_AR=/usr/bin/llvm-ar -DCMAKE_RANLIB=/usr/bin/llvm-ranlib''+<code bash> 
 +-DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_AR=/usr/bin/llvm-ar -DCMAKE_AS=/usr/bin/llvm-as -DCMAKE_RANLIB=/usr/bin/llvm-ranlib -DCMAKE_LINKER_TYPE=LLD 
 +</code> 
 + 
 +  * ''DWARF error: invalid or unhandled FORM value: 0x23'' 
 + 
 +Ne pas spécifier ''CMAKE_LINKER_TYPE'' va entrainer cette erreur. [[https://github.com/llvm/llvm-project/issues/56994| C++17 leads to linker error with ld due to some strange debug info?]] {{ :prog:cmake:c_17_leads_to_linker_error_with_ld_due_to_some_strange_debug_info_issue_56994_llvm_llvm-project_5_31_2024_12_40_25_pm_.html |Archive du 08/08/2022 le 31/05/2024}} 
 + 
 +Sinon, il est aussi possible de mettre l'option de compilation ''-gdwarf-4'' pour les flags ''C'' et ''CXX''.
  
 ===FetchContent=== ===FetchContent===
Ligne 229: Ligne 256:
 </code> </code>
  
-====Cas spécifiques====+====Environnement de compilation et de sortie====
  
-===Exécuter une action qui n'est rattachée à aucun programme/target===+===Environnement de sortie===
  
-Il suffit de passer par une ''target'' intermédiaire.+<code cmake> 
 +if(WIN32) 
 +  set(OS "Windows"
 +elseif(UNIX AND NOT APPLE) 
 +  set(OS "Linux/Unix"
 +elseif(APPLE) 
 +  set(OS "macOS"
 +else() 
 +  set(OS "Unknown"
 +endif() 
 + 
 +if(CMAKE_SIZEOF_VOID_P EQUAL 8) 
 +  set(ARCHITECTURE "64-bit"
 +elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) 
 +  set(ARCHITECTURE "32-bit"
 +else() 
 +  set(ARCHITECTURE "Unknown"
 +endif() 
 +</code> 
 + 
 +====Exécution d'une commande==== 
 + 
 +===En passant par une nouvelle target===
  
 <code cmake> <code cmake>
-# On crée une target qui sera ajoutée à la commande make par défaut. +add_custom_target(clang_fmt ALL COMMAND xxxxxx)
-add_custom_target(clang_fmt ALL+
-# On définir une commande à exécuter. +
-add_custom_command(TARGET clang_fmt COMMAND xxxxxx)+
 </code> </code>
  
-===Exécuter uniquement le préprocesseur===+===Associé une commande à une target existante===
  
-Il faut créer une target compilable en l'excluant de ''all''. Cela va créer des target intermédiaire, notamment ''xxx.cpp.i''. Il suffit alors de l'exécuter explicitement.+  * En passant par une target intermédiaire
  
 <code cmake> <code cmake>
-add_library(file_obj OBJECT EXCLUDE_FROM_ALL file.cpp) +add_custom_target(clang_fmt_dep COMMAND ...) 
-add_custom_target(file ALL COMMAND make file.cpp.i)+ 
 +add_dependencies(clang_fmt clang_fmt_dep)
 </code> </code>
  
-[[http://anadoxin.org/blog/generating-preprocessed-sources-in-cmake-projects.html|Generating preprocessed sources in CMake projects]{{ :prog:cmake:generating_preprocessed_sources_in_cmake_projects_-_antek_s_tech_blog_2020-07-21_18_01_14_.html |Archive du 21/11/2018 le 21/07/2020}}+  * Sans passer par une target intermédiaire 
 + 
 +<code cmake> 
 +add_custom_command(TARGET clang_fmt PRE_BUILD COMMAND ...) 
 +</code> 
 + 
 +  * En passant par un fichier qui sera généré 
 + 
 +<code cmake> 
 +add_custom_command(OUTPUT file COMMAND ...) 
 + 
 +add_dependencies(clang_fmt file) 
 +</code> 
 + 
 +===Spécificité au générateur Visual Studio=== 
 + 
 +Normalement, une commande échoue si elle ne renvoie pas 0. 
 + 
 +Mais Visual Studio va également analyser la sortie standard. Si le contenu de la sortie standard est faussement considéré comme une erreur, il faut rediriger la sortie standard vers NUL. 
 + 
 +<code cmake> 
 +if(CMAKE_GENERATOR MATCHES "Visual Studio"
 +  set(IGNORE_ERROR_IN_LOG ">" "NUL" "2>&1"
 +else() 
 +  set(IGNORE_ERROR_IN_LOG ""
 +endif() 
 + 
 +  add_custom_target(targ COMMAND ... ${IGNORE_ERROR_IN_LOG}) 
 +
 +</code> 
 + 
 +Ce problème peut se produire en lançant la commande `python -m ensurepip` car elle lance la sous-commande `pip install` et cette commande peut générer l'erreur : 
 + 
 +<code> 
 +"...\target.vcxproj" (default target) (5) -
 +(CustomBuild target) ->  
 +  CUSTOMBUILD : error : pip's dependency resolver does not currently take into account all the packages that are installedThis behaviour is the source of the following dependency conflicts. [...\target.vcxproj] 
 +  C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(254,5)error MSB8066Custom build for '...\file.rule;...\target.rule;...\CMakeLists.txt' exited with code -1[...\target.vcxproj] 
 + 
 +    15 Warning(s) 
 +    2 Error(s) 
 +</code>
  
 ===Dépendances dans un sous-dossier=== ===Dépendances dans un sous-dossier===
Ligne 276: Ligne 364:
  
 [[https://gmt.soest.hawaii.edu/boards/2/topics/34|CMake dependencies on subdirectories]] {{ :prog:cmake:cmake_dependencies_on_subdirectories_-_gmt_-_gmt_the_generic_mapping_tools_2019-11-29_20_46_00_.html |Archive du 16/03/2012 le 29/11/2019}} [[https://gmt.soest.hawaii.edu/boards/2/topics/34|CMake dependencies on subdirectories]] {{ :prog:cmake:cmake_dependencies_on_subdirectories_-_gmt_-_gmt_the_generic_mapping_tools_2019-11-29_20_46_00_.html |Archive du 16/03/2012 le 29/11/2019}}
 +
 +====Rustines à appliquer systématiquement====
 +
 +  * ''configure_file''
 +
 +Il faut forcer la configuration si le fichier a été supprimé depuis la configuration initiale de CMake.
 +
 +<code cmake>
 +configure_file(version.h.in version.h)
 +# Need to regenerate version.h if you remove it.
 +# https://gitlab.kitware.com/cmake/cmake/-/issues/18985
 +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
 +    "${CMAKE_CURRENT_BINARY_DIR}/version.h")
 +</code>
  
 ====Déprécié==== ====Déprécié====
Ligne 293: Ligne 395:
   DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-${version})   DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-${version})
 </code> </code>
 +
 +====Divers====
 +
 +===Exécuter uniquement le préprocesseur===
 +
 +Il faut créer une target compilable en l'excluant de ''all''. Cela va créer des target intermédiaire, notamment ''xxx.cpp.i''. Il suffit alors de l'exécuter explicitement.
 +
 +<code cmake>
 +add_library(file_obj OBJECT EXCLUDE_FROM_ALL file.cpp)
 +add_custom_target(file ALL COMMAND make file.cpp.i)
 +</code>
 +
 +[[http://anadoxin.org/blog/generating-preprocessed-sources-in-cmake-projects.html|Generating preprocessed sources in CMake projects]] {{ :prog:cmake:generating_preprocessed_sources_in_cmake_projects_-_antek_s_tech_blog_2020-07-21_18_01_14_.html |Archive du 21/11/2018 le 21/07/2020}}
 +
  
 ====Tests==== ====Tests====
Ligne 366: Ligne 482:
   endif()   endif()
 endforeach() endforeach()
 +</code>
 +
 +Dans le cas de Qt, il va manquer tout l'environnement Qt.
 +
 +Solution Qt 1: copier les dlls comme précédemment et définir une variable d'environnement ''QT_QPA_PLATFORM_PLUGIN_PATH=C:\Qt\5.15.2\msvc2019_64\plugins\platforms''.
 +
 +Solution Qt 2: ajouter tout l'environnement Qt. La définition de la variable ''VCINSTALLDIR'' n'est nécessaire que pour Windows.
 +
 +<code cmake>
 +add_custom_command(
 +  TARGET target
 +  POST_BUILD
 +  COMMAND
 +    ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC
 +    ${WINDEPLOYQT_EXECUTABLE} --qmldir ${CMAKE_CURRENT_SOURCE_DIR} --pdb
 +    "$<TARGET_FILE:target>")
 </code> </code>
  
Ligne 424: Ligne 556:
 [[https://stackoverflow.com/questions/9298278/cmake-print-out-all-accessible-variables-in-a-script|CMake: Print out all accessible variables in a script]] {{ :prog:cmake:cmake_print_out_all_accessible_variables_in_a_script_-_stack_overflow_18_08_2022_14_09_34_.html |Archive du 15/02/2012 le 18/08/2022}} [[https://stackoverflow.com/questions/9298278/cmake-print-out-all-accessible-variables-in-a-script|CMake: Print out all accessible variables in a script]] {{ :prog:cmake:cmake_print_out_all_accessible_variables_in_a_script_-_stack_overflow_18_08_2022_14_09_34_.html |Archive du 15/02/2012 le 18/08/2022}}
  
-  * Afficher toutes les étapes, line par line, d'un run ''CMake''+  * Afficher toutes les étapes, ligne par ligne, d'un run ''CMake'' (configuration uniquement)
  
 Ajouter l'option ''%%--%%trace-expand''. Ajouter l'option ''%%--%%trace-expand''.
 +
 +  * Afficher le temps d'exécution de chaque ligne CMake (configuration uniquement)
 +
 +Ajouter les options ''%%--profiling-format=google-trace --profiling-output=perf.json%%'' et lire via [[https://ui.perfetto.dev/|Perfetto]].
 +
 +{{:prog:cmake:config-perf.png?1685|}}
  
   * Activer l'affichage des lignes de compilation   * Activer l'affichage des lignes de compilation
  
 Ajouter dans le ''CMakeLists.txt'' : ''set(CMAKE_VERBOSE_MAKEFILE ON)''. Ou lancer ''VERBOSE=1 cmake ...'' Ajouter dans le ''CMakeLists.txt'' : ''set(CMAKE_VERBOSE_MAKEFILE ON)''. Ou lancer ''VERBOSE=1 cmake ...''
 +
 +  * Afficher le temps pour chaque compilation pour chaque objet
 +
 +<code cmake>
 +set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time")
 +set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CMAKE_COMMAND} -E time")
 +</code>
 +
 +Ne fonctionne que pour les Makefile et Ninja. Pas avec Visual Studio.
 +
 +Inconvénient : il faut tout compiler sans l'option ''-j''. Sinon, tous les temps affichés sont mélangés.
  
 ====Ninja==== ====Ninja====
prog/cmake.1690365006.txt.gz · Dernière modification : 2023/07/26 11:50 de root