Je veux utiliser cmake pour définir VERSION sur une version finale en cas de génération de version et sur le temps de compilation autrement.
Lors de l’utilisation des versions de make for development, il était facile d’obtenir le temps de compilation via
-DVERSION=`date +%Y-%m-%d_%H:%M`
qui pourrait être utilisé directement par le code source c/c ++. Malheureusement, je n'ai pas trouvé comment atteindre le même objectif avec cmake.
string(TIMESTAMP VERSION "%Y-%m-%d %H:%M")
add_definitions(-DVERSION="${VERSION}")
définit VERSION à l'heure à laquelle cmake a été exécuté. Comment définir VERSION sur le temps de compilation en utilisant cmake (pour éviter d'avoir à tripoter __DATE__
et __TIME__
en l'absence d'un drapeau RELEASE)?
Pour les versions relativement récentes de CMake (> = 2.8.11):
string(TIMESTAMP {output variable} [{format string}] [UTC])
(voir http://www.cmake.org/cmake/help/v3.0/command/string.html ). Par exemple:
string(TIMESTAMP TODAY "%Y%m%d")
Ma solution multiplateforme lors de la première exécution de CMake crée un fichier timestamp.cmake
dans le répertoire binaire et définit une cible timestamp
qui exécute le fichier généré. Le fichier timestamp.cmake
forme une chaîne d'horodatage ISO 8601 à l'aide de la commande STRING
CMake et l'écrit dans un fichier timestamp.h
avec une directive de préprocesseur #define _TIMEZ_
ajoutée (les définitions avec un trait de soulignement en tête sont acceptables; les définitions avec deux traits de soulignement en tête ne doivent pas être définies par l'utilisateur).
Incluez les éléments suivants dans votre fichier CMake principal.
# build time in UTC ISO 8601
FILE (WRITE ${CMAKE_BINARY_DIR}/timestamp.cmake "STRING(TIMESTAMP TIMEZ UTC)\n")
FILE (APPEND ${CMAKE_BINARY_DIR}/timestamp.cmake "FILE(WRITE timestamp.h \"#ifndef TIMESTAMP_H\\n\")\n")
FILE (APPEND ${CMAKE_BINARY_DIR}/timestamp.cmake "FILE(APPEND timestamp.h \"#define TIMESTAMP_H\\n\\n\")\n")
FILE (APPEND ${CMAKE_BINARY_DIR}/timestamp.cmake "FILE(APPEND timestamp.h \"#define _TIMEZ_ \\\"\${TIMEZ}\\\"\\n\\n\")\n")
FILE (APPEND ${CMAKE_BINARY_DIR}/timestamp.cmake "FILE(APPEND timestamp.h \"#endif // TIMESTAMP_H\\n\")\n")
ADD_CUSTOM_TARGET (
timestamp
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/timestamp.cmake
ADD_DEPENDENCIES ${CMAKE_BINARY_DIR}/timestamp.cmake)
Utilisez ensuite la commande ADD_DEPENDENCIES
CMake pour rendre votre cible principale (probablement le fichier exécutable principal) dépendant de la cible timestamp
. Comme il est toujours considéré comme obsolète par CMake, il est actualisé à chaque fois que la cible principale est reconstruite, ce qui actualise l'heure de construction, comme demandé.
ADD_DEPENDENCIES (${CMAKE_BINARY_DIR}/${BINARY_NAME} timestamp)
Vous pouvez spécifier plusieurs dépendances supplémentaires séparées par un espace blanc avec cette commande, si nécessaire.
Ensuite, vous pouvez simplement #include "timestamp.h"
(en supposant que le répertoire binaire de CMake se trouve dans le chemin d’inclusion, ce qui est généralement le cas. Si ce n’est pas simple: INCLUDE_DIRECTORIES (${CMAKE_BINARY_DIR})
), utilisez _TIMEZ_
chaque fois que vous souhaitez que l’horodatage de construction soit au format ISO 8601 (ou, en fait, ce que vous voudrez: vous pouvez le spécifier vous-même, voir la documentation de CMake pour connaître l'utilisation de la commande STRING
).
Cela aurait pu être simplifié en créant directement (manuellement) le fichier timestamp.cmake
et en l'ajoutant à votre référentiel de code, mais je l'ai considéré comme n'étant pas assez propre. C'est un inconvénient général de CMake. Vous ne pouvez pas accéder à la procédure de formation de chaîne d'horodatage (celle utilisée dans la commande STRING
CMake) à l'étape où le backend de CMake, quel qu'il soit (par exemple, GNU make) s'exécute. il faut donc utiliser un fichier CMake séparé et l'appeler à ce stade. Cela aurait pu être fait beaucoup plus simple et plus propre si vous pouviez appeler la procédure de formation de chaîne d'horodatage CMake dans le "mode de commande CMake" (type d'invocation cmake -E
), par exemple, comme ceci: cmake -E date [format] [UTC]
, mais hélas. J'ai déposé un ticket dans le système de suivi des bogues Mantis de CMake .
Vous pouvez aider cela en soutenant ma demande de fonctionnalité en publiant des commentaires indiquant à quel point vous en avez besoin.
Peut-être pourriez-vous utiliser les macros du compilateur __DATE__
__TIME__
dans votre code au lieu de l'obtenir de cmake. Cela vaut la peine de mentionner que vous devrez nettoyer/créer pour mettre à jour ces valeurs (puisque GCC l’incorpore, si l’objet est déjà compilé, il ne sera pas compilé à nouveau, donc aucune modification de date/heure)
Je me retrouve avec la solution suivante:
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
add_custom_target(
"linktimestamp"
ALL
COMMAND date +'%Y-%m-%d %H:%M:%S' > "linktimestamp.txt"
COMMAND objcopy --input binary --output elf64-x86-64 --binary-architecture i386:x86-64 --rename-section .data=.rodata,CONTENTS,ALLOC,LOAD,READONLY,DATA "linktimestamp.txt" "linktimestamp.o"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMENT "link timestamp: ${LINK_TIMESTAMP}"
)
else()
add_custom_target(
"linktimestamp"
ALL
COMMAND date +'%Y-%m-%d %H:%M:%S' > "linktimestamp.txt"
COMMAND objcopy --input binary --output elf32-i386 --binary-architecture i386 --rename-section .data=.rodata,CONTENTS,ALLOC,LOAD,READONLY,DATA "linktimestamp.txt" "linktimestamp.o"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMENT "link timestamp: ${LINK_TIMESTAMP}"
)
endif()
#add_dependencies(${PROJECT_NAME} "linktimestamp")
target_link_libraries(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/linktimestamp.o")
La cible binaire ${PROJECT_NAME}
est liée à chaque fois à la section mise à jour.
Qt code pour obtenir cet horodatage:
extern char _binary_linktimestamp_txt_start[];
//extern char _binary_linktimestamp_txt_end[];
extern char _binary_linktimestamp_txt_size[];
const auto text = QByteArray::fromRawData(_binary_linktimestamp_txt_start, reinterpret_cast< std::intptr_t >(_binary_linktimestamp_txt_size));
qDebug() << QDateTime::fromString(QString::fromUtf8(text), "yyyy-MM-dd HH:mm:ss\n"));