web-dev-qa-db-ja.com

cmakeを使用して日付と時刻をコンパイルする

Cmakeを使用して、リリースビルドの場合はVERSIONをリリースバージョンに設定し、それ以外の場合はコンパイル時間に設定します。

Makeを開発ビルドに使用する場合、コンパイル時間の取得は簡単でした。

-DVERSION=`date +%Y-%m-%d_%H:%M`

これは、c/c ++ソースコードで直接使用できます。残念ながら、私はcmakeを使用して同じことがどのように達成できるかを知りませんでした。

string(TIMESTAMP VERSION "%Y-%m-%d %H:%M")
add_definitions(-DVERSION="${VERSION}")

cmakeが実行された時刻にVERSIONを設定します。 cmakeを使用するときに、VERSIONをコンパイル時間に設定するにはどうすればよいですか(RELEASEフラグがない場合に__DATE____TIME__をいじる必要がないようにするため)。

CMakeの比較的最近のバージョン(> = 2.8.11)の場合:

string(TIMESTAMP {output variable} [{format string}] [UTC])

http://www.cmake.org/cmake/help/v3.0/command/string.html を参照してください)。例えば:

string(TIMESTAMP TODAY "%Y%m%d")
25
mathias

CMakeの最初の実行時の私のクロスプラットフォームソリューションは、バイナリディレクトリにファイル_timestamp.cmake_を作成し、生成されたファイルを実行するターゲットtimestampを定義します。ファイル_timestamp.cmake_は、STRING CMakeコマンドを使用してISO 8601タイムスタンプ文字列を形成し、_timestamp.h_プリプロセッサディレクティブを前に付けてファイル_#define _TIMEZ__に書き込みます(1つのアンダースコアで定義して問題ありません;定義2つの先行アンダースコアはユーザー定義ではありません)。

メインのCMakeファイルに以下を含めます。

_# 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)
_

次に、_ADD_DEPENDENCIES_ CMakeコマンドを使用して、メインターゲット(おそらくメインの実行可能ファイル)をtimestampターゲットに依存させます。 CMakeでは常に古いと見なされているため、メインターゲットが再構築されるたびに更新され、要求に応じて構築時間が更新されます。

_ADD_DEPENDENCIES (${CMAKE_BINARY_DIR}/${BINARY_NAME} timestamp)
_

必要に応じて、このコマンドで空白で区切られた複数の追加の依存関係を指定できます。

次に、単に_#include "timestamp.h"_(CMakeバイナリdirが通常はインクルードパスにあると想定します。そうでない場合、それは簡単です:INCLUDE_DIRECTORIES (${CMAKE_BINARY_DIR}))、そしていつでも__TIMEZ__を使用できますISO 8601形式のビルドタイムスタンプが必要です(または、実際には、好きなように指定できます STRINGコマンドの使用法については、CMakeのドキュメントを参照してください )。

_timestamp.cmake_ファイルを直接(手動で)作成してコードリポジトリに追加することで、これを簡単にすることができますが、十分にクリーンではないと考えました。 CMakeの一般的な欠点は、CMakeのバックエンドがある段階で、タイムスタンプ文字列形成手順(STRING CMakeコマンドで使用される手順)にアクセスできないことです(たとえば、GNU make)が実行されるので、別のCMakeファイルを使用してその段階で呼び出す必要があります。これは、「CMakeコマンドモード」でCMakeタイムスタンプ文字列形成プロシージャを呼び出すことができれば、はるかに簡単でクリーンになります(_cmake -E_呼び出しのタイプ)たとえば、次のようになります:_cmake -E date [format] [UTC]_ですが、悲しいかな CMakeのMantisバグトラッカーにチケットを提出しました

あなたはそれがどれだけ必要かを示すいくつかのコメントを投稿する私の機能要求をサポートすることによってそれが起こるのを助けることができます。

7
dbanet

コンパイラマクロ__DATE____TIME__ cmakeから取得するのではなく、コード内で。これらの値を更新するにはクリーンアップ/メイクを行う必要があることを言及する価値があります(GCCが埋め込んでいるため、オブジェクトが既にコンパイルされている場合、再度コンパイルされないため、日付/時刻は変更されません)。

2
Lucas Teske

私は次の解決策に終わります:

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

バイナリターゲット${PROJECT_NAME}更新されたセクションと毎回リンクされます。

Qtこのタイムスタンプを取得するコード:

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

私はしばらく前に同じ問題にぶつかり、解決策として this repo と書きました。それをCMakeサブディレクトリとして追加するだけで、build_date_strにプログラムのリンク時間が含まれます。

Stackoverflowの前にgithubがオフラインになる場合、このソリューションのアイデアは次のとおりです。

  1. 上記のソリューションのように、BUILD_TIMEを使用してstring(TIMESTAMP ... CMake変数を作成します。
  2. BUILD_TIMEを記録する小さなライブラリをコンパイルして、プログラムからグローバル変数(印刷できるものなど)に入れます。
  3. そのライブラリのビルドを、cmake -U BUILD_TIMEを使用してCMakeキャッシュから変数を削除するカスタムターゲットに依存させる。

つまり、プロジェクトをビルドするたびに、依存関係がチェックされ、CMakeキャッシュがクリアされ、このタイムスタンプライブラリに対してCMakeが再実行されます。このソリューションの欠点は、CIシステムがある場合、CMakeステップに渡すパラメーターはすべて、ビルドステップにも渡すことを覚えておく必要があることです。

0
user2365669