CMake为自己创建的库添加版本信息

1.Windows平台

Windows上的DLL是可以带上文件信息的,包括版本号、公司名等。如果你使用Visual Studio自带的动态链接库工程目标开发DLL,那么VS会帮你把这些信息加到最后生成的DLL中;但是CMake不会,默认情况下通过add_library生成的DLL没有任何额外信息。那么在CMake工程中,如何给生成的DLL加这些信息呢?

版本信息作用

正规公司出品的DLL一般都会有版本信息。比如我们右键点击Qt的随便一个DLL,选择属性,在“详细信息”那个tab下就可以看到很多信息:

毫无疑问,直接附属在DLL文件中的版本信息,比任何其他文档都更准确地指明了当前DLL的版本。一旦出bug了,右键查看下就知道这个DLL是什么时候、哪个部门生成的。

具体方法

其实也很简单,方法分三步:

  1. 首先准备一个.rc资源模板,里面各信息对应位置都是CMake可替换的变量;
  2. 在CMakeLists.txt中,通过configure_file处理.rc模板,生成最终的.rc文件;
  3. 将最终的.rc文件放入add_library参与编译。

rc资源模板

模板如下,保存为http://VersionInfo.rc.in

VERSIONINFO
 FILEVERSION ${PROJECT_VERSION_MAJOR}, ${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH}
 PRODUCTVERSION ${PROJECT_VERSION_MAJOR}, ${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH}
 FILEFLAGSMASK 0x17L
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x0L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription", "MyLibrary Binary"
            VALUE "FileVersion", "${PROJECT_VERSION_MAJOR}, ${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH}"
            VALUE "InternalName", "MyLibrary"
            VALUE "LegalCopyright", "Copyright (C) 2019"
            VALUE "OriginalFilename", ""
            VALUE "ProductName", "MyLibrary"
            VALUE "ProductVersion", "${PROJECT_VERSION_MAJOR}, ${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH}"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END


在CMake中处理文件  

使用CMake的configure_file命令可以将上面的.rc模板文件中的CMake变量都替换为当前CMake解析过程中的变量值:

if(MSVC)
    set(MY_VERSIONINFO_RC "${CMAKE_BINARY_DIR}/VersionInfo.rc")
    configure_file("${CMAKE_SOURCE_DIR}/VersionInfo.rc.in"
                   "${MY_VERSIONINFO_RC }")
endif()


.rc模板中的${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR},和${PROJECT_VERSION_PATCH}都来自CMake中project命令:因为是Windows平台特有的机制,所以我们使用条件判断语句判断下是否是MSVC。

project(MyLibrary VERSION 1.2.3)


经过上面转换之后,${MY_VERSIONINFO_RC }这个CMake变量就存了转换后的.rc文件路径。将其加入库编译文件列表即可:此时${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR},和${PROJECT_VERSION_PATCH}的值就变成了1,2和3。

add_library(${TARGET_NAME} SHARED ${PUBLIC_HEADERS} ${PRIVATE_HEADERS} ${SOURCES} ${MY_VERSIONINFO_RC })

最后编译生成,右键查看生成的DLL的详细信息就能看到我们添加的版本了。

2. Linux平台下

动态库.so是可以添加版本号码的,而静态库不可以。

 一、库命名

        我们在linux下使用一些库时,会发现其后面带有一些数字,例如:libc.so.1 。形如lib*.so.x.y.z是有一套命名规则(*表示你给so的名字),x表示major version ,y表示minor version  z表示release version ,引入这套规则的目的是保证程序的更新,兼容等,

       linux共有的so有三种名字:

    (1)real name:其命名规则为lib*.so.x.y.z,在它的开头,包含有soname信息。程序运行时真正调用的so,也就是里面是真正含有代码的,

    (2)soname(short for shared object name):其命名规则为lib*.so.x,应用程序在链接时,所找到的库,它的信息是写在real name,在链接时,从realname中读取出soname,写入应用程序中,应程序再通过soname找到real name

    (3)link name:其命名规则为lib*.so就是我们在链接时,所使用的名字,比如 -lc ,这样,编译器就会去寻找libc.so.x.y.z ,如果有多个,编译器去寻找最新的。当然,用户也可以直接指定全名,比如,/**/**/**/lib*.so.1.1.2,这个linkname其实是一个虚拟的,如果存在realname soname,那这个linkname其实是不存在的。既然这样,linkname作用是什么,linkname使得用户不用去记住那些数字编号了,直接利用前面的名字就可以找到所使用的so。编译器其实是根据linkname去找到realname,然后提取出soname的。

二、关于动态库

        下面我们自己编译一些so来试试看:我使用cmake来管理工程,当然也可以直接使用gcc,为了方便理解。操作中两者我都会采用

    ######动态库的生成及使用

  (1) cmake版

project(test_version)
cmake_minimum_required(VERSION 2.6)
set(CMAKE_C_FLAGS "-fPIC")
set(CMAKE_BUILD_TYPE Release ON)
add_library(test_version SHARED so.c)
SET_TARGET_PROPERTIES(test_version PROPERTIES VERSION 1.2.3 SOVERSION 1)


大家可以通过readelf -d **.so.**查看相关情况。#realname版本号为1.2.3 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值