J'essaie d'utiliser add_custom_command pour générer un fichier pendant la construction. La commande n'a jamais semblé être exécutée, j'ai donc créé ce fichier de test.
cmake_minimum_required( VERSION 2.6 )
add_custom_command(
OUTPUT hello.txt
COMMAND touch hello.txt
DEPENDS hello.txt
)
J'ai essayé de courir:
cmake .
make
Et hello.txt n'a pas été généré. Qu'est ce que j'ai mal fait?
Ajoutez ce qui suit:
add_custom_target(run ALL
DEPENDS hello.txt)
Si vous connaissez les makefiles, cela signifie:
all: run
run: hello.txt
La solution add_custom_target(run ALL ...
Fonctionnera pour les cas simples lorsque vous n'avez qu'une seule cible que vous construisez, mais tombe en panne lorsque vous avez plusieurs cibles de premier niveau, par exemple application et tests.
J'ai rencontré ce même problème lorsque j'essayais de regrouper certains fichiers de données de test dans un fichier objet afin que mes tests unitaires ne dépendent d'aucun élément externe. Je l'ai résolu en utilisant add_custom_command
Et une magie de dépendance supplémentaire avec set_property
.
add_custom_command(
OUTPUT testData.cpp
COMMAND reswrap
ARGS testData.src > testData.cpp
DEPENDS testData.src
)
set_property(SOURCE unit-tests.cpp APPEND PROPERTY OBJECT_DEPENDS testData.cpp)
add_executable(app main.cpp)
add_executable(tests unit-tests.cpp)
Alors maintenant, testData.cpp sera généré avant que unit-tests.cpp ne soit compilé, et chaque fois que testData.src change. Si la commande que vous appelez est vraiment lente, vous obtenez le bonus supplémentaire que lorsque vous créez uniquement la cible de l'application, vous n'aurez pas à attendre que cette commande (dont seul l'exécutable des tests ait besoin) se termine.
Ce n'est pas montré ci-dessus, mais une application soigneuse de ${PROJECT_BINARY_DIR}, ${PROJECT_SOURCE_DIR} and include_directories()
gardera votre arbre source propre des fichiers générés.
Le problème avec deux réponses existantes est qu'elles rendent la dépendance globale (add_custom_target(name ALL ...)
) ou l'affectent à un fichier unique spécifique (set_property(...)
) qui devient désagréable si vous en avez plusieurs les fichiers qui en ont besoin comme dépendance. Au lieu de cela, ce que nous voulons, c'est une cible que nous pouvons faire une dépendance d'une autre cible.
Pour ce faire, utilisez add_custom_command
Pour définir la règle, puis add_custom_target
Pour définir une nouvelle cible basée sur cette règle. Ensuite, vous pouvez ajouter cette cible en tant que dépendance d'une autre cible via add_dependencies
.
# this defines the build rule for some_file
add_custom_command(
OUTPUT some_file
COMMAND ...
)
# create a target that includes some_file, this gives us a name that we can use later
add_custom_target(
some_target
DEPENDS some_file
)
# then let's suppose we're creating a library
add_library(some_library some_other_file.c)
# we can add the target as a dependency, and it will affect only this library
add_dependencies(some_library some_target)
Les avantages de cette approche:
some_target
N'est pas une dépendance pour ALL
, ce qui signifie que vous ne le construisez que lorsqu'il est requis par une cible spécifique. (Alors que add_custom_target(name ALL ...)
le construirait inconditionnellement pour toutes les cibles.)some_target
Est une dépendance pour la bibliothèque dans son ensemble, il sera construit avant tous les fichiers de cette bibliothèque. Cela signifie que s'il y a beaucoup de fichiers dans la bibliothèque, nous n'avons pas à faire set_property
Sur chacun d'entre eux.DEPENDS
à add_custom_command
, Il ne sera reconstruit que lorsque ses entrées changeront. (Comparez cela à l'approche qui utilise add_custom_target(name ALL ...)
où la commande est exécutée sur chaque build, qu'elle en ait besoin ou non.)Pour plus d'informations sur les raisons pour lesquelles les choses fonctionnent de cette façon, consultez cet article de blog: https://samthursfield.wordpress.com/2015/11/21/cmake-dependencies-between-targets-and-files-and-custom -commandes /