[关闭]
@iStarLee 2018-11-06T21:18:45.000000Z 字数 7530 阅读 421

Learning Cmake Notes

cmake


Reference

1 编译一个完整的STM32工程

这是一个完整的STM32F407工程,这是一个工程第一级目录下的CMakeLists.txt

  1. # CMake minimum version
  2. cmake_minimum_required (VERSION 3.1)
  3. # Project Infomation
  4. project( blinky )
  5. # 使用汇编编译
  6. enable_language(ASM)
  7. # add sub进入到这个文件夹下执行它的CMakeLists.txt
  8. add_subdirectory(Drivers)
  9. # Reset output path
  10. set (EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
  11. set (LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
  12. # STDLIB
  13. set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
  14. # 包含头文件路径
  15. include_directories (Drivers/CMSIS/Device/Include )
  16. # 包含源码文件
  17. aux_source_directory (User/Source/ DIR_USER_SRCS)
  18. # CC AR LD AS
  19. set (CMAKE_C_COMPILER "arm-none-eabi-gcc")
  20. set (CMAKE_C_AR "arm-none-eabi-ar")
  21. set (CMAKE_ASM_COMPILER "arm-none-eabi-gcc")
  22. # CFLAGS
  23. set (CMAKE_C_FLAGS "-g -mthumb -fno-builtin -mcpu=cortex-m4 -mfpu=fpv5-sp-d16 -mfloat-abi=softfp -Wall -std=gnu99 -ffunction-sections -fdata-sections -fomit-frame-pointer -mabi=aapcs -fno-unroll-loops -ffast-math -ftree-vectorize" CACHE INTERNAL "c compiler flags")
  24. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D USE_HAL_DRIVER -D STM32F407xx")
  25. # CXXFLAGS
  26. set (CMAKE_CXX_FLAGS "-g -mthumb -fno-builtin -mcpu=cortex-m4 -mfpu=fpv5-sp-d16 -mfloat-abi=softfp -Wall -std=c++11 -ffunction-sections -fdata-sections -fomit-frame-pointer -mabi=aapcs -fno-unroll-loops -ffast-math -ftree-vectorize" CACHE INTERNAL "cxx compiler flags")
  27. # ASMFLAGS
  28. set (CMAKE_ASM_FLAGS "-g -mthumb -mcpu=cortex-m4 -mfpu=fpv5-sp-d16 -mfloat-abi=softfp -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags")
  29. # LDFLAGS
  30. set (CMAKE_EXE_LINKER_FLAGS "-g -Wl,--gc-sections -mthumb -mcpu=cortex-m4 -mfpu=fpv5-sp-d16 -mfloat-abi=softfp -mabi=aapcs" CACHE INTERNAL "executable linker flags")
  31. set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${CMAKE_SOURCE_DIR}/ldscripts/STM32F407VGTx_FLASH.ld")
  32. # Load the the extern library
  33. # add_library (STM32F4xx_HAL_Driver STATIC IMPORTED)
  34. # set_property (TARGET STM32F4xx_HAL_Driver PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/Drivers/Build/lib/libSTM32F4xx_HAL_Driver.a)
  35. # 这句话和上面两句作用一样
  36. link_directories(${CMAKE_SOURCE_DIR}/Drivers/Build/lib )
  37. # Load the the extern freertos library
  38. # add_library (STM32F4xx_FreeRTOS STATIC IMPORTED)
  39. # set_property (TARGET STM32F4xx_FreeRTOS PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/FreeRTOS/Build/lib/libSTM32F4xx_FreeRTOS.a)
  40. # 这句话和上面两句作用一样
  41. link_directories(${CMAKE_SOURCE_DIR}/FreeRTOS/Build/lib )
  42. # Generate the target 生成目标文件
  43. add_executable (${CMAKE_PROJECT_NAME}.elf ${DIR_USER_SRCS} ${DIR_BSP_SRCS} ${DIR_CMSIS_SRCS} ${CMAKE_SOURCE_DIR}/Drivers/CMSIS/Device/Source/startup/startup_stm32f407xx.s)
  44. # Link the library to the target 使用库
  45. target_link_libraries (${CMAKE_PROJECT_NAME}.elf STM32F4xx_HAL_Driver STM32F4xx_FreeRTOS)
  46. # Generate the binary file 生成二进制文件
  47. add_custom_target (${CMAKE_PROJECT_NAME}.bin ALL arm-none-eabi-objcopy -Obinary "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.bin" DEPENDS ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf)
  48. # Generate the hex file 生成十六进制文件
  49. add_custom_target (${CMAKE_PROJECT_NAME}.hex ALL arm-none-eabi-objcopy -Oihex "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.hex" DEPENDS ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf)
  50. # Echo the size Infomation
  51. add_custom_target (size ALL arm-none-eabi-size "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf" DEPENDS ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.elf)
  52. # Make flash to the board by st-link
  53. add_custom_target (flash COMMAND st-flash write ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_PROJECT_NAME}.bin 0x8000000)
  54. # Make clean-all 添加的自定义命令
  55. add_custom_target (clean-all COMMAND rm -rf ${CMAKE_BINARY_DIR}/*)

2 生成静态库和动态库(共享库)

以生成stm32 官方库为例,部分内容展示了如何生成库的流程

  1. # Reset output path
  2. set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
  3. # Set include path
  4. include_directories( CMSIS/Include )
  5. # The need build source path and build all files
  6. aux_source_directory (STM32F4xx_HAL_Driver/Src DIR_STM32F4xx_HAL_Driver_SRCS)
  7. # CC AR
  8. set(CMAKE_C_COMPILER "arm-none-eabi-gcc")
  9. set(CMAKE_C_AR "arm-none-eabi-ar")
  10. # CFLAGS
  11. set (CMAKE_C_FLAGS "-g -mthumb -fno-builtin -mcpu=cortex-m4 -mfpu=fpv5-sp-d16 -mfloat-abi=softfp -Wall -std=gnu99 -ffunction-sections -fdata-sections -fomit-frame-pointer -mabi=aapcs -fno-unroll-loops -ffast-math -ftree-vectorize" CACHE INTERNAL "c compiler flags")
  12. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSTM32F407xx -DUSE_HAL_DRIVER")
  13. # Generate the target to the static library
  14. add_library (STM32F4xx_HAL_Driver ${DIR_STM32F4xx_HAL_Driver_SRCS})

3 使用configure_file()自定义编译选项

  1. # configure file
  2. configure_file(
  3. "${PROJECT_SOURCE_DIR}/config.h.in"
  4. "${PROJECT_SOURCE_DIR}/config/config.h")
  5. # use configure file
  6. option(USE_CMAKEDEFINE "help string describing USE_CMAKEDEFINE" ON)
  7. if(USE_CMAKEDEFINE)
  8. message(STATUS "use cmake define...")
  9. endif(USE_CMAKEDEFINE)
  10. # use cmake config file ,so include the config.h folder
  11. include_directories (config)

在源文件中编写以下代码

  1. /*use cmake config file*/
  2. #include "config.h"
  3. #ifdef USE_CMAKEDEFINE
  4. #else
  5. #endif

编译过程:

  1. cmake ..
  2. # 便于交互式的选择该变量的值,可以使用 ccmake 命令
  3. ccmake .. # 回车键选择,c配置,g生成
  4. make

4 安装文件

安装分为以下几类

安装的cmake代码写在生成该文件的CMakeLists.txt中。

  1. # 普通文件的安装:
  2. INSTALL(FILES COPYRIGHT README
  3. DESTINATION share/doc/cmake/usual-c)
  4. # 目录的安装:
  5. INSTALL(DIRECTORY doc/
  6. DESTINATION share/doc/cmake/usual-c)
  7. # 非目标文件的可执行程序安装(比如脚本之类):
  8. INSTALL(PROGRAMS runhello.sh
  9. DESTINATION bin)
  10. # 目标文件的安装
  11. # ARCHIVE 特指静态库, LIBRARY 特指动态库, RUNTIME特指可执行目标二进制
  12. INSTALL(TARGETS hello
  13. RUNTIME DESTINATION bin
  14. )
  15. # 安装共享库和头文件
  16. # ARCHIVE 特指静态库, LIBRARY 特指动态库, RUNTIME特指可执行目标二进制
  17. INSTALL(TARGETS hello hello_static
  18. LIBRARY DESTINATION lib
  19. ARCHIVE DESTINATION lib)
  20. INSTALL(FILES hello.h
  21. DESTINATION include/hello)

5 为工程添加测试

  1. # 启用测试
  2. enable_testing()
  3. # 测试程序是否成功运行
  4. add_test (test_run Demo 5 2)
  5. # 测试帮助信息是否可以正常提示
  6. add_test (test_usage Demo)
  7. set_tests_properties (test_usage
  8. PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent")
  9. # 测试 5 的平方
  10. add_test (test_5_2 Demo 5 2)
  11. set_tests_properties (test_5_2
  12. PROPERTIES PASS_REGULAR_EXPRESSION "is 25")
  1. # 定义一个宏,用来简化测试工作
  2. macro (do_test arg1 arg2 result)
  3. add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2})
  4. set_tests_properties (test_${arg1}_${arg2}
  5. PROPERTIES PASS_REGULAR_EXPRESSION ${result})
  6. endmacro (do_test)
  7. # 利用 do_test 宏,测试一系列数据
  8. do_test (5 2 "is 25")
  9. do_test (10 5 "is 100000")
  10. do_test (2 10 "is 1024")

6 增加GDB设置

指定 Debug 模式下开启 -g 选项

  1. set(CMAKE_BUILD_TYPE "Debug")
  2. set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
  3. set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

7 添加环境检查

在config.h.in 文件中,预定义相关的宏变量。

  1. #cmakedefine HAVE_POW

在CMakeLists.txt中

  1. # 检查系统是否支持 pow 函数,放在 configure_file 命令前
  2. include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
  3. check_function_exists (pow HAVE_POW)
  4. # 加入一个配置头文件,用于处理 CMake 对源码的设置
  5. configure_file (
  6. "${PROJECT_SOURCE_DIR}/config.h.in"
  7. "${PROJECT_BINARY_DIR}/config.h"
  8. )
  9. # 是否加入 MathFunctions 库
  10. if (NOT HAVE_POW)
  11. include_directories ("${PROJECT_SOURCE_DIR}/math")
  12. add_subdirectory (math)
  13. set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
  14. endif (NOT HAVE_POW)

8 为代码添加版本信息

在config.h.in中

  1. // the configured options and settings for Tutorial
  2. #define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@
  3. #define Demo_VERSION_MINOR @Demo_VERSION_MINOR@

在CMakeLists.txt中,放在 configure_file 命令前

  1. set (Demo_VERSION_MAJOR 1)
  2. set (Demo_VERSION_MINOR 0)

在主程序中直接使用该宏

  1. printf("%s Version %d.%d\n",
  2. argv[0],
  3. Demo_VERSION_MAJOR,
  4. Demo_VERSION_MINOR);

9 生成安装包

首先在顶层的 CMakeLists.txt 文件尾部添加下面几行:

  1. # 构建一个 CPack 安装包
  2. include (InstallRequiredSystemLibraries)
  3. set (CPACK_RESOURCE_FILE_LICENSE
  4. "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
  5. set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}")
  6. set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}")
  7. include (CPack)

上面的代码做了以下几个工作:

接下来的工作是像往常一样构建工程,并执行 cpack 命令。

  1. # 生成二进制安装包:
  2. cpack -C CPackConfig.cmake
  3. # 或者生成源码安装包
  4. cpack -C CPackSourceConfig.cmake

生成安装包的本质是把需要安装的文件打包成一个压缩包,最后解压到某个文件夹下。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注