196 votes

Ajouter automatiquement tous les fichiers d'un dossier à une cible en utilisant CMake ?

J'envisage de faire passer un projet multiplateforme de systèmes de gestion de compilation distincts (Visual C++, XCode et makefiles) à CMake.

Une fonction essentielle dont j'ai besoin est d'ajouter automatiquement tous les fichiers d'un répertoire à une cible. Bien que cela soit facile à faire avec make, ce n'est pas facile à faire avec Visual C++ et XCode (corrigez-moi si je me trompe). Est-il possible de le faire directement dans CMake ? Comment ?

0 votes

Dans Visual Studio, au moins pour les projets C#, il y a un bouton dans la barre d'outils de l'explorateur de projet, appelé "show all files" (montrer tous les fichiers). Il rend visibles tous les sous-répertoires d'un projet, grisés s'ils ne contiennent pas de fichiers logiquement inclus dans le projet. Vous pouvez inclure ces répertoires via le menu contextuel, ce qui inclut tous les fichiers sources qu'ils contiennent, de manière récursive :)

282voto

Kleist Points 3675

Depuis CMake 3.1+, les développeurs décourager fortement les utilisateurs d'utiliser file(GLOB o file(GLOB_RECURSE pour collecter des listes de fichiers sources.

Remarque : Il n'est pas recommandé d'utiliser GLOB pour collecter une liste de fichiers source à partir de votre arborescence. Si aucun fichier CMakeLists.txt n'est modifié lorsqu'une source est ajoutée ou supprimée, le système de compilation généré ne peut pas savoir quand demander à CMake de régénérer. Le drapeau CONFIGURE_DEPENDS peut ne pas fonctionner de manière fiable sur tous les générateurs, ou si un nouveau générateur est ajouté dans le futur qui ne peut pas le supporter, les projets qui l'utilisent seront bloqués. Même si CONFIGURE_DEPENDS fonctionne de manière fiable, il est toujours coûteux d'effectuer la vérification à chaque recompilation.

Voir le documentation ici .

Il y a deux bonnes réponses ( [1] , [2] ) sur SO détaillant les raisons de lister manuellement les fichiers sources.


C'est possible. Par exemple, avec file(GLOB :

cmake_minimum_required(VERSION 2.8)

file(GLOB helloworld_SRC
     "*.h"
     "*.cpp"
)

add_executable(helloworld ${helloworld_SRC})

Notez que cela nécessite manuel ré-exécution de cmake si un fichier source est ajouté ou supprimé, car le système de compilation généré ne sait pas quand demander à CMake de régénérer, et le faire à chaque compilation augmenterait le temps de compilation.

Depuis CMake 3.12, vous pouvez passer l'option CONFIGURE_DEPENDS à file(GLOB pour vérifier et réinitialiser automatiquement les listes de fichiers à chaque fois que la construction est invoquée. Vous devez écrire :

cmake_minimum_required(VERSION 3.12)

file(GLOB helloworld_SRC CONFIGURE_DEPENDS "*.h" "*.cpp")

Cela permet au moins d'éviter de relancer manuellement CMake à chaque fois qu'un fichier est ajouté.

11 votes

Une alternative à la ré-exécution manuelle de cmake est de toucher le fichier CMakeLists.txt avant d'exécuter make.

2 votes

10 votes

>"Nous ne recommandons pas d'utiliser GLOB pour collecter une liste de fichiers sources à partir de votre arbre des sources. Si aucun fichier CMakeLists.txt ne change lorsqu'une source est ajoutée ou supprimée, le système de compilation généré ne peut pas savoir quand demander à CMake de régénérer." Ceci n'est plus recommandé dans la documentation de CMAKE3.7 citée par Hand1Cloud.

34voto

kara deniz Points 585

La réponse de Kleist fonctionne certainement, mais il y a une importante mise en garde :

Lorsque vous écrivez un Makefile manuellement, vous pourriez générer un SRCS à l'aide d'une fonction pour sélectionner toutes les .cpp y .h des dossiers. Si un fichier source est ajouté ultérieurement, la réexécution de la commande make l'inclura.

Cependant, CMake (avec une commande comme file(GLOB ...) ) générera explicitement une liste de fichiers et la placera dans le fichier Makefile . Si vous avez un nouveau fichier source, vous devrez générer à nouveau le fichier Makefile en réexécutant cmake .

edit : il n'est pas nécessaire de supprimer le Makefile.

4 votes

Ne peut-on pas simplement réexécuter cmake, ce qui devrait supprimer/modifier le Makefile obsolète ?

36 votes

Ce n'est pas une réponse, c'est un commentaire sur la réponse de @Kleist.

3 votes

@Neowizard pas dans la terminologie de Stackoverflow.

9voto

Tsyvarev Points 24128

Extension pour @Kleist answer :

Depuis CMake 3.12, l'option supplémentaire CONFIGURE_DEPENDS es soutenu par commandes file(GLOB) y file(GLOB_RECURSE) . Avec cette option, il y a aucun besoin a manuellement réexécuter CMake après l'ajout/la suppression d'un fichier source dans le répertoire - CMake sera réexécuté automatiquement lors de la prochaine compilation du projet.

Toutefois, l'option CONFIGURE_DEPENDS implique que le répertoire correspondant sera revérifié à chaque fois que la construction est demandée, de sorte que construire Le processus consommer plus de temps que sans CONFIGURE_DEPENDS .

Même avec CONFIGURE_DEPENDS disponible La documentation de CMake est encore ne recommande pas en utilisant file(GLOB) o file(GLOB_RECURSE) pour collecter les sources.

0voto

Pour utiliser la hiérarchie des projets Visual Studio dans Clion avec cmake :

cmake_minimum_required(VERSION 3.17)
project(MyProject)

set(CMAKE_CXX_STANDARD 17)

file(GLOB APP_SOURCES */*.cpp)
foreach (testsourcefile ${APP_SOURCES})
    get_filename_component(testname ${testsourcefile} NAME_WLE)
    get_filename_component(dirname ${testsourcefile} DIRECTORY)
    file(GLOB dir_src CONFIGURE_DEPENDS
            "${dirname}/*.h"
            "${dirname}/*.cpp"
            )
    message("${testname}.cpp | ${dir_src}")
    add_executable("${testname}.cpp" ${dir_src})
endforeach (testsourcefile ${APP_SOURCES})

-4voto

alcoforado Points 134

Pourquoi ne pas utiliser powershell pour créer la liste des fichiers sources pour vous. Jetez un coup d'œil à ce script.

param (
    [Parameter(Mandatory=$True)]
    [string]$root 
)

if (-not (Test-Path  -Path $root)) {    
throw "Error directory does not exist"
}

#get the full path of the root
$rootDir = get-item -Path $root
$fp=$rootDir.FullName;

$files = Get-ChildItem -Path $root -Recurse -File | 
         Where-Object { ".cpp",".cxx",".cc",".h" -contains $_.Extension} | 
         Foreach {$_.FullName.replace("${fp}\","").replace("\","/")}

$CMakeExpr = "set(SOURCES "

foreach($file in $files){

    $CMakeExpr+= """$file"" " ;
}
$CMakeExpr+=")"
return $CMakeExpr;

Supposons que vous ayez un dossier avec la structure suivante

C:\Workspace\A
--a.cpp
C:\Workspace\B 
--b.cpp

Enregistrez maintenant ce fichier sous "generateSourceList.ps1" par exemple, et exécutez le script comme suit

~>./generateSourceList.ps1 -root "C:\Workspace" > out.txt

Le fichier out.txt contiendra

set(SOURCE "A/a.cpp" "B/b.cpp")

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X