Loading

1 CMake简介

CMake是一种跨平台编译工具,比Make更为高级,使用起来要方便得多。CMake主要是编写CMakeLists文件,然后用CMake命令将CMakeLists文件转化为Make所需要的Makefile文件,其可以跨平台生成对应能用的Makefile,最后用make命令编译源码生成可执行程序或共享库,它的作用和qt的qmake是相似的。

2 单个源文件编译

2.1 目录结构

.
├── CMakeLists.txt    
└── main.c

0 directories, 2 files

2.2 编写 CMakeLists.txt

# CMake 最低版本号要求
cmake_minimum_required (VERSION 3.1)

# 项目名称
project (Demo)

# 指定生成目标
add_executable(BGM main.c)

2.3 执行编译

在当前目录执行cmake . -G "MSYS Makefiles",得到Makefile后再使用make命令编译得到BGM可执行文件。指令执行完毕后的目录结构:

.
├── BGM.exe
├── cmake_install.cmake
├── CMakeCache.txt
├── CMakeFiles
├── CMakeLists.txt
├── main.c
└── Makefile

3 多个源文件编译

3.1 同一目录

3.1.1 目录结构

.
├── CMakeLists.txt
├── main.c
├── MathFunctions.c
└── MathFunctions.h

0 directories, 4 files

3.1.2 编写 CMakeLists.txt

# CMake 最低版本号要求
cmake_minimum_required (VERSION 3.1)

# 项目名称
project (Demo)

# 查找当前目录下的所有源文件, 并将名称保存到 SRCS 变量
aux_source_directory(./ SRCS)

# 指定生成目标
add_executable(BGM ${SRCS})

3.1.3 执行编译

在当前目录执行cmake . -G "MSYS Makefiles",得到Makefile后再使用make命令编译得到BGM可执行文件。指令执行完毕后的目录结构:

.
├── BGM.exe
├── cmake_install.cmake
├── CMakeCache.txt
├── CMakeFiles
├── CMakeLists.txt
├── main.c
├── Makefile
├── MathFunctions.c
└── MathFunctions.h

3.2 多个目录

3.2.1 目录结构

现在进一步将MathFunctions.hMathFunctions.c文件移动到math目录下:

.
├── CMakeLists.txt
├── main.c
└── math
    ├── CMakeLists.txt
    ├── MathFunctions.c
    └── MathFunctions.h

对于多目录结构,需要分别在根目录和子目录里各编写一个CMakeLists.txt。本次编译采用方法为先将math目录里的文件编译成静态库,再由main函数调用。

3.2.2 编写 CMakeLists.txt

编写math子目录下的CMakeLists.txt:

# 查找当前目录下的所有源文件, 并将名称保存到 LIB_MathFunctions_SRCS 变量
aux_source_directory(./ LIB_MathFunctions_SRCS)
 
# 生成链接库, 将当前目录中的源文件编译为静态链接库
add_library(MathFunctions STATIC ${LIB_MathFunctions_SRCS})

编写根目录下的CMakeLists.txt:

# CMake 最低版本号要求
cmake_minimum_required(VERSION 2.8)
 
# 项目信息
project(BGM)
 
# 查找当前目录下的所有源文件, 并将名称保存到 DIR_ROOT_SRCS 变量
aux_source_directory(./ DIR_ROOT_SRCS)
 
# 添加 math 子目录, 这样 math 目录下的 CMakeLists.txt 文件和源代码也会被处理
add_subdirectory(./math)
 
# 指定生成目标
add_executable(Demo ${DIR_ROOT_SRCS})
 
# 添加链接库, 指明可执行文件 Demo 需要连接一个名为 MathFunctions 的链接库
target_link_libraries(Demo MathFunctions)

3.2.3 执行编译

在build子目录下执行cmake .. -G "MSYS Makefiles",得到Makefile后再使用make命令编译得到Demo可执行文件。指令执行完毕后的目录结构:

.
├── build
│   ├── cmake_install.cmake
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── Demo.exe
│   ├── Makefile
│   └── math
├── CMakeLists.txt
├── math
│   ├── CMakeLists.txt
│   ├── MathFunctions.c
│   └── MathFunctions.h
└── TestMain.c

4 directories, 9 files

附录

一个成熟项目的单元测试CMakeLists.txt参考:

# @file CMakeLists.txt
# @author Nixon (Xinglong.Ni@geely.com)
# @version 0.2
# @data 2023.09.12
# @brief build ota_utest in ubuntu env
# @note [change history]
#
# @copyright GEELY AUTOMOBILE RESEARCH INSTITUTE CO.,LTD Copyright (c) 2023
# -------------------------------------------------------------------------
# [change history]
# v0.1    2023.08.10    Nixon    1.初版
# v0.2    2023.09.12    Nixon    1.添加一些学习内容
# v0.3    2024.03.14    Nixon    1.优化 otamaster someip 模块路径
# -------------------------------------------------------------------------

# Makefile:在build子目录下执行 cmake .. -G "Unix Makefiles"
# Ninja   :在built子目录下执行 cmake .. -G "Ninja"

# CMake 最低版本号要求
cmake_minimum_required(VERSION 3.14)

# 项目信息
project(ota_utest)

# 编译选项配置
set(CMAKE_CXX_STANDARD 14)  # GoogleTest requires at least C++14
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 编译器选项
add_compile_options(-g)
# add_compile_options(-g -ftest-coverage -fprofile-arcs)  # -Wall -Wextra -g
# -ftest-coverage: 用于在编译后生成 .gcno 记录文件, 包含用于重建基本块图和为块分配源行号的信息
# -fprofile-arcs:  用于在执行后生成 .gcda 记录数据文件, 包含弧过渡计数、值分布计数和一些摘要信息

# 添加 otamaster 模块
set(OTAMASTER_DIR "${CMAKE_SOURCE_DIR}/src/otamaster_0321_23R4_stest_fix_temp")
file(GLOB OTA_MODULE_DIRS DIRECTORY "${OTAMASTER_DIR}/*")

foreach(module_dir ${OTA_MODULE_DIRS})
        aux_source_directory("${module_dir}/src" CFILES)  # otamaster 各模块源文件
        list(APPEND INC_DIRS "${module_dir}/inc")         # otamaster 各模块头文件路径
endforeach()

# 添加 otamaster someip IF 模块
set(OTAMASTER_SOMEIPIF_DIR "${OTAMASTER_DIR}/ota_someip_port")

set(OTATCAMSrv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTATCAMSrv")
list(APPEND INC_DIRS "${OTATCAMSrv_DIR}/client/impl/include")

set(InstallationConsentSrv_DIR "${OTAMASTER_SOMEIPIF_DIR}/InstallationConsentSrv")
list(APPEND INC_DIRS "${InstallationConsentSrv_DIR}/server/impl/include")

set(OTAInstallInfoSrv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTAInstallInfoSrv")
list(APPEND INC_DIRS "${OTAInstallInfoSrv_DIR}/client/impl/include")

set(OTAInstallInfo1Srv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTAInstallInfo1Srv")
list(APPEND INC_DIRS "${OTAInstallInfo1Srv_DIR}/client/impl/include")

set(OTAInstallInfo2Srv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTAInstallInfo2Srv")
list(APPEND INC_DIRS "${OTAInstallInfo2Srv_DIR}/client/impl/include")

set(TCAMNADSrv_DIR "${OTAMASTER_SOMEIPIF_DIR}/TCAMNADSrv")
list(APPEND INC_DIRS "${TCAMNADSrv_DIR}/client/impl/include")

set(OTADownloadInfoSrv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTADownloadInfoSrv")
list(APPEND INC_DIRS "${OTADownloadInfoSrv_DIR}/client/impl/include")

set(OTADownloadInfo1Srv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTADownloadInfo1Srv")
list(APPEND INC_DIRS "${OTADownloadInfo1Srv_DIR}/client/impl/include")

set(OTADownloadInfo2Srv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTADownloadInfo2Srv")
list(APPEND INC_DIRS "${OTADownloadInfo2Srv_DIR}/client/impl/include")

set(OTADHUSrv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTADHUSrv")
list(APPEND INC_DIRS "${OTADHUSrv_DIR}/client/impl/include")
list(APPEND INC_DIRS "${OTADHUSrv_DIR}/server/impl/include")

set(OTASilentInstallStsSrv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTASilentInstallStsSrv")
list(APPEND INC_DIRS "${OTASilentInstallStsSrv_DIR}/client/impl/include")

set(OTASilentInstallControlSrv_DIR "${OTAMASTER_SOMEIPIF_DIR}/OTASilentInstallControlSrv")
list(APPEND INC_DIRS "${OTASilentInstallControlSrv_DIR}/client/impl/include")

# 添加 utest 模块
set(UTEST_DIR "${CMAKE_SOURCE_DIR}/utest")
file(GLOB UTEST_MODULE_DIRS DIRECTORY "${UTEST_DIR}/*")

foreach(module_dir ${UTEST_MODULE_DIRS})
        aux_source_directory("${module_dir}" CXXFILES)  # UTEST 各模块源文件
        list(APPEND INC_DIRS "${module_dir}")           # UTEST 各模块头文件路径
endforeach()

# 添加 gtest 模块
list(APPEND INC_DIRS "/usr/local/include/gtest")
list(APPEND INC_DIRS "/usr/include/gtest")

# 添加 gmock 模块
list(APPEND INC_DIRS "/usr/local/include/gmock")
list(APPEND INC_DIRS "/usr/include/gmock")

# 添加 mockcpp 模块
list(APPEND INC_DIRS "/usr/local/include/mockcpp")
list(APPEND INC_DIRS "/usr/mockcpp/mockcpp/3rdparty")

# 添加 zlib 模块
set(ZLIB_DIR "${CMAKE_SOURCE_DIR}/../6third_party/zlib")
list(APPEND INC_DIRS "${ZLIB_DIR}")
list(APPEND INC_DIRS "${ZLIB_DIR}/include")
list(APPEND INC_DIRS "${ZLIB_DIR}/src")
aux_source_directory("${ZLIB_DIR}/src" CFILES)  
aux_source_directory("${ZLIB_DIR}/microtar/src" CFILES)  

# 添加 3external_interface 模块
aux_source_directory("${CMAKE_SOURCE_DIR}/../3external_interface/src" CXXFILES)  

# 添加 uds_middleware 模块
set(UDS_MIDDLEWARE_DIR "${CMAKE_SOURCE_DIR}/../3external_interface/inc/uds_middleware")
list(APPEND INC_DIRS "${UDS_MIDDLEWARE_DIR}/client/include")
list(APPEND INC_DIRS "${UDS_MIDDLEWARE_DIR}/server/include")

# 添加 csmw 模块
set(CSMW_DIR "${CMAKE_SOURCE_DIR}/../3external_interface/inc/csmw")
list(APPEND INC_DIRS "${CSMW_DIR}/inc")
# aux_source_directory("${CSMW_DIR}/src" CXXFILES)  

# 添加 apvp 模块
set(APVP_DIR "${CMAKE_SOURCE_DIR}/../3external_interface/inc")
list(APPEND INC_DIRS "${APVP_DIR}")
# aux_source_directory("${APVP_DIR}" CXXFILES)  

# 添加 frameworks/native/ota 模块
set(FRAMEWORKS_NATIVE_OTA_DIR "${CMAKE_SOURCE_DIR}/../3external_interface/inc/frameworks/native/ota")
list(APPEND INC_DIRS "${FRAMEWORKS_NATIVE_OTA_DIR}/server/include")
# aux_source_directory("${APVP_DIR}" CXXFILES)  

# 添加构建目标需要的自定义头文件路径
include_directories(${INC_DIRS})                    

# # 需要排除的UTEST文件夹
# set(EXCLUDED_UTEST_FOLDERS
#     ${UTEST_DIR}/inventoryclient
#     ${UTEST_DIR}/updateengine)

# # 从源文件列表中移除需要排除的UTEST文件
# foreach(EXCLUDED_UTEST_FOLDER ${EXCLUDED_UTEST_FOLDERS})
#     file(GLOB_RECURSE EXCLUDE_UTEST_FILES ${EXCLUDED_UTEST_FOLDER}/*.cpp)
#     list(REMOVE_ITEM CXXFILES ${EXCLUDE_UTEST_FILES})
# endforeach()

# lib库路径
link_directories("/usr/local/lib")

# 指定生成目标
add_executable(utest ${CFILES} ${CXXFILES})

# 连接目标库
target_link_libraries(utest curl gtest gmock mockcpp gcov pthread)

# 定义UTEST宏
add_definitions(-DUTEST)

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

👤本站访客数: 👁️本站访问量: