71 votes

Comment puis-je passer git SHA1 au compilateur comme définition en utilisant cmake?

Dans un Makefile, cela se ferait avec quelque chose comme:

 g++ -DGIT_SHA1="`git log -1 | head -n 1`" ...
 

Ceci est très utile, car le binaire connaît le commit exact SHA1 pour pouvoir le vider en cas de défaut de segmentation.

Comment puis-je obtenir la même chose avec CMake?

125voto

rpavlik Points 609

J'ai fait quelques CMake modules que les pairs dans un repo git pour la gestion des versions et des fins similaires - ils sont tous dans mon référentiel https://github.com/rpavlik/cmake-modules

La bonne chose à propos de ces fonctions, ils auront la force de re-configurer (une reprise de cmake) avant de construire à chaque fois que la TÊTE de valider les modifications. Contrairement à faire quelque chose de juste une fois avec execute_process, vous n'avez pas besoin d'souvenez-vous de cmake pour mettre à jour la définition de hachage.

Pour ce but précis, vous avez besoin d'au moins l' GetGitRevisionDescription.cmake et GetGitRevisionDescription.cmake.in fichiers. Puis, dans votre principal CMakeLists.txt le fichier, vous auriez quelque chose comme ceci

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/whereYouPutMyModules/")
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1)

Ensuite, vous pouvez soit ajouter un système à l'échelle de définition (qui, malheureusement, serait la cause de beaucoup de la reconstruction)

add_definitions("-DGIT_SHA1=${GIT_SHA1}")

ou, mon alternative suggérée: Faire un fichier source généré. La création de ces deux fichiers dans votre code source:

GitSHA1.rpc.dans:

#define GIT_SHA1 "@GIT_SHA1@"
const char g_GIT_SHA1[] = GIT_SHA1;

GitSHA1.h:

extern const char g_GIT_SHA1[];

Ajoutez ceci à votre CMakeLists.txt (en supposant que vous avez une liste de fichiers source dans les SOURCES):

configure_file("${CMAKE_CURRENT_SOURCE_DIR}/GitSHA1.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp" @ONLY)
list(APPEND SOURCES "${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp" GitSHA1.h)

Ensuite, vous avez une variable globale contenant votre SHA de la chaîne - la-tête avec l'externe ne change pas lorsque le SHA, de sorte que vous pouvez simplement inclure que n'importe quel endroit que vous voulez reportez-vous à la chaîne, et ensuite seulement le CPP produit doit être recompilé à chaque livraison afin de vous donner accès à la SHA partout.

10voto

the Ritz Points 66

J'utiliserais qc. comme ceci dans mon CMakeLists.txt:

 exec_program(
    "git"
    ${CMAKE_CURRENT_SOURCE_DIR}
    ARGS "describe"
    OUTPUT_VARIABLE VERSION )

string( REGEX MATCH "-g.*$" VERSION_SHA1 ${VERSION} )
string( REGEX REPLACE "[-g]" "" VERSION_SHA1 ${VERSION_SHA1} )

add_definitions( -DGIT_SHA1="${VERSION_SHA1}" )
 

4voto

kralyk Points 805

Voici ma solution, je pense que c'est assez court mais efficace ;-)

Tout d'abord, un fichier est nécessaire dans l'arborescence des sources (j'ai le nom de il git-rev.h.in), il ressemble à quelque chose comme ceci:

#define STR_EXPAND(x) #x
#define STR(x) STR_EXPAND(x)
#define GIT_REV STR(GIT_REV_)
#define GIT_REV_ \ 
 

(Veuillez ne jamais l'esprit ces macros, c'est un peu fou truc pour faire une chaîne de valeur brute.) Il est essentiel que ce fichier a exactement un saut de ligne vide à la fin, de sorte que la valeur peut être ajouté.

Et maintenant, ce code va dans respectif CMakeLists.txt le fichier:

# --- Git revision ---
add_dependencies(your_awesome_target gitrev)      #put name of your target here
include_directories(${CMAKE_CURRENT_BINARY_DIR})  #so that the include file is found
set(gitrev_in git-rev.h.in)                       #just filenames, feel free to change them...
set(gitrev git-rev.h)
add_custom_target(gitrev
  ${CMAKE_COMMAND} -E remove -f ${CMAKE_CURRENT_BINARY_DIR}/${gitrev}
  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${gitrev_in} ${CMAKE_CURRENT_BINARY_DIR}/${gitrev}
  COMMAND git rev-parse HEAD >> ${CMAKE_CURRENT_BINARY_DIR}/${gitrev}
  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}         #very important, otherwise git repo might not be found in shadow build
  VERBATIM                                              #portability wanted
)

Cette commande ensuers que l' git-rev.h.in est copié dans l'arbre de construction en tant que git-rev.h et git révision est ajouté à sa fin.

Donc tout ce que vous devez faire est d'inclure git-rev.h dans l'un de vos fichiers et de faire ce que vous voulez avec l' GIT_REV macro, ce qui donne un courant git révision de hachage comme une chaîne de valeur.

La bonne chose à propos de cette solution est que l' git-rev.h est recréée à chaque fois que vous construisez la cible associée, de sorte que vous n'avez pas à exécuter cmake de plus et plus de nouveau.

Il doit également être assez portable - pas de non-externe portable outils ont été utilisés et même de la sanglante stupide windows cmd prend en charge l' > et >> des exploitants ;-)

3voto

Jakub Narębski Points 87537

Je ne peux pas vous aider avec le CMake côté, mais par rapport à Git côté je recommande de prendre un coup d'oeil comment noyau Linux et le projet Git lui-même le fait, via GIT-VERSION-GEN script, ou comment tig t-il dans son Makefile, en utilisant git describe si il y a le dépôt git de présenter, pour retomber à "version" / "VERSION" / "GIT-VERSION-FILE" a généré et qui est présent dans les archives, enfin de revenir à la valeur par défaut codé en dur dans le script (ou Makefile).

La première partie (à l'aide d' git describe) exige que vous les marquer à l'aide de communiqués de annoté (et éventuellement signé avec GPG) des balises. Ou utiliser git describe --tags utiliser aussi léger balises.

1voto

Greg Hewgill Points 356191

Si CMake ne dispose pas d'une capacité intégrée de faire cette substitution, alors vous pourriez écrire un wrapper shell script qui lit un fichier de modèle, succédanés le hash SHA1 comme ci-dessus dans le bon emplacement (à l'aide d' sed, par exemple), crée le réel CMake fichier build, puis appelle CMake pour construire votre projet.

Une approche légèrement différente, pourrait être le SHA1 de substitution en option. Vous devez créer le fichier CMake avec un mannequin valeur de hachage comme "NO_OFFICIAL_SHA1_HASH". Quand aux développeurs de créer leurs propres construit à partir de leur répertoire de travail, le code ne serait pas inclure un hash SHA1 de la valeur (seule la valeur factice), car le code dans le répertoire de travail n'a même pas un correspondant de hachage SHA1 encore de valeur.

D'autre part, lorsqu'un officiel de construire est faite par votre serveur de build, à partir de sources tiré à partir d'un référentiel central, alors vous savez que la valeur de hachage SHA1 pour le code source. À ce stade, vous pouvez remplacer la valeur de hachage dans le CMake fichier puis lancer CMake.

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