2017-01-01 5 views
-1

In einem CMake-Projekt verwende ich Git-Tags für Versionsnummern. Mit dem Ansatz von https://github.com/iPenguin/version_git kann ich die Versionsnummer in den Quellcode bekommen (das heißt, dass CMake eine version.cpp-Datei mit einer const-Zeichenfolge erstellt, die die Versionsnummer enthält, die ich dann in meinen C++ - Quellcodes verwenden kann). Das Problem besteht darin, dass ich beim Erstellen eines Quellpakets mit CPack das .git-Verzeichnis ausschließt und beim Kompilieren der aus dem Paket extrahierten Quellen die Versionsnummer nicht verfügbar ist.Wie wird die Versionsnummer von einem Git-Tag in das CPack-generierte Quellpaket übertragen?

Wie CPack die Versionsnummer in das Quellpaket legen?

Ich habe folgende Anforderungen:

  1. Ich will nicht das Build-Verzeichnis in meinem Source-Paket enthalten sein. Es ist wichtig zu beachten, dass ich out-of-source-Builds von einem Verzeichnis unter dem Projektstamm aus führe. Das heißt, wenn meine Toplevel CMakeLists.txt im Verzeichnis my_project ist, dann führe ich "cmake .." und "make" im Verzeichnis my_project/build aus.

  2. Ich möchte das .git-Verzeichnis nicht in mein Quellpaket aufnehmen.

  3. Ich möchte, dass alle von cmake erzeugten Dateien und "make package_source" innerhalb des Build-Verzeichnisses liegen. Außerdem möchte ich nicht, dass cmake Dateien außerhalb des Build-Verzeichnisses ändert oder löscht.

  4. Ich möchte nicht undokumentiertes Verhalten von cmake und cpack verwenden, insbesondere die Pfade, die von cpack verwendet werden.

Bisher war ich nicht in der Lage, eine Lösung zu finden, die alle meine Anforderungen erfüllen würde. Hier ist, was ich versucht habe:

Ich lassen CMake erstellen eine Datei VersionForSourcePackage.cmake, die, wenn später von cmake aufgenommen wird, wird die Variable VERSION. Dann möchte ich diese Datei in das Quellpaket einfügen, so dass, wenn cmake im extrahierten Paket ausgeführt wird, die VERSION-Variable gesetzt wird. Diese Datei wird unter dem Build-Verzeichnis erstellt, aber ich weiß nicht, wie CPack es richtig in die Quellpakete kopieren kann.

Die erste Möglichkeit ist eine leichte Modifikation von https://github.com/iPenguin/version_git, aber es genügt meine Anforderung Nummer 4. Volles Beispiel nicht bei https://github.com/josefcibulka/version_git ist.

Beim Erstellen von Repository, bekomme ich die Versionsnummer von git und speichern Sie es in $ {PROJECT_BINARY_DIR} /versionForSourcePackage.cmake. Dann verwende ich CPACK_INSTALL_COMMANDS, damit CPack diese Datei nach $ {PROJECT_BINARY_DIR}/_ CPack_Packages/Linux-Quelle/$ {CPACK_SOURCE_GENERATOR}/$ {CPACK_SOURCE_PACKAGE_FILE_NAME}/kopieren kann, damit sie im Paket enthalten ist. Dies verletzt die Anforderungsnummer 4 und außerdem, wenn ich in Zukunft sowohl TGZ- als auch ZIP-Pakete erstellen möchte, muss ich einige Änderungen vornehmen. Gibt es eine Variable, die ich in CPACK_INSTALL_COMMANDS verwenden könnte, um den Pfad zu dem Verzeichnis zu erhalten, in dem CPack den Inhalt des Pakets vorbereitet?

CMakeLists.txt wie folgt aussieht:

cmake_minimum_required(VERSION 2.8) 

project("version_from_git") 

# Appends the cmake/modules path to MAKE_MODULE_PATH variable. 
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH}) 

# When in the extracted package, use the previously generated file, otherwise get the current version from git. 
if(EXISTS "${PROJECT_SOURCE_DIR}/versionForSourcePackage.cmake") 
    include("${PROJECT_SOURCE_DIR}/versionForSourcePackage.cmake") 
else() 
    include(GetGitRevisionDescription) 
    git_describe(VERSION --tags --dirty=-dirty) 
endif() 

# Parse the version information into pieces. 
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION}") 
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION}") 
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VERSION}") 
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+(.*)" "\\1" VERSION_SHA1 "${VERSION}") 
set(VERSION_SHORT "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") 

set(CPACK_SOURCE_GENERATOR "TGZ") 
set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}") 
set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}") 
set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}") 
# The following will copy the version file to the source package. 
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION_SHORT}-Source") 
set(CPACK_INSTALL_COMMANDS "${CMAKE_COMMAND} -E make_directory \ 
    ${PROJECT_BINARY_DIR}/_CPack_Packages/Linux-Source/${CPACK_SOURCE_GENERATOR}/${CPACK_SOURCE_PACKAGE_FILE_NAME}/" 
    "${CMAKE_COMMAND} -E copy \ 
    ${PROJECT_BINARY_DIR}/versionForSourcePackage.cmake \ 
    ${PROJECT_BINARY_DIR}/_CPack_Packages/Linux-Source/${CPACK_SOURCE_GENERATOR}/${CPACK_SOURCE_PACKAGE_FILE_NAME}/") 
# Exclude the build and .git directory from the source package. 
set(CPACK_SOURCE_IGNORE_FILES "${PROJECT_SOURCE_DIR}/.git/;${PROJECT_BINARY_DIR}/;${CPACK_SOURCE_IGNORE_FILES}") 

include (CPack) 

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/version.cpp.in 
       ${CMAKE_CURRENT_BINARY_DIR}/version.cpp) 
# Prepare the versionForSourcePackage.cmake file that will be included in the source package. 
configure_file(
    ${PROJECT_SOURCE_DIR}/versionForSourcePackage.cmake.in 
    ${PROJECT_BINARY_DIR}/versionForSourcePackage.cmake @ONLY) 
set(version_file "${CMAKE_CURRENT_BINARY_DIR}/version.cpp") 

set(source_files "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp") 

#Add the version_file to the project build. 
add_executable(${PROJECT_NAME} ${source_files} ${version_file}) 

Die Datei versionForSourcePackage.cmake.in:

set(VERSION "[email protected][email protected]") 

Die zweite Möglichkeit ist der Ansatz bei https://github.com/lcw/cmake_git_version verwendet. Ein vollständiges Beispiel finden Sie im Zweig second_possibility in https://github.com/josefcibulka/version_git. Die Datei versionForSourcePackage.cmake wird in das Unterverzeichnis version_file des Build-Verzeichnisses gestellt, und dieses Verzeichnis wird unter CPACK_SOURCE_INSTALLED_DIRECTORIES hinzugefügt. Dies funktioniert gut, wenn sich das Projekt- und das Erstellungsverzeichnis auf derselben Ebene befinden. Das Problem ist, dass, wenn das Build-Verzeichnis unter dem Projektverzeichnis ist, ich das Build-Verzeichnis CPACK_SOURCE_IGNORE_FILES hinzufügen, um Anforderung 1 zu erfüllen. Dann, selbst wenn ich CPACK_SOURCE_INSTALLED_DIRECTORIES auf das Verzeichnis version_file festlegen, wird es ignoriert. Es kann so gemacht werden, dass ich nur alles im Build-Verzeichnis mit Ausnahme des Verzeichnisses version_file ignoriere. Dann enthält das Build-Verzeichnis im Quellpaket nur das Verzeichnis version_file, das besser ist als das gesamte Build-Verzeichnis, aber immer noch nicht perfekt.

aktualisieren: Es scheint, dass Anforderung 4 entweder nicht erfüllt ist, weil ich nicht CPACK_SOURCE_INSTALLED_DIRECTORIES in the CMake documentation finden.

Die Unterschiede von der ersten Möglichkeit sind, in CMakeLists.txt:

# The following will transfer the version from git to the source package. 
set(CPACK_SOURCE_INSTALLED_DIRECTORIES "${PROJECT_SOURCE_DIR};/;${PROJECT_BINARY_DIR}/version_file;/") 
# Exclude the build and .git directory from the source package. 
set(CPACK_SOURCE_IGNORE_FILES "${PROJECT_SOURCE_DIR}/.git/;${PROJECT_BINARY_DIR}/([^v].*|v[^e].*|ve[^r].*|ver[^s].*|vers[^i].*|vers[^i].*|versi[^o].*|versio[^n].*|version[^_].*|version_[^f].*|version_f[^i].*|version_fi[^l].*|version_fil[^e].*);${CPACK_SOURCE_IGNORE_FILES}") 

include (CPack) 

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/version.cpp.in 
       ${CMAKE_CURRENT_BINARY_DIR}/version.cpp) 
configure_file(
    ${PROJECT_SOURCE_DIR}/versionForSourcePackage.cmake.in 
    ${PROJECT_BINARY_DIR}/version_file/versionForSourcePackage.cmake @ONLY) 
+0

CPack a * .cmake Skript, wenn Verpackung laufen kann, so kann sie eine Datei erstellt gelesen von der Build (und legen Sie die Versionsvariable fest). Ich habe heute keine Quellen, aber es war nicht zu schwer. – Velkan

+0

@Velkan Ich kann CPack über die Versionsnummer informieren.Ich habe die Frage neu formuliert, um klarzustellen, dass ich eine Datei mit der Versionsnummer in das Quellpaket schreiben möchte und dies auf eine korrekte Art und Weise tun möchte. – pepan

+0

@Velkan Danke, dass du mich auf die Möglichkeit hingewiesen hast, ein cmake-Skript von cpack auszuführen. Dies stellt sich als besser heraus, als wenn ich einen Shell-Befehl ausführen würde. Jetzt kann ich fast genau das machen, was ich brauchte; Ich werde bald eine vollständige Antwort schreiben. – pepan

Antwort

0

Am Ende ist mir eine Modifikation der ersten Möglichkeit verwenden, aber die Probleme sind nur zum Teil gelöst.

Statt CPACK_INSTALL_COMMANDS, verwende ich CPACK_INSTALL_SCRIPT und ein CMake Skript. Dieses Skript wird für jedes Paket ausgeführt, das gerade erstellt wird, und das Schöne daran ist, dass innerhalb dieses Skripts CMAKE_CURRENT_BINARY_DIR auf das Verzeichnis verweist, in dem der Inhalt des Pakets gesammelt wird. Das heißt, was auch immer ich in dieses Verzeichnis kopiere, wird in das Paket gelangen.

Dies scheint jedoch ein undokumentiertes Verhalten von CMAKE_CURRENT_BINARY_DIR zu sein. Zum Beispiel sind CMAKE_BINARY_DIR und PROJECT_BINARY_DIR leer, wenn sie in einem CMake-Skript verwendet werden, das von CPack ausgeführt wird. Vielleicht ist in einer anderen Version von CMake CMAKE_CURRENT_BINARY_DIR auch leer, wenn es von CPack ausgeführt wird.

Ein weiteres Problem ist, dass ich möchte, dass die Versionsdatei nur in Quellpakete und nicht in Binärpakete kopiert wird. Die Art, wie ich die Unterscheidung mache, ist, dass wenn CMAKE_CURRENT_BINARY_DIR mit "Source" endet, nehme ich an, dass das Skript während der Vorbereitung eines Quellpakets ausgeführt wird.

Vollständiges Beispiel ist in der using_cpack_install_script Zweig von https://github.com/josefcibulka/version_git. Die geänderten Teile CMakeLists.txt:

# The following will transfer the version from git to the source package. 
set(CPACK_INSTALL_SCRIPT "${CMAKE_BINARY_DIR}/versionNumberToPackage.cmake") 

configure_file(${CMAKE_SOURCE_DIR}/versionNumberToPackage.cmake.in 
       ${CMAKE_BINARY_DIR}/versionNumberToPackage.cmake @ONLY) 

Der Inhalt versionNumberToPackage.cmake.in sind:

# Copies VersionForSourcePackage.cmake to the source package (it should not be copied to binary package). 
# Detection if this is the source package is that the path ends with "Source" and an optional slash. 
if("${CMAKE_CURRENT_BINARY_DIR}" MATCHES "Source/?$") 
    file(COPY @[email protected]/versionForSourcePackage.cmake DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 
endif() 
Verwandte Themen