情感测试简介

注册

 

发新话题 回复该主题

原生支持CMake的SDK构建实现类似 [复制链接]

1#

C++开发者使用第三方库一直非常麻烦,但并不是必须如此.如果你使用CMake,事情就会简单起来,譬如使用Qt/p>

##配置库依赖find_package(Qt5COMPONENTSWidgetsQmlREQUIRED)target_link_libraries(YourAppPRIVATEQt5::WidgetsQt5:ml)

MeetingC++于年进行的调查显示,70%以上c++开发者使用CMake,几乎是现实标准/p>CMake使用情况

但是,如果库作者不提供对应的CMake支持,开发者将无法仅仅使用find_package、target_link_libraries来使用该第三方库.

由于CMake历史上体验不太好,也没有像样的教程,很多库作者是非不为也,实不能也.这里将展示如何提供原生支持CMake的SDK构建.

前提条件

这里需要强调的是,这篇文章目的在于讲解SDK构建,工程应当已经使用CMake来构建了.

示例工程目录结构如下/p>

CMakeLists.txtlibs\CMakeLists.txtlibs\libA.hpplibs\libB.cpplibs\include\libB.hpp

构建的SDK包含两个库/p>头文件库libA动态库libB

其中CMakeLists.txt内容如下/p>

cmake_minimum_required(VERSION3.15)project(exampleVERSION0.0.1LANGUAGESCXX)##设置调试版本带dset(CMAKE_DEBUG_POSTFIX"d")add_subdirectory(libs)

在libs\CMakeLists.txt中定义了以上两个库:

cmake_minimum_required(VERSION3.15)#libA是存粹的头文件库,只需要指定头文件路径add_library(libAINTERFACE)add_library(${PROJECT_NAME}:bAALIASlibA)target_include_directories(libAINTERFACE"$BUILD_INTERFACE{CMAKE_CURRENT_SOURCE_DIR}""$INSTALL_INTERFACE:include")add_library(libBSHARED)add_library(${PROJECT_NAME}:bBALIASlibB)target_sources(libBPRIVATElibB.cppinclude/libB.hpp)set_target_properties(libBPROPERTIESWINDOWS_EXPORT_ALL_SYMBOLSTrue##自动导出符号)target_include_directories(libBINTERFACE"$BUILD_INTERFACE{CMAKE_CURRENT_SOURCE_DIR}""$INSTALL_INTERFACE:include")#指定库依赖target_link_libraries(libBPUBLIC${PROJECT_NAME}:bA)

libA.hpp内容如下:

#pragmaonceconstexprintanswer(){return42;}

libB.hpp内容如下:

#pragmaoncevoidexample();

libB.cpp内容如下:

#include"include\libB.hpp"#include"libA.hpp"#includeiostreamvoidexample(){std::cout"answer:"answer()"\n";}

以上代码即可以正常的构建.下面来看一下怎么构建出SDK.

SDK结构

这里参考Qt,SDK结构如下:

目录内容说明binlibB.dll、libBd.dll、libBd.pdb存放动态库、应用程序、调试符号includelibA.hpp、libB.hpp存放头文件liblibB.lib、libBd.lib存放库文件lib\cmakeexample\exampleConfig.cmake等存放库的CMake支持文件

可以将SDK构建拆分成每个库的安装与导出、整个工程的安装与导出.

libA的安装与导出

针对库来说,其安装动作要输出头文件、库文件、动态库等信息,并且把CMake信息导出.首先来看如何安装头文件(修改libs/CMakeLists.txt):

##安装头文件install(FILESlibA.hppDESTINATIONinclude)

然后是安装库、动态库等文件,同时将CMake导出所需信息输出到${PROJECT_NAME}Targets:

##安装target并导出install(TARGETSlibAEXPORT${PROJECT_NAME}TargetsLIBRARYDESTINATIONlibARCHIVEDESTINATIONlibRUNTIMEDESTINATIONbinINCLUDESDESTINATIONinclude)

这里的${PROJECT_NAME}就代表者工程名,即exampleTargets.

头文件库相对简单,下面看一下动态库.

libB的安装与导出

libB安装比起头文库只是头文件处理和pdb文件有所差异,需要将如下内容添加到libs/CMakeLists.txt:

##安装头文件install(DIRECTORY${CMAKE_CURRENT_SOURCE_DIR}/include/DESTINATIONincludeFILES_MATCHINGPATTERN"*.h*")##安装库/应用程序文件,并导出target到工程的Targetsinstall(TARGETSlibBEXPORT${PROJECT_NAME}TargetsRUNTIMEDESTINATIONbinLIBRARYDESTINATIONlibARCHIVEDESTINATIONlib)##安装pdb(可选)get_target_property(target_typelibBTYPE)if(NOTtarget_typeSTREQUAL"STATIC_LIBRARY")install(FILES$TARGET_PDB_FILEbBDESTINATIONbinOPTIONAL)endif()工程的安装与导出

整个工程的安装与导出相对复杂,需要生成如下文件:

文件说明exampleConfig.cmake提供find_package支持,由开发者提供模板来生成exampleConfigVersion.cmake提供版本处理支持exampleTargets.cmake存储工程包含的所有库、应用程序的导出信息

先来看一下需要向CMakeLists.txt添加的全部内容:

include(CMakePackageConfigHelpers)##生成包版本文件exampleConfigVersion.cmakewrite_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmakeVERSION${CMAKE_PROJECT_VERSION}COMPATIBILITYAnyNewerVersion)##生成包配置文件exampleConfig.cmakeconfigure_package_config_file(Config.cmake.in${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmakeINSTALL_DESTINATIONlib/cmake/${PROJECT_NAME})##安装find_package支持文件install(FILES${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmakeDESTINATIONlib/cmake/${PROJECT_NAME})##安装导出目标,生成为exampleTargets.cmake文件install(EXPORT${PROJECT_NAME}TargetsNAMESPACE${PROJECT_NAME}::FILE${PROJECT_NAME}Targets.cmakeDESTINATIONlib/cmake/${PROJECT_NAME})

其中Config.cmake.in内容如下:

macro(check_required_

分享 转发
TOP
发新话题 回复该主题