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資源模板

模板如下,保存為

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()

因為是Windows平台特有的機制,所以我們使用條件判斷語句判斷下是否是MSVC。

.rc模板中的${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR},和${PROJECT_VERSION_PATCH}都來自CMake中project命令:

project(MyLibrary VERSION 1.2.3)

此時${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR},和${PROJECT_VERSION_PATCH}的值就變成了1,2和3。

經過上面轉換之后,${MY_VERSIONINFO_RC }這個CMake變量就存了轉換后的.rc文件路徑。將其加入庫編譯文件列表即可:

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)

#realname版本號為1.2.3 

大家可以通過readelf -d **.so.**查看相關情況。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM