2016-07-06 8 views
3

Ich möchte eine CMake-Konfiguration auslösen, wenn die Ausgabe eines Befehls geändert wird. Speziell versuche ich, CMake konfigurieren zu lassen, wenn sich die Ausgabe von git describe --always --dirty gegenüber der vorherigen Konfiguration von CMake geändert hat.Wie eine CMake-Rekonfigurierung ausgelöst wird, wenn sich die Ausgabe eines Befehls ändert

kann die meisten dieses Problem durch die Beobachtung der HEAD Datei und die Lösung des SYMREF innen refs/heads/[branch] und deren Verknüpfung mit configure_file(...) jedoch gelöst werden, dies auf nicht abholen, wenn der Baum in einem schmutzigen Zustand ist (IE, wenn es nicht gebundenen ist Änderungen). In diesem Fall fügt git describe --always --dirty das Suffix -dirty an den Ausgang an.

In diesem Fall gibt es keine Änderungen an den Git-Dateien, nur dass git Unterschiede aus dem gespeicherten Zustand festgestellt hat, so kann ich nicht auf Dateien hier cmake, um die Änderung zu bemerken und neu zu konfigurieren.

Also ich bin auf der Suche, ob es eine Möglichkeit gibt, cmake zu bekommen, um den Befehl git den Unterschied in der Ausgabe zu beachten und eine Rekonfiguration auszulösen, fast so etwas wie eine Phase vor der Rekonfiguration zu benötigen.

Nicht sicher, ob dies möglich ist, wenn jemand Ideen hat, wie sonst dieses Verhalten erreicht werden kann?

+0

diese Art von Sachen in CMake selbst nicht tun, denn das würde Ihnen eine Art "Huhn-und-Ei" -Problem (Prüfung auf Dateien geändert, wenn keine Dateien geändert wurden). Verschieben Sie es einfach in einen Shell-Skript-Wrapper, der Ihren Git aufruft, konfiguriert und erstellt Schritte. – Florian

+0

Der Grund dafür ist, dass ich den 'git describe' String in die Versionsinformationen kompilieren kann, um sicherzustellen, dass ich genau weiß, aus welchem ​​Commit er erstellt wurde und _crittic_, wenn es Änderungen von diesem Commit gibt. Ich möchte kein Meta-Build-System darüber haben, nur um ein kleines Stück Funktionalität zu bekommen, wenn ich es vermeiden kann und ich sehe nicht, warum es in einer Hühner- und Eissituation enden sollte? – rblk

+1

Ich weiß nicht, wie CMake gezwungen wird, configure während des Builds erneut auszuführen. Aber wenn Sie nur * version.h * ändern und alles davon abhängig machen wollen, können Sie diese Datei auf der Stufe ** build ** mit etwas wie add_custom_target (BuildVersion COMMAND $ {CMAKE_EXECUTABLE} -P ) erzeugen. Dadurch wird CMake im Skriptmodus ausgeführt, in dem Sie den üblichen Befehl 'configure_file' verwenden können. Mit dem Befehl 'add_dependencies ( BuildVersion)' wird sichergestellt, dass die ausführbare Datei neu erstellt wird, wenn das Skript die * version.h * -Datei ändert. – Tsyvarev

Antwort

0

Das Problem

Das Problem hierbei ist, dass der "pre-recon-Check stage" von Ihrer Build-Umgebung behandelt wird. CMake wird nur aufgerufen, wenn einige seiner Eingabedateien geändert werden (weil CMake Regeln für Ihre Buildumgebung generiert hat, um zu verfolgen, ob diese Dateien geändert werden).

Für diese Diskussion nehmen wir an, Sie haben so etwas wie:

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

configure_file(version.h.in version.h) 

Nein Errichten-In neu konfigurieren, wenn der externe Befehlsausgabe Änderungen

Ich glaube nicht so etwas wie „die Überprüfung der Ausgabe von externen Befehl als Pre-Reconfigure-Schritt "ist ohne ein zusätzliches Skript möglich, das Sie in Ihrem Build-Prozess verwenden.

Sie könnten CMake zwingen, jedes Mal neu zu konfigurieren, z. indem Sie make rebuild_cache vor Ihrem tatsächlichen Build anrufen oder indem Sie z. add_custom_command(TARGET MyExe POST_BUILD ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/version.h), aber den Konfigurationsprozess jedes Mal aufzurufen ist sehr zeitaufwendig.

Lösung

In meiner Projekte, die ich so etwas wie der Code oben bewegt haben, in seine eigene WriteVersionInfo.cmake Skript:

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

Hier bin ich direkt auf eine .cpp Datei zu schreiben und geben sie direkt an der Compiler als PRE_LINK Schritt. Bitte beachten Sie, dass der obige Ansatz für Bibliotheksziele nicht funktioniert (weil es keinen Pre-Link-Schritt gibt).

Referenzen