2016-07-06 97 views
3

我希望觸發命令輸出更改時發生的CMake配置;具體而言,我正在考慮在配置CMake時從git describe --always --dirty的輸出發生變化時嘗試進行CMake配置。如何在命令輸出更改時觸發CMake

大多數這個問題可以通過觀看HEAD文件和解決symref裏面refs/heads/[branch]和連接這些與configure_file(...)然而,這並不當樹是在異常狀態下(即當有未提交上撿起來解決修改)。在這種情況下,git describe --always --dirty會將-dirty後綴附加到輸出。

當發生這種情況時,沒有對git文件的更改,只有git已經注意到存儲狀態的差異,所以我不能在這裏的任何文件上使用configure_file(...)來讓cmake注意到更改並重新配置。

所以我正在尋找是否有辦法讓cmake運行git命令注意輸出差異並觸發重新配置,幾乎需要類似於預重新配置檢查階段的東西。

不確定這是否可能,如果任何人有任何想法如何可以實現這種行爲?

+0

不要做這種在CMake的本身的東西,因爲這會給你那種一個「雞和蛋」的問題(檢查當文件沒有改變時更改文件)。把它移動到一些調用你的git的shell腳本包裝器,配置和構建步驟。 – Florian

+0

所以我正在尋找這樣做的原因是我可以編譯'git describe'字符串到版本信息中,以確保我確切地知道從哪個git提交它是從_critically_構建的,如果該提交有修改。 我不希望在它上面有一個元構建系統,只是爲了獲得這一小塊功能,如果我能避免它,我不明白爲什麼它應該在雞和雞蛋的情況下結束? – rblk

+1

我不知道如何強制CMake在構建期間重新運行配置。但是,如果您只想更改* version.h *並重新創建與之相關的所有內容,則可以在** build **階段使用'add_custom_target(BuildVersion COMMAND $ {CMAKE_EXECUTABLE} -P )'生成該文件。這在腳本模式下運行CMake,您可以使用通常的'configure_file'命令。進一步'add_dependencies( BuildVersion)'命令將得到保證,如果腳本更改* version.h *文件,則可執行文件將被重建。 – Tsyvarev

回答

0

的問題

的這裏的問題是,「前重新配置檢查階段」是構建環境處理。只有當它的一些輸入文件被改變時纔會調用CMake(因爲CMake已經爲你的構建環境生成規則來跟蹤這些文件是否被更改)。

爲了便於討論,讓我們假設你有這樣的:

execute_process(
    COMMAND ${GIT_EXECUTABLE} describe --always --dirty 
    OUTPUT_VARIABLE _git_file_list 
    OUTPUT_STRIP_TRAILING_WHITESPACE 
) 

configure_file(version.h.in version.h) 

沒有內置的重新配置時,外部命令輸出的變更

我不認爲像「檢查的外部輸出命令作爲預先重新配置步驟「是可能的,而不需要您構建構建過程的附加腳本。

您可以強制CMake每次重新配置通過在實際構建之前調用make rebuild_cache或者通過添加例如add_custom_command(TARGET MyExe POST_BUILD ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/version.h),但每次調用配置過程都是非常耗時的事情。

解決方案

在我的項目中我提出類似上面的代碼到它自己的WriteVersionInfo.cmake腳本:

set(_version_cpp_full_path "${CMAKE_CURRENT_BINARY_DIR}/version.cpp") 
set(_version_obj_full_path "${_version_cpp_full_path}${CMAKE_CXX_OUTPUT_EXTENSION}") 

string(REPLACE " " ";" _compiler_flags_list ${CMAKE_CXX_FLAGS}) 

# Create a dummy output to satisfy dependency check 
if (NOT EXISTS ${_version_obj_full_path}) 
    file(WRITE ${_version_obj_full_path} "") 
endif() 

add_custom_command(
    TARGET MyExe 
    PRE_LINK 
    COMMAND ${CMAKE_COMMAND} -D GIT_EXECUTABLE=${GIT_EXECUTABLE} 
          -D _version_cpp_name=${_version_cpp_full_path} 
          -P ${CMAKE_CURRENT_SOURCE_DIR}/WriteVersionInfo.cmake 
    COMMAND ${CMAKE_CXX_COMPILER} ${_compiler_flags_list} 
            -o ${_version_obj_full_path} 
            -c ${_version_cpp_full_path} 
    VERBATIM 
) 

target_link_libraries(
    MyExe 
    ${_version_obj_full_path} 
) 

在這裏,我直接寫入.cpp文件後,直接把它傳遞給編譯器作爲PRE_LINK的一步。請注意,上述方法不適用於圖書館目標(因爲沒有預先鏈接步驟)。

參考