LINUX.ORG.RU

Способы указания версии ПО

 , , ,


2

1

Доброго времени суток!

Есть проект, написанный на C++ с использованием системы контроля версий Git и системы сборки CMake.

Я хочу сделать так, чтобы в конечный исполняемый файл «вшивалась» версия этого проекта. При этом я не хочу следить за номером версии.

Принимая во внимание тот факт, что версия в наиболее распространённом случае состоит из набора «подверсий» (major, minor, build...), я бы хотел иметь возможность указывать, какую часть версии инкрементировать.

Я знаю, что в Git используются тэги для указания меток версии. В CMake же есть возможность указания макросов через конфигурационные файлы *.in.

Первый способ не обеспечит мне «вшивание» версии в ПО (я не смогу сделать что-то вроде «myProg --version»). В то же время для использования конфиг файлов Cmake-а я буду вынужден перед изменением версии залазить в CMakeLists.txt и править числа прямо там, что, как по мне, выглядит очень грубо.

Так вот вопрос мой в том, есть ли уже какие-либо готовые решения указания версии ПО?

Спасибо!

Я сделал так:
На каждый релиз - тег в git. И далее просто:
В Makefile:

FW_VERSION := $(shell git describe 2>/dev/null)
...
CFLAGS += -D_FIRMWARE_VERSION_STR=\"$(FW_VERSION)\"

И далее в самой программе использую макрос _FIRMWARE_VERSION_STR. Но как именно это сделать в cmake не подскажу :)

joy4eg ★★★★★
()

Возможно, поторопился с вопросом...

Нашёл эту тему.

Хотя в ней ни слова про Git, но всё равно пригодится

AccumPlus
() автор топика
Ответ на: комментарий от AccumPlus

Ну конечно.

Если так сильно хочется автоматизировать, сделай кастомную цель в CMake, которая будет искать последний тег, инкрементировать в нём нужный разряд и помечать им HEAD.

intelfx ★★★★★
()
Ответ на: комментарий от AccumPlus

А версию в гит просто вбиваете руками, да?

Ну дык, каждый релиз нужно обозначить ручками, а как иначе ? :)
Промежуточные билды будут иметь такую версию: <последний тег>-<кол-во коммитов после>-g<hash текущего HEAD>.
Например: последний тег у нас 0.0.4, после него было сделано 5 коммитов, текущий HEAD у нас 688df9e. Результат: 0.0.4-5-g688df9e.

joy4eg ★★★★★
()
Ответ на: комментарий от joy4eg

Всё понял, спасибо) Думаю, этот вариант мне подойдёт.

AccumPlus
() автор топика
Ответ на: комментарий от intelfx

Можете указать направление, где можно посмотреть про создание целей CMake? В Make это target, а здесь по запросу target выдаёт всё, что угодно, но только не то, что нужно.

AccumPlus
() автор топика
Ответ на: комментарий от targitaj

Тогда мне придётся сначала заносить в Git новый тэг, править txt-файл, потом собирать. Это конечно вариант, но мне бы хотелось получить более автоматизированный процесс

AccumPlus
() автор топика
Ответ на: комментарий от intelfx

Выходит, что мне нужны будут отдельные цели для инкремента каждого разряда версии?

AccumPlus
() автор топика
Ответ на: комментарий от joy4eg

Никогда так не делайте.

Во-первых, вы добавляете build-time зависимость от git. При опакечивании любой адекватный мантейнер безжалостно оторвёт её руками. Во-вторых, это не работает если исходники скачать тарболлом. В-третьих, если при этом у вас директория выше, например ~, содержит .git, оно возьмёт тэг оттуда и вы сильно удивитесь.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 2)

Я хочу сделать так, чтобы в конечный исполняемый файл «вшивалась» версия этого проекта. При этом я не хочу следить за номером версии.

Придётся следить. Версию указать в CMakeLists.txt, через ADD_DEFINITIONS или CONFIGURE_FILE можно передать в код или куда угодно ещё (в Doxygen, например). За тэгом в git придётся следить отдельно.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Это все верно и подходит для либ/программ которые распространяются отельно от репы. Но если же это internal проект который живет исключительно в git, то почему бы и нет ? :)

joy4eg ★★★★★
()
Ответ на: комментарий от slovazap

Я правильно понял, что при изменении версии нужно будет изменять CMakeLists.txt, вписывая туда новые числа?

AccumPlus
() автор топика
Ответ на: комментарий от joy4eg

Ну так-то если это никто никогда не увидит то да, делайте что угодно. Но от публикации закрытого/локального/только для себя проекта зарекаться не стоит.

slovazap ★★★★★
()
Ответ на: комментарий от conalex

Ну, самый простой вариант, но, как оказалось, самый правильный...

Файл CMakeLists.h:

cmake_minimum_required(VERSION 2.8.11)

project(Test)

set (CMAKE_BUILD_TYPE Debug)

set (MAJOR_VERSION 0)
set (MINOR_VERSION 1)

configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h")

set (sources	main.cpp
)

set (headers	version.h
)

add_executable(${CMAKE_PROJECT_NAME} ${sources} ${headers})

Файл version.h.in:

#define MAJOR_VERSION @MAJOR_VERSION@
#define MINOR_VERSION @MINOR_VERSION@

Файл main.cpp:

#include <iostream>

#include "version.h"

int main()
{
	std::cout << "Version: " << MAJOR_VERSION << '.' << MINOR_VERSION << std::endl;

	return 0;
}

Единственное, пока version.h не сгенерирован, среда ругается на отсутствие файлов и на неизвестные параметры. Но это до первой сборки.

Ещё есть вариант без генерации файла version.h, с помощью ADD_DEFINITIONS. Но при таком исходе среда будет всегда ругаться на неизвестный параметр.

Файл CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.11)

project(Test)

set (CMAKE_BUILD_TYPE Debug)

add_definitions(-DMAJOR_VERSION=0 -DMINOR_VERSION=1)

configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h")

set (sources	main.cpp
)

set (headers	
)

add_executable(${CMAKE_PROJECT_NAME} ${sources} ${headers})

Мне больше нравится первый вариант.

AccumPlus
() автор топика
Ответ на: комментарий от conalex

Всё же хочу попробовать сделать то, что хотел с самого начала. Но это позже.

AccumPlus
() автор топика
Ответ на: комментарий от AccumPlus

Файл CMakeLists.h:

Очевидно, CMakeLists.txt

configure_file(«${PROJECT_SOURCE_DIR}/version.h.in» «${PROJECT_SOURCE_DIR}/version.h»)

Во втором варианте CMakeLists.txt без этой строки

P.S. Как редактировать сообщения?

AccumPlus
() автор топика
Ответ на: комментарий от conalex

вот такой штуковиной не пользовался?

Неа, но интересно, спасибо!

AccumPlus
() автор топика
Ответ на: комментарий от ymuv

Я делал:

Не будет работать, потому что для смены версии нужно будет переконфигурировать проект. Инкрементальная сборка накрывается. Можно использовать CMAKE_CONFIGURE_DEPENDS, но это в данном случае костыль.

Dendy ★★★★★
()
Ответ на: комментарий от conalex

вот такой штуковиной не пользовался?

Этой штукой нужно уметь пользоваться. Правильный способ вынести её вызов в отдельный cmake-скрипт, который будет генерировать файл с версией, .h или .cpp не суть важно. Вызов этого скрипта должен быть завёрнут в add_custom_command/add_custom_target с командой ${CMAKE_COMMAND} -E и указанием генерируемого файла в BUILD_PRODUCTS. Если этого не сделать, то версия будет безусловно перегенерироваться каждый раз про конфигурировании/сборке, даже если она не изменилась, и заставлять пересобираться весь остальной проект. Если скрипт не обнаружит гит, то он может сгенерировать код на основании других данных или дефолтную заглушку или вообще завершиться с ошибкой.

Dendy ★★★★★
()

У меня версия добывается из тега гита скриптом GitVersion.cmake, а при сборке тарболла CPACKом создаётся скрипт FallbackVersion.cmake, в котором тупо записана версия.

Athor ★★
()
Ответ на: комментарий от ymuv

Тем самым нарушая основную идею CMake для разделения этапов конфигурации и сборки. Да и IDE здесь ни при чём, обычный скрипт cmake . && cmake -B делает то же самое.

Dendy ★★★★★
()
Ответ на: комментарий от conalex

Сейчас что-то соображу. Я там обманул в предыдущем посте, не ${CMAKE_COMMAND} -E, а ${CMAKE_COMMAND} -P. И не BUILD_PRODUCTS, а BYPRODUCTS. Память уже деградирует (-:

Dendy ★★★★★
()

в cpp файле константа чем плоха ? )

x905 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.