确保内部共享库版本是正确的

时间:2014-06-18 12:42:58

标签: c++ design-patterns c++11 shared-libraries

我目前的任务是在内部库中尝试改进我们公司的版本控制实践。我已经阅读了Semantic Versioning 2.0.0这对于我们当前的版本实践(例如library_v01)并没有真正告诉我们很多关于每个库版本的问题,这似乎是一个非常好,简单而优雅的解决方案。

理想情况下,应用程序将检查在编译时使用的库的版本,以便在部署和/或测试之前捕获任何不匹配。我们的应用程序是用Visual Studio编写的,我们很快就会升级到C ++ 11编译器友好的VS2013,这就是为什么我的第一个想法是使用static_asserts来在编译时检查版本,如:

// Defined in library code and accessible by applications
struct LibraryVersion {
    static const unsigned int LIB_VERSION_MAJOR = 1;
    static const unsigned int LIB_VERSION_MINOR = 0;
    static const unsigned int LIB_VERSION_PATCH = 0;
}

// Application code
static const unsigned int EXPECTED_LIB_VERSION_MAJOR = 1;
static const unsigned int EXPECTED_LIB_VERSION_MINOR = 0;
static const unsigned int EXPECTED_LIB_VERSION_PATCH = 0;

void lib_version_check() {
    static_assert(LibraryVersion::LIB_VERSION_MAJOR == EXPECTED_LIB_VERSION_MAJOR, "Error Major");
    static_assert(LibraryVersion::LIB_VERSION_MINOR == EXPECTED_LIB_VERSION_MINOR, "Error Minor");
    static_assert(LibraryVersion::LIB_VERSION_PATCH == EXPECTED_LIB_VERSION_PATCH, "Error Patch");
}

在库文件中可以使用某种预处理器定义,这可以在包含路径中使用,这样每个应用程序都可以包含正确的库文件,例如

$(LIB_DIR)="C:\Libs\"
$(LIB_VERS)="v1.0.0"
Include_Path = $(LIB_DIR)\$(LIB_VERS);

文件结构类似于:

C:\Libs\v1.0.0\include\...
C:\Libs\v1.0.1\include\...
C:\Libs\v1.0.2\include\...
C:\Libs\v1.2.0\include\...

然而,这对我来说似乎不是最优雅的解决方案,并且必须跟踪两个版本变量(预处理器值和表示MAJOR,MINOR和PATCH版本的无符号整数)似乎有点多。

所以基本上我想问一下其他人是否遇到过类似的东西,如果他们对优雅的解决方案有什么了解,或者使用上述解决方案有任何陷阱可能我没想过的?也许有一个像上面描述的文件结构是有问题的和/或有一个更简单的方法?对于任何反馈,我们都表示感谢。非常感谢。

1 个答案:

答案 0 :(得分:1)

我们只使用git标签作为主要,次要和补丁生成带有模板的标头。我们做你上面所做的,但它都是自动化的。这不能解决编译依赖性。

但是,需要将库版本的依赖性提升到我们的自定义waf构建系统的包依赖项中。例如:

# We need boost
conf.env.BOOST_MINIMUM_VERSION = (1, 50)
conf.load('boost', tooldir=vcawaflib.dir)

# VCA project dependencies
conf.env.VCA_TEST_MINIMUM_VERSION = (0, 2, 3)
conf.project_uselib('sdk/test', 'vca_test')

构建系统与系统包管理器接口(在Windows上它使用我们编写的自定义python包管理器)并解析所有依赖项。

话虽如此,我们的构建系统设置已经做了很多工作。对于您的情况,您可以允许编译器计算库依赖项,但我会使用std::tuple,因为它在版本比较时做了正确的事情

include/my_awesome_library/version.h

namespace my_awesome_library {
  static constexpr auto version = std::make_tuple(1, 0, 0);
}  // namespace my_awesome_library

src/my_program_or_library/dependencies.c

static_assert(my_awesome_library::version >= std::make_tuple(1, 0, 0), "\nmy_awesome_library is old");

这可以是预处理器定义为:

#define VERSION_CHECK(version, ...) \
  static_assert(version >= std::make_tuple(__VA_ARGS__), #version " is old");

VERSION_CHECK(my_awesome_library::version, 1, 0, 0);

您可以将其展开以执行最小和最大检查等。

微软在较新版本的Visual Studio中做得更加符合标准,但是您必须检查上述内容是否适用于您使用的任何MSVC编译器。