MyTetra Share
Делитесь знаниями!
Автоматическое добавление версии билда в код с помощью CMake
Время создания: 02.05.2013 20:39
Текстовые метки: cmake, version, версия
Раздел: Компьютер - Программирование - Системы сборки - CMake
Запись: xintrea/mytetra_syncro/master/base/1367512754jiy6yhmv3v/text.html на raw.github.com

Автоматическое добавление версии билда в код с помощью CMake



Очень удобно всегда знать какой конкретно версии та или иная сборка проекта. Для этого обычно вводят номер версии, состоящий из нескольких цифр. Я являюсь сторонником структуры состоящей из 4 цифр, вида:



Именование

Смысл

Major

Изменение этого поля указывает на то, что изменения функционала весьма существенные. Возможно даже была утрачена совместимость по файлам данных и протоколам.

Minor

Указывает, что версия с большим значением этого поля, обладает большим функционалом.

Patch

Значение изменяется при выпуске новых версий, которые содержат исправления.

Build

Удобно для внутреннего использования, чтобы ссылаться на одну и ту же версию кода.


Все вместе это и формирует полное именование версии (Major.Minor.Pathch.Build):


4.6.12.589


Некоторые используют в качестве build уникальное числовое значение, которое увеличивается каждый раз, например, при ночной сборке. Я считаю, что никакого смысла в этом нет – гораздо удобнее привязать данный номер к ревизии в репозитории. Я использую Subversion и CMake, поэтому продемонстрирую как можно автоматизировать проставлении версии билда с этими инструментами.



Первое – необходимо добавить заголовочный файл в проект (например, version.h):


#include <string>

#include <boost/cstdint.hpp>

namespace Version

{

const std::string& AsText();

boost::uint64_t AsNumber();

}


Здесь находится простой интерфейс, через который из программы можно получить номер полной версии в текстовом виде или в виде уникального целочисленного идентификатора.


Теперь приведу содержимое version.cpp:


#include <boost/format.hpp>

#include "../version.h"

namespace

{

const boost::uint8_t MAJOR = 4;

const boost::uint16_t MINOR = 6;

const boost::uint16_t PATCH = 12;

const boost::uint32_t BUILD = 589; // Это значение будет изменено автоматически

}

const std::string& Version::AsText()

{

static const std::string text = boost::str(boost::format("%1%.%2%.%3%.%4%") %

static_cast<unsigned>(MAJOR) % MINOR % PATCH % BUILD);

return text;

}

boost::uint64_t Version::AsNumber()

{

BOOST_STATIC_ASSERT(BUILD < 0xFFFFFF);

using namespace boost;

const size_t size = sizeof(uint64_t);

static const boost::uint64_t number =

(static_cast<uint64_t>(MAJOR)

<< (size - sizeof(MAJOR)) * 8) |

(static_cast<uint64_t>(MINOR)

<< (size - sizeof(MAJOR) - sizeof(MINOR)) * 8) |

(static_cast<uint64_t>(PATCH)

<< (size - sizeof(MAJOR) - sizeof(MINOR) - sizeof(PATCH)) * 8) |

BUILD;

return number;

}


Здесь все тривиально и, думаю, не требует комментариев. Последнее, что осталось – механизм изменения значения BUILD, на номер ревизии в репозитории. С этим отлично справится CMake, просто добавьте в CMakeLists.txt следующий код:


set (VERSION_FILE ../common/sources/version.cpp)

find_package (Subversion REQUIRED)

Subversion_WC_INFO (${PROJECT_SOURCE_DIR} Repo)

file (READ ${VERSION_FILE} OLD_CODE)

foreach (LINE ${OLD_CODE})

string (REGEX MATCH "BUILD = ([0-9]+)" BUILD_NUMBER ${LINE})

if (BUILD_NUMBER)

string (REGEX REPLACE "[0-9]+$" ${Repo_WC_REVISION} LINE ${LINE})

endif ()

set (NEW_CODE ${NEW_CODE} ${LINE})

endforeach (LINE)

file (WRITE ${VERSION_FILE} "${NEW_CODE}")

Единственная тонкость в скрипте в последней строке, а конкретней – кавычки в "${NEW_CODE}", без них будут убраны все ";".


 
MyTetra Share v.0.59
Яндекс индекс цитирования