• CMAKE 实现自动区分不同版本库


    开发SDK时,经常需要依赖第三方库。此时需要考虑库的版本问题,一方面针对不同的编译器和Release、Debug版本灵活选择不同的第三方库,另一方面生成不同版本的库,并能被其他项目灵活引用。CMAKE此时体现其重要作用。

    这里记录并分析开源OCR项目Tesseract的编译过程。

    Tesseract 依赖第三方库leptonica,使用方法为:

      find_package(Leptonica REQUIRED)
      include_directories(${Leptonica_INCLUDE_DIRS})
      target_link_libraries(libtesseract ${Leptonica_LIBRARIES})

    利用CMake编译库leptonica时,会生成三个配置文件:LeptonicaConfig.cmake,LeptonicaConfig-version.cmake,LeptonicaTargets.cmake。在LeptonicaConfig.cmake中包含了LeptonicaTargets.cmake文件,并将Leptonica_LIBRARIES定义为leptonica, 在 LeptonicaTargets 中对变量leptonica根据不同编译版本有不同定义:

    // File LeptonicaConfig.cmake
    include(${CMAKE_CURRENT_LIST_DIR}/LeptonicaTargets.cmake)
    #
    # ====================================================================
    # Link libraries:
    # ====================================================================
    set(Leptonica_LIBRARIES leptonica)
    ////////////////////////
    
    //File LeptonicaTargets.cmake
    # Create imported target leptonica
    add_library(leptonica SHARED IMPORTED)
    
    # Import target "leptonica" for configuration "Debug"
    set_property(TARGET leptonica APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
    set_target_properties(leptonica PROPERTIES
      IMPORTED_IMPLIB_DEBUG "E:/ImageProcess/OCR/tesseract/leptonica-1.74.0/build_vs12/src/Debug/leptonica-1.74.0d.lib"
      IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG "E:/ImageProcess/OCR/tesseract/lib/Win32/giflib416-static-mtdll-debug.lib;
    E:/ImageProcess/OCR/tesseract/lib/Win32/libpng143-static-mtdll-debug.lib;
    E:/ImageProcess/OCR/tesseract/lib/Win32/libtiff394-static-mtdll-debug.lib;
    E:/ImageProcess/OCR/tesseract/lib/Win32/zlib128-static-mtdll-debug.lib"
      IMPORTED_LOCATION_DEBUG "E:/ImageProcess/OCR/tesseract/leptonica-1.74.0/build_vs12/bin/Debug/leptonica-1.74.0d.dll"  )
    
    # Import target "leptonica" for configuration "Release"
    set_property(TARGET leptonica APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
    set_target_properties(leptonica PROPERTIES
      IMPORTED_IMPLIB_RELEASE "E:/ImageProcess/OCR/tesseract/leptonica-1.74.0/build_vs12/src/Release/leptonica-1.74.0.lib"
      IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "E:/ImageProcess/OCR/tesseract/lib/Win32/giflib416-static-mtdll-debug.lib;
    E:/ImageProcess/OCR/tesseract/lib/Win32/libpng143-static-mtdll.lib;
    E:/ImageProcess/OCR/tesseract/lib/Win32/libtiff394-static-mtdll.lib;
    E:/ImageProcess/OCR/tesseract/lib/Win32/zlib128-static-mtdll.lib"
      IMPORTED_LOCATION_RELEASE "E:/ImageProcess/OCR/tesseract/leptonica-1.74.0/build_vs12/bin/Release/leptonica-1.74.0.dll")
    

    编译Tesseract成功后,安装结果包括头文件、库文件、和CMake配置文件。
    file

    图1

    file
    图2

    分析Tesseract项目的CMakeLists.txt,首先是配置部分,首先是生成configure文件: TesseractConfig-version.cmake、TesseractConfig.cmake;其次,待生成的库文件名对应Release、Debug有不同定义;接着,导出TesseractTargets.cmake文件;最后是安装配置文件。

    // 1
    configure_file(
        ${CMAKE_SOURCE_DIR}/cmake/templates/TesseractConfig-version.cmake.in
        ${CMAKE_BINARY_DIR}/TesseractConfig-version.cmake @ONLY)
    configure_file(
        ${CMAKE_SOURCE_DIR}/cmake/templates/TesseractConfig.cmake.in
        ${CMAKE_BINARY_DIR}/TesseractConfig.cmake @ONLY)
    // 2
    if (WIN32)
      set_target_properties(libtesseract PROPERTIES OUTPUT_NAME   tesseract${VERSION_MAJOR}${VERSION_MINOR})
      set_target_properties(libtesseract PROPERTIES DEBUG_OUTPUT_NAME tesseract${VERSION_MAJOR}${VERSION_MINOR}d)
    endif()
    // 3
    export(TARGETS libtesseract FILE ${CMAKE_BINARY_DIR}/TesseractTargets.cmake)
    // 4
    install(EXPORT TesseractTargets DESTINATION cmake)
    install(FILES
        ${CMAKE_BINARY_DIR}/TesseractConfig.cmake
        ${CMAKE_BINARY_DIR}/TesseractConfig-version.cmake
        DESTINATION cmake)
    /////////////////////////////////////////////////////////////////////
    

    在图2中,可以看到2个多出来的文件:TesseractTargets-debug, TesseractTargets-release。这两个文件就是实现根据环境设置不同库的功能。通过比较发现,最终的安装文件TesseractTargets.cmake与编译项目中生成的TesseractTargets.cmake(与工程文件sln同目录)并不相同,安装目录中的cmake文件是通过上述步骤3 export方法导出的。源文件TesseractTargets.cmake主要内容 :

    ...
    # Protect against multiple inclusion, which would fail when already imported targets are added once more.
    set(_targetsDefined)
    set(_targetsNotDefined)
    set(_expectedTargets)
    foreach(_expectedTarget libtesseract)
      list(APPEND _expectedTargets ${_expectedTarget})
      if(NOT TARGET ${_expectedTarget})
        list(APPEND _targetsNotDefined ${_expectedTarget})
      endif()
      if(TARGET ${_expectedTarget})
        list(APPEND _targetsDefined ${_expectedTarget})
      endif()
    endforeach()
    ...
    # Create imported target libtesseract
    add_library(libtesseract SHARED IMPORTED)
    
    set_target_properties(libtesseract PROPERTIES
      INTERFACE_COMPILE_DEFINITIONS "TESS_IMPORTS")
    
    # Import target "libtesseract" for configuration "Debug"
    set_property(TARGET libtesseract APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
    set_target_properties(libtesseract PROPERTIES
      IMPORTED_IMPLIB_DEBUG "E:/ImageProcess/OCR/tesseract/tesseract-3.05.01/vs2013/Debug/tesseract305d.lib"
      IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG "Ws2_32;leptonica"
      IMPORTED_LOCATION_DEBUG "E:/ImageProcess/OCR/tesseract/tesseract-3.05.01/vs2013/bin/Debug/tesseract305d.dll" )
    
    # Import target "libtesseract" for configuration "Release"
    set_property(TARGET libtesseract APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
    set_target_properties(libtesseract PROPERTIES
      IMPORTED_IMPLIB_RELEASE "E:/ImageProcess/OCR/tesseract/tesseract-3.05.01/vs2013/Release/tesseract305.lib"
      IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "Ws2_32;leptonica"
      IMPORTED_LOCATION_RELEASE "E:/ImageProcess/OCR/tesseract/tesseract-3.05.01/vs2013/bin/Release/tesseract305.dll"  )
    ...

    导出的目标TesseractTargets.cmake主要内容:

    ...
    # Load information for each installed configuration.
    get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
    file(GLOB CONFIG_FILES "${_DIR}/TesseractTargets-*.cmake")
    foreach(f ${CONFIG_FILES})
      include(${f})
    endforeach()

    而对应的TesseractTargets-debug.cmake 和 TesseractTargets-release.cmake 的主要内容:

    //File TesseractTargets-debug.cmake
    ...
    # Commands may need to know the format version.
    set(CMAKE_IMPORT_FILE_VERSION 1)
    
    # Import target "libtesseract" for configuration "Debug"
    set_property(TARGET libtesseract APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
    set_target_properties(libtesseract PROPERTIES
      IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/lib/tesseract305d.lib"
      IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG "Ws2_32;leptonica"
      IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/tesseract305d.dll"
      )
    
    list(APPEND _IMPORT_CHECK_TARGETS libtesseract )
    list(APPEND _IMPORT_CHECK_FILES_FOR_libtesseract "${_IMPORT_PREFIX}/lib/tesseract305d.lib" "${_IMPORT_PREFIX}/bin/tesseract305d.dll" )
    ...
    // File TesseractTargets-release.cmake
    ...
    # Import target "libtesseract" for configuration "Release"
    set_property(TARGET libtesseract APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
    set_target_properties(libtesseract PROPERTIES
      IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/lib/tesseract305.lib"
      IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "Ws2_32;leptonica"
      IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/tesseract305.dll"
      )
    
    list(APPEND _IMPORT_CHECK_TARGETS libtesseract )
    list(APPEND _IMPORT_CHECK_FILES_FOR_libtesseract "${_IMPORT_PREFIX}/lib/tesseract305.lib" "${_IMPORT_PREFIX}/bin/tesseract305.dll" )
    ...

    通过比较Tesseract项目与Leptonica项目,不难总结出添加依赖库与生成新的库时实现版本控制的主要方法及流程。
    第一步,使用Cmake正确安装第三方库后:

    find_package(3RDLIBRARY REQUIRED)
    include_directories(${3RDLIBRARY_INCLUDE_DIRS})
    target_link_libraries(project ${3RDLIBRARY_LIBRARIES})

    第二步,生成CMake配置文件:

    CMakeLists.txt ——> XXConfig.cmake XXConfig-version.cmake

    XXConfig.cmake ——> XXTargets.cmake

    XXTargets.cmake ——>XXTargets.cmake(new) XXTargets-debug.cmake
    XXTargets-release.cmake

    图3

    显然,可以将XXTargets完成的功能置于XXConfig中,这样的话配置文件便只有2个。
    关于cmake配置文件的生成规则,继续研究。

  • 相关阅读:
    Windows 7的 磁盘管理中,某个磁盘或分区,突然变成只读。
    Python 静态变量 与 静态方法
    如何用手机上网给电信固话充值
    Windows,查看进程的连接的IP地址,批量模式,最后做成Excel
    如果在VMware上免费下载驱动
    DELL iDRAC 远程虚拟机报错:虚拟介质分离或所选虚拟磁盘驱动器的虚拟介质重定向已由另一用户使用
    Windows Server 2008安装 百度Wifi 360Wifi 小米Wifi 失败的解决方法
    让Windows 8 / 8.1 以及 Windows Server 2012 / 2012 R2的桌面,显示我的电脑图标
    让Windows 8 / 8.1 以及 Windows Server 2012 / 2012 R2的任务管理器的性能面板,显示磁盘数据
    企业CIO、CTO必读的34个经典故事
  • 原文地址:https://www.cnblogs.com/brother-louie/p/13976550.html
Copyright © 2020-2023  润新知