# cmake_study **Repository Path**: layne2020/cmake_study ## Basic Information - **Project Name**: cmake_study - **Description**: 本仓库主要用来学习cmake - **Primary Language**: 其他 - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2025-02-26 - **Last Updated**: 2025-02-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 从零开始编写一个cmake构建脚本 本文档介绍cmake构建脚本编写,包含的一些主要元素和命名规范。 ## 一、cmake构建工具版本要明确 ``` #命令名字要小写,这条语句要求构建工具至少需要版本为3.12或以上 cmake_minimum_required (VERSION 3.12) ``` ## 二、工程名及库的版本号明确 1)TINYXPATH为工程名,需要大写 2)指定库的版本号VERSION 1.3.0,该版本号会被三个cmake内置变量所继承,例如主版本号PROJECT_VERSION_MAJOR=1,次版本号PROJECT_VERSION_MINOR=3,补丁版本号PROJECT_VERSION_PATCH=0,后续可以直接使用这三个内置变量来使用库的版本号 ``` project(TINYXPATH VERSION 1.3.0) ``` ## 三、配置构建语言 1)可以自己根据工程配置需要构建的语言,比如CXX表示可以编译C++文件;C表示可以编译c文件;ASM表示可以编译汇编文件 ``` enable_language(CXX C ASM) ``` ## 四、配置测试用例可选变量 1)配置自定义变量,默认不构建测试用例,可以由使用者通过传入参数打开测试用例构建选项 ``` option(BUILD_TESTS "Build tests" OFF) #变量名BUILD_SAMPLE 变量说明"Build tests" 状态 OFF:表示不打开 ON:表示打开 ``` ## 五、打印调试信息 1)使用message命令打印日志 ```cmake message(WARNING "message text") #构建时打印警告信息 message(FATAL_ERROR "message text") #产生CMAKE Error时,会停止编译构建过程 message(STATUS "message text") #常用于查看变量值,类似于编程语言中的 DEBUG 级别信息. ``` ## 五、配置生成动态库或者静态库 1)配置内置变量BUILD_SHARED_LIBS,设置脚本默认构建库的模式,使用者可以通过传入参数来自己设置生成动/静态库 ``` set(BUILD_SHARED_LIBS TRUE CACHE BOOL "If TRUE, tinyxpath is built as a shared library, otherwise as a static library") ``` ## 六、常用变量定义 1)配置一些后面使用比较频繁的变量,变量名需要大写,并且变量名不能以CMAKE开头 ``` set(TARGET_NAME tinyxpath) #定义变量存放库名 set(TARGET_SAMPLE_NAME tinyxpath_test) #定义变量存放库测试用例名 set(TARGET_SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_NAME}) #定义变量存放库路径 set(TARGET_SRC ${TARGET_SRC_PATH}/tinystr.cpp) #定义变量存放库源码 if(BUILD_TESTS) #判断是否需要编译测试用例 set(TARGET_SAMPLE_SRC ${TARGET_SRC_PATH}/htmlutil.cpp ${TARGET_SRC_PATH}/main.cpp) #定义变量存放测试程序源码 endif() set(TARGET_INCLUDE ${TARGET_SRC_PATH}) #定义变量存放编译库或编译测试用例所需要的头文件的路径 set(TARGET_INSTALL_INCLUDEDIR include) #定义变量存放三方库安装时,头文件存放的路径 set(TARGET_INSTALL_BINDIR bin) #定义变量存放三方库安装时,可执行二进制文件存放的路径 set(TARGET_INSTALL_LIBDIR lib) #定义变量存放三方库安装时,库存放的路径 ``` ## 七、引用三方库 1)使用find_package引用其他的三方库 ``` find_package(XXX REQUIRED) #xxx表示要搜索的库名 ``` ## 八、编译库并配置库的属性 1) 优先使用target_***的命令为库配置依赖 ``` add_library(${TARGET_NAME} ${TARGET_SRC}) #生成库,会根据内置变量BUILD_SHARED_LIBS变量的值来生成动态库或者静态库 target_include_directories(${TARGET_NAME} PRIVATE ${TARGET_INCLUDE}) #配置构建时所依赖头文件的路径 if(BUILD_SHARED_LIBS) set_target_properties(${TARGET_NAME} PROPERTIES VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} SOVERSION ${PROJECT_VERSION_MAJOR}) #生成动态库时,为库设置版本号 endif() if(BUILD_TESTS) add_executable(${TARGET_SAMPLE_NAME} ${TARGET_SAMPLE_SRC}) #生成测试用例 target_include_directories(${TARGET_SAMPLE_NAME} PRIVATE ${TARGET_INCLUDE}) #配置构建时所依赖的头文件路径 target_link_libraries(${TARGET_SAMPLE_NAME} PUBLIC ${TARGET_NAME}) #配置所依赖的库 endif() ``` ## 九、文件安装 1)支持install,库对外提供被find_package的能力 2)install后,所有导出的头文件、动态库、静态库、可执行二进制、cmake文件都可以安装到指定路径下 ``` install(TARGETS ${TARGET_NAME} #TARGETS 安装的目标文件,可以是可执行文件、动态库、静态库 EXPORT ${TARGET_NAME} #需要对外导出的文件,该选项用于生成xxxConfig.cmake,便于支持find_package PUBLIC_HEADER DESTINATION ${TARGET_INSTALL_INCLUDEDIR} #头文件路径 PRIVATE_HEADER DESTINATION ${TARGET_INSTALL_INCLUDEDIR} #头文件路径 RUNTIME DESTINATION ${TARGET_INSTALL_BINDIR} #可执行程序路径 LIBRARY DESTINATION ${TARGET_INSTALL_LIBDIR} #动态库路径 ARCHIVE DESTINATION ${TARGET_INSTALL_LIBDIR}) #静态库路径 install(FILES ${TARGET_SRC_PATH}/xpath_processor.h #FILES 安装文件,可以是头文件,配置文件等 DESTINATION ${TARGET_INSTALL_INCLUDEDIR}/${TARGET_NAME}) # DESTINATION 需要安装到的路径 install( EXPORT ${TARGET_NAME} FILE ${TARGET_NAME}Targets.cmake #FILE 安装单个文件 ${TARGET_NAME}Targets.cmake由前面EXPORT参数生成的文件,用于find_package查找 DESTINATION ${TARGET_INSTALL_LIBDIR}/cmake/${TARGET_NAME} #DESTINATION 需要安装到的路径 ) include(CMakePackageConfigHelpers) write_basic_package_version_file( #生成库版本相关文件,用于find_package时可以找到库的版本号 ${TARGET_NAME}ConfigVersion.cmake VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} COMPATIBILITY SameMajorVersion ) configure_package_config_file( #生成库相关文件,用于find_package时可以找到库 cmake/PackageConfig.cmake.in ${TARGET_NAME}Config.cmake #cmake/PackageConfig.cmake.in 该文件需要自己编写 INSTALL_DESTINATION ${TARGET_INSTALL_LIBDIR}/cmake/${TARGET_NAME} #指定该文件存放的路径 ) install(FILES #将上述生成的两个文件安装到指定目录,用于find_package ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}ConfigVersion.cmake DESTINATION ${TARGET_INSTALL_LIBDIR}/cmake/${TARGET_NAME} ) ``` PackageConfig.cmake.in 文件放在CMakeLists.txt同一级目录下的cmake目录下, ``` XXX ├── cmake │ └── PackageConfig.cmake.in ├── CMakeLists.txt ``` PackageConfig.cmake.in内容如下 ``` @PACKAGE_INIT@ #内置宏 set(@PROJECT_NAME@_INCLUDE_DIRS ${PACKAGE_PREFIX_DIR}/include) #配置库头文件路径,对外导出变量@PROJECT_NAME@_INCLUDE_DIRS供外部引用 set(@PROJECT_NAME@_STATIC_LIBRARIES ${PACKAGE_PREFIX_DIR}/lib/lib@TARGET_NAME@.a) #配置库,对外导出变量@PROJECT_NAME@_LIBRARIES供外部引用 set(@PROJECT_NAME@SHARED_LIBRARIES ${PACKAGE_PREFIX_DIR}/lib/lib@TARGET_NAME@.so) include(CMakeFindDependencyMacro) include(${CMAKE_CURRENT_LIST_DIR}/@TARGET_NAME@Targets.cmake) check_required_components(@TARGET_NAME@) #检查@TARGET_NAME@ ``` ## 十、实战 [demo](demo)