web-dev-qa-db-fra.com

Compiler la date et l'heure en utilisant cmake

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")
15
mathias

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.

5
dbanet

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)

2
Lucas Teske

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"));
0
Orient