300 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			300 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # 1. CMake构建工具使用
 | ||
| 
 | ||
|   SDK使用CMake工具构建。
 | ||
| 
 | ||
| ## 1.1. 安装
 | ||
| 
 | ||
| ```code
 | ||
| 详见://tools/cmake/Makefile
 | ||
| $ cd tools/cmake
 | ||
| $ make
 | ||
| $ cmake --version
 | ||
| cmake version 3.27.4
 | ||
| ```
 | ||
| 
 | ||
| ## 1.2. SDK构建配置脚本
 | ||
| 
 | ||
| * build目录下是基本的配置脚本。
 | ||
| 
 | ||
| ```code
 | ||
| build/
 | ||
| ├── cmake
 | ||
| │   ├── Makefile                  // 调用cmake命令生成Makefile文件;
 | ||
| │   └── toolchain
 | ||
| │       └── linux.toolchain.cmake // 工具链配置文件已经一些全局变量;
 | ||
| ├── global_config.cmake           // 配置文件
 | ||
| └── sdk_config.cmake              // 配置文件
 | ||
| ```
 | ||
| 
 | ||
| ### 1.2.1. //build/cmake/Makefile
 | ||
| 
 | ||
|   调用cmake命令生成Makefile文件。
 | ||
| 
 | ||
| ```code
 | ||
| all:
 | ||
|     @mkdir -p ../../cmake-shell;\  // 创建cmake输出目录,这一步很关键,所有cmake的中间文件都将会存放在此目录。
 | ||
|     cd ../../cmake-shell;\
 | ||
|     pwd;\
 | ||
|     # 调用cmake命令,并指定工具链配置文件,生成Makefile文件。
 | ||
|     cmake -DCMAKE_TOOLCHAIN_FILE="./build/cmake/toolchain/linux.toolchain.cmake" ..;\
 | ||
|     cd ..
 | ||
| clean:
 | ||
|     rm -rf ../../cmake-shell
 | ||
| ```
 | ||
| 
 | ||
| 在根目录执行:make cmake 的时候,即是调用上述Makefile生成Makefile文件。
 | ||
| 
 | ||
| ### 1.2.2. //build/cmake/toolchain/linux.toolchain.cmake
 | ||
| 
 | ||
|   工具链配置文件或者一些跨平台差异化的配置文件。该文件在//build/cmake/Makefile中被指定,当需要交叉编译时,此文件的变量需要被重新配置。
 | ||
| 
 | ||
| ```code
 | ||
| 
 | ||
| INCLUDE(CMakeForceCompiler)
 | ||
| 
 | ||
| set(LINUX_TEST                    "true")
 | ||
| set(CROSS_COMPILE_PREFIX          "")                // 工具链前缀
 | ||
| set(CMAKE_C_COMPILER "${CROSS_COMPILE_PREFIX}gcc")   // 配置工具链
 | ||
| set(CMAKE_CXX_COMPILER "${CROSS_COMPILE_PREFIX}g++") // 配置工具链
 | ||
| 
 | ||
| # path to compiler and utilities
 | ||
| set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
 | ||
| set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
 | ||
| set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 | ||
| 
 | ||
| # Name of the target platform
 | ||
| set(CMAKE_SYSTEM_NAME Linux)
 | ||
| set(CMAKE_SYSTEM_PROCESSOR arm)
 | ||
| 
 | ||
| # Version of the system
 | ||
| set(CMAKE_SYSTEM_VERSION 1)
 | ||
| cmake_policy(SET CMP0011 NEW)
 | ||
| cmake_policy(SET CMP0005 NEW)
 | ||
| 
 | ||
| add_definitions(-Wall -O2 -Os)
 | ||
| add_definitions(-Wno-unused-local-typedefs)
 | ||
| add_definitions(-Wstrict-aliasing -Wwrite-strings)
 | ||
| 
 | ||
| set(TOOLCHAIN_NAME arm-linux-gnueabihf)
 | ||
| 
 | ||
| set(TARGET_PLATFORM                        "linux") // 编译系统平台,Linux表示在PC的ubuntu系统上编译
 | ||
| set(SUBMODULE_PATH_OF_IPC_SDK               "") // 子仓库路面,此处为空,交叉编译时设置
 | ||
| set(PLATFORM_PATH                          "${CMAKE_CURRENT_SOURCE_DIR}") // 平台路径
 | ||
| set(TEST_COVERAGE                          "true") // 覆盖率报告开关
 | ||
| add_definitions(-DPLATFORM_PATH=\"${PLATFORM_PATH}\") // 定义一个宏
 | ||
| set(PROJECT_OUTPUT_FOLDER        "output_files")  // 编译的目标文件输出目录
 | ||
| set(CMAKE_INSTALL_PREFIX         "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_OUTPUT_FOLDER}")
 | ||
| 
 | ||
| ... // 此处省略不同模块的配置参数,一般是一些宏定义;
 | ||
| ```
 | ||
| 
 | ||
| ### 1.2.3. //CMakeLists.txt
 | ||
| 
 | ||
|   SDK跟目录下的第一个CMakeLists.txt文件,cmake命令执行的时候会指定根目录,到此目录下寻找CMakeLists.txt文件作为整个项目的构建起点。
 | ||
| 
 | ||
| ## 1.3. 重要的配置
 | ||
| 
 | ||
| ### 1.3.1. 目录设置
 | ||
| 
 | ||
|   目录结构都是通过.cmake脚本来配置的。
 | ||
| 
 | ||
| #### 1.3.1.1. 源码目录结构配置
 | ||
| 
 | ||
| 详见://build/global_config.cmake
 | ||
| 
 | ||
| ```code
 | ||
| set(EXEC_OUTPUT_PATH            "${PLATFORM_PATH}/${PROJECT_OUTPUT_FOLDER}/bin")
 | ||
| set(LIBS_OUTPUT_PATH            "${PLATFORM_PATH}/${PROJECT_OUTPUT_FOLDER}/libs")
 | ||
| set(TEST_TOOLS_OUTPUT_PATH      "${PLATFORM_PATH}/${PROJECT_OUTPUT_FOLDER}/libs/test_tools")
 | ||
| set(EXTERNAL_LIBS_OUTPUT_PATH   "${PLATFORM_PATH}/${PROJECT_OUTPUT_FOLDER}/libs/external")
 | ||
| set(TEST_OUTPUT_PATH            "${PLATFORM_PATH}/${PROJECT_OUTPUT_FOLDER}/test")
 | ||
| 
 | ||
| set(PROJECT_ROOT_PATH           "${PLATFORM_PATH}")
 | ||
| set(APPLICATION_SOURCE_PATH     "${CMAKE_SOURCE_DIR_IPCSDK}/application") # 应用层目录
 | ||
| set(MIDDLEWARE_SOURCE_PATH      "${CMAKE_SOURCE_DIR_IPCSDK}/middleware")  # 中间件层目录
 | ||
| set(UTILS_SOURCE_PATH           "${CMAKE_SOURCE_DIR_IPCSDK}/utils")       # 工具层目录
 | ||
| set(HAL_SOURCE_PATH             "${CMAKE_SOURCE_DIR_IPCSDK}/hal")         # 硬件抽象层目录
 | ||
| set(TEST_SOURCE_PATH            "${CMAKE_SOURCE_DIR_IPCSDK}/test")        # 自动化测试代码/example目录
 | ||
| set(EXTERNAL_SOURCE_PATH        "${CMAKE_SOURCE_DIR_IPCSDK}/external")    # 外部依赖库目录
 | ||
| ```
 | ||
| 
 | ||
| ## 1.4. CMakeLists.txt基本语法
 | ||
| 
 | ||
| ### 1.4.1. 概述
 | ||
| 
 | ||
|   概括性描述就是,只需要告诉CMakeLists.txt文件,构建时包含哪些配置文件,依赖的头文件目录,需要编译的源码文件,依赖的目标目录(如有),输出的目标,依赖的目标(一般是库),CMakeLists.txt即可生成一个Makefile代码来构建这个目标。
 | ||
| 
 | ||
|   整个SDK由很多的CMakeLists.txt文件组成,绝大多数的CMakeLists.txt文件负责把该目录的源码编译成一个库,SDK通过链接不同功能的库来构建不同的应用程序。
 | ||
| 
 | ||
| ```code
 | ||
| ./application/CMakeLists.txt
 | ||
| ./application/HuntingCamera/CMakeLists.txt
 | ||
| ./CMakeLists.txt
 | ||
| ./hal/CMakeLists.txt
 | ||
| ./middleware/AppManager/CMakeLists.txt
 | ||
| ./middleware/CMakeLists.txt
 | ||
| ./test/all/CMakeLists.txt
 | ||
| ./test/application/CMakeLists.txt
 | ||
| ./test/application/HuntingCamera/CMakeLists.txt
 | ||
| ./test/application/MissionManager/CMakeLists.txt
 | ||
| ./test/application/MissionManager/tool/CMakeLists.txt
 | ||
| ./test/application/VersionReleaseTool/CMakeLists.txt
 | ||
| ./test/CMakeLists.txt
 | ||
| ./test/hal/CMakeLists.txt
 | ||
| ./test/hal/tool/CMakeLists.txt
 | ||
| ./test/middleware/AppManager/CMakeLists.txt
 | ||
| ./tools/clang-tidy/CMakeLists.txt
 | ||
| ./utils/CMakeLists.txt
 | ||
| ./utils/Config/CMakeLists.txt
 | ||
| ./utils/ConfigBase/CMakeLists.txt
 | ||
| ```
 | ||
| 
 | ||
| ### 1.4.2. 一个CMakeLists.txt示例
 | ||
| 
 | ||
|   CMakeLists.txt可以通过调用一些shell脚本来完成除编译之外的其它工具,例如:格式化代码。
 | ||
| 
 | ||
| ```code
 | ||
| 
 | ||
| include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake)
 | ||
| set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) // 设置可执行文件的输出目录
 | ||
| set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH})    // 设置库文件的输出目录
 | ||
| 
 | ||
| include_directories( // 该目标需要依赖的头文件的目录
 | ||
|     ./src
 | ||
|     ./include
 | ||
|     ${UTILS_SOURCE_PATH}/StatusCode/include
 | ||
|     ${UTILS_SOURCE_PATH}/Log/include
 | ||
| )
 | ||
| 
 | ||
| #do not rely on any other library
 | ||
| #link_directories( // 该目标需要链接依赖的库的目录,因为是目标是库,无需链接,此设置无
 | ||
| #)
 | ||
| 
 | ||
| aux_source_directory(./src SRC_FILES) // 需要编译的源码文件,此处是src目录下的所有文件
 | ||
| 
 | ||
| set(TARGET_NAME StatusCode) // 设置输出目标名称
 | ||
| add_library(${TARGET_NAME} STATIC ${SRC_FILES})
 | ||
| target_link_libraries(${TARGET_NAME} Log) // 该目标需要依赖的库,这一步很关键,cmake将会根据依赖关系自动去编译需要的依赖库;
 | ||
| 
 | ||
| if ("${COMPILE_IMPROVE_SUPPORT}" MATCHES "true")
 | ||
| add_custom_target( // 静态检测代码
 | ||
|     StatusCode_code_check
 | ||
|     COMMAND ${CLANG_TIDY_EXE}
 | ||
|     -checks='${CLANG_TIDY_CHECKS}'
 | ||
|     --header-filter=.*
 | ||
|     --system-headers=false
 | ||
|     ${SRC_FILES}
 | ||
|     ${CLANG_TIDY_CONFIG}
 | ||
|     -p ${PLATFORM_PATH}/cmake-shell
 | ||
|     WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/StatusCode
 | ||
| )
 | ||
| file(GLOB_RECURSE HEADER_FILES *.h)
 | ||
| add_custom_target( // 格式化代码
 | ||
|     StatusCode_code_format
 | ||
|     COMMAND ${CLANG_FORMAT_EXE}
 | ||
|     -style=file
 | ||
|     -i ${SRC_FILES} ${HEADER_FILES}
 | ||
|     WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/StatusCode
 | ||
| )
 | ||
| add_custom_command(
 | ||
|     TARGET ${TARGET_NAME}
 | ||
|     PRE_BUILD
 | ||
|     COMMAND make StatusCode_code_check
 | ||
|     COMMAND make StatusCode_code_format
 | ||
|     WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/
 | ||
| )
 | ||
| endif()
 | ||
| 
 | ||
| define_file_name(${TARGET_NAME}) // 该函数实现log库打印时,可打印文件名
 | ||
| 
 | ||
| file(GLOB_RECURSE INSTALL_HEADER_FILES include/*.h)
 | ||
| install(FILES ${INSTALL_HEADER_FILES} DESTINATION include) // 拷贝头文件到安装目录
 | ||
| ```
 | ||
| 
 | ||
| ### 1.4.3. 通过CMakeLists.txt构建开源库
 | ||
| 
 | ||
|   通过CMakeLists.txt构建开源库,可以自动关联第三方的依赖库,编译的时候自动按需编译对应的开源库。
 | ||
| 
 | ||
| ```code
 | ||
| 
 | ||
| include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake)
 | ||
| include(build/config_base.cmake)
 | ||
| set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH})
 | ||
| set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH})
 | ||
| 
 | ||
| include_directories(
 | ||
|     ./src
 | ||
|     ./include
 | ||
|     ${UTILS_SOURCE_PATH}/StatusCode/include
 | ||
|     ${UTILS_SOURCE_PATH}/Log/include
 | ||
|     ${EXTERNAL_SOURCE_PATH}/libconfig/libconfig-1.7.3/lib
 | ||
| )
 | ||
| # link_directories(
 | ||
| #     ${EXTERNAL_SOURCE_PATH}/libconfig/libconfig-1.7.3/lib/.libs
 | ||
| # )
 | ||
| 
 | ||
| aux_source_directory(./src SRC_FILES)
 | ||
| 
 | ||
| set(TARGET_NAME ConfigBase)
 | ||
| add_library(${TARGET_NAME} STATIC ${SRC_FILES})
 | ||
| target_link_libraries(${TARGET_NAME} StatusCode Log libconfig.a)
 | ||
| 
 | ||
| if ("${COMPILE_IMPROVE_SUPPORT}" MATCHES "true")
 | ||
| add_custom_target(
 | ||
|     ConfigBase_code_check
 | ||
|     COMMAND ${CLANG_TIDY_EXE}
 | ||
|     -checks='${CLANG_TIDY_CHECKS}'
 | ||
|     --header-filter=.*
 | ||
|     --system-headers=false
 | ||
|     ${SRC_FILES}
 | ||
|     ${CLANG_TIDY_CONFIG}
 | ||
|     -p ${PLATFORM_PATH}/cmake-shell
 | ||
|     WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/ConfigBase
 | ||
| )
 | ||
| add_custom_command(
 | ||
|     TARGET ${TARGET_NAME}
 | ||
|     PRE_BUILD
 | ||
|     COMMAND make ConfigBase_code_check
 | ||
|     WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/
 | ||
| )
 | ||
| file(GLOB_RECURSE HEADER_FILES *.h)
 | ||
| add_custom_target(
 | ||
|     ConfigBase_code_format
 | ||
|     COMMAND ${CLANG_FORMAT_EXE}
 | ||
|     -style=file
 | ||
|     -i ${SRC_FILES}  ${HEADER_FILES}
 | ||
|     WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/ConfigBase
 | ||
| )
 | ||
| add_custom_command(
 | ||
|     TARGET ${TARGET_NAME}
 | ||
|     PRE_BUILD
 | ||
|     COMMAND make ConfigBase_code_check
 | ||
|     COMMAND make ConfigBase_code_format
 | ||
|     WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/
 | ||
| )
 | ||
| endif()
 | ||
| 
 | ||
| # build libconfig before make libConfigBase.a
 | ||
| add_custom_command(
 | ||
|     # OUTPUT ${EXTERNAL_SOURCE_PATH}/libconfig/libconfig-1.7.3/lib/.libs/libconfig.a
 | ||
|     OUTPUT ${EXTERNAL_LIBS_OUTPUT_PATH}/libconfig.a // 创建这个开源库输出文件的生成方法
 | ||
|     COMMAND echo "Build libconfig-1.7.3. COMPILE_HOST = ${COMPILE_HOST}"
 | ||
|     # COMMAND tar zxvf libconfig-1.7.3.tar.gz
 | ||
|     COMMAND sh build_libconfig.sh ${TARGET_PLATFORM} ${COMPILE_HOST}
 | ||
|     # 把生成的开源库拷贝到输出目录
 | ||
|     COMMAND mv ${EXTERNAL_SOURCE_PATH}/libconfig/libconfig-1.7.3/lib/.libs/libconfig.a ${EXTERNAL_LIBS_OUTPUT_PATH}/libconfig.a
 | ||
|     WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/libconfig/
 | ||
| )
 | ||
| add_custom_target(
 | ||
|     libconfig.a // 创建一个库目标
 | ||
|     # DEPENDS ${EXTERNAL_SOURCE_PATH}/libconfig/libconfig-1.7.3/lib/.libs/libconfig.a
 | ||
|     DEPENDS ${EXTERNAL_LIBS_OUTPUT_PATH}/libconfig.a // 这个目标依赖开源库的编译输出文件
 | ||
| )
 | ||
| 
 | ||
| define_file_name(${TARGET_NAME})
 | ||
| config_owner(${TARGET_NAME})
 | ||
| 
 | ||
| file(GLOB_RECURSE INSTALL_HEADER_FILES include/*.h)
 | ||
| install(FILES ${INSTALL_HEADER_FILES} DESTINATION include)
 | ||
| ```
 | 
