前面一篇文章。编程配置 – Android CMake CMakeLists.txt 构建配置文件

    這是一個 CMake generator expression。 像 $<…> 這樣的表達式是在 CMake 2.8 中引入的 generator exressions。這些表達式的主要特徵是它們在構建時進行評估,而不是在配置時進行評估,就像正常的 CMake 變量一樣。 https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html

    1. if current_configuration == "Debug"
    2. output "Release"
    3. if current_configureation == "Release"
    4. output "Debug"
    5. set(RCFILE app.rc)
    6. source_group("rcfile" FILES ${RCFILE})
    7. set_source_files_properties(${RCFILE} PROPERTIES LANGUAGE RC)
    8. # MacOS -Winconsistent-missing-override
    9. # GCC 5.1 -Werror=suggest-override
    10. # -pthread for g++
    11. SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -pthread -Werror=return-type")
    • 编写合格的 C 代码(1):通过编译选项将特定警告视为错误 CMake CMakeLists.txt 高级特性 - 图1
    • 编写合格的 C 代码(2):实现简易日志库 CMake CMakeLists.txt 高级特性 - 图2
    • 开启 安全开发生命周期(SDL)检查
    • CMakeLists.txt 中的设定
      1. if (CMAKE_SYSTEM_NAME MATCHES "Windows")
      2. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /we4715 /we4013 /we4431 /we4133 /we4716 /we6244 /we6246 /we4457 /we4456 /we4172 /we4700 /we4477 /we4018 /we4047")
      3. set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} /we4715 /we4013 /we4431 /we4133 /we4716 /we6244 /we6246 /we4457 /we4456 /we4172 /we4700 /we4477 /we4018 /we4047")
      4. elseif (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin")
      5. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=return-type -Werror=shadow -Werror=return-local-addr -Werror=uninitialized -Werror=format -Werror=sign-compare -Werror=int-conversion")
      6. set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=return-type -Werror=shadow -Werror=return-local-addr -Werror=uninitialized -Werror=format -Werror=sign-compare -Werror=int-conversion")
      7. endif()
    • Visual Studio 中的设定
      • 项目属性 -> 配置属性 ->C/C++-> 高级 -> 将特定的警告视为错误,填入相应的警告、错误代号:
        • 4715;4013;4431;4133;4716;6244;6246;4457;4456;4172;4700;4477;4018;4047
    • 基于 Makefile
      • CFLAGS += -Werror=implicit-function-declaration -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=return-type -Werror=shadow -Werror=return-local-addr -Werror=uninitialized -Werror=format -Werror=sign-compare -Werror=int-conversion
    • 直接调用 gcc/clang
      • gcc xxx.c -Werror=implicit-function-declaration -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=return-type -Werror=shadow -Werror=return-local-addr -Werror=uninitialized -Werror=format -Werror=sign-compare -Werror=int-conversion

    C4715:不是所有的控件路径都返回值。Two ways of doing this #pragma warning (error : 4715) Compiling with /we4715 option passed to cl.exe

    PlatformWindowsMSVC.cmake CMake CMakeLists.txt 高级特性 - 图3

    1. # MacOS -Winconsistent-missing-override
    2. # GCC 5.1 -Werror=suggest-override
    3. SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") # -pthread for g++
    4. if (MSVC)
    5. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /we4715") # makes missing return as error
    6. endif()
    7. # version specific compile flags
    8. # 1800: Visual Studio 12 2013
    9. # 1900: Visual Studio 14 2015
    10. if (MSVC_VERSION VERSION_LESS 1900)
    11. list(APPEND DEFAULT_COMPILE_FLAGS
    12. <<CONFIG:Debug>: /Zi> # this is set in RelWithDebInfo builds for all MSVC versions
    13. <<CONFIG:RelNoOptimization>: /Zi>
    14. )
    15. else() # Visual Studio 14 2015 as minimum
    16. list(APPEND DEFAULT_COMPILE_FLAGS
    17. /Zc:referenceBinding /Zc:strictStrings /Zc:throwingNew
    18. # allow native edit and continue
    19. <<CONFIG:Debug>: /ZI>
    20. <<CONFIG:RelNoOptimization>: /ZI>
    21. # Enable compiler generation of Control Flow Guard security checks. (incompatible with /ZI)
    22. <<CONFIG:Release>: /guard:cf>
    23. <<CONFIG:RelWithDebInfo>: /guard:cf>
    24. )
    25. endif()

    from
    CMake CMakeLists.txt 高级特性 - 图6 from CMake CMakeLists.txt 高级特性 - 图7

    1. source_group(main FILES ${SOURCES})
    2. source_group(math FILES ${MATHSRC})
    3. source_group(math\\matrix FILES ${MATSRC})
    4. source_group(uav FILES ${UAVSRC})
    5. # Create the source groups for source tree with root at CMAKE_CURRENT_SOURCE_DIR.
    6. source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_LIST})
    7. # https://github.com/juj/MathGeoLib/blob/master/CommonOptions.cmake
    8. # Add the global _DEBUG flag from WIN32 platform to all others, which is universally used in MGL to
    9. # perform debug-mode-specific compilation.
    10. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
    11. set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
    12. if (CMAKE_CL_64)
    13. add_definitions(-D_WIN64)
    14. endif()
    15. set(JSON_BuildTests OFF CACHE INTERNAL "") # 外面
    16. # 里面:
    17. option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
    18. if (BUILD_TESTING AND JSON_BuildTests) ...

    from CMake CMakeLists.txt 高级特性 - 图8

    1. cmake_minimum_required(VERSION 3.1)
    2. project(hello)
    3. function(assign_source_group)
    4. foreach(_source IN ITEMS ${ARGN})
    5. if (IS_ABSOLUTE "${_source}")
    6. file(RELATIVE_PATH _source_rel "${CMAKE_CURRENT_SOURCE_DIR}" "${_source}")
    7. else()
    8. set(_source_rel "${_source}")
    9. endif()
    10. get_filename_component(_source_path "${_source_rel}" PATH)
    11. string(REPLACE "/" "\\" _source_path_msvc "${_source_path}")
    12. source_group("${_source_path_msvc}" FILES "${_source}")
    13. endforeach()
    14. endfunction(assign_source_group)
    15. function(my_add_executable)
    16. foreach(_source IN ITEMS ${ARGN})
    17. assign_source_group(${_source})
    18. endforeach()
    19. add_executable(${ARGV})
    20. endfunction(my_add_executable)
    21. my_add_executable(hello include/hello.hpp src/hello.cpp)
    22. # group source on visual project
    23. # setup_project_group(PROJ_SRCS ${PROJ_SRCS} CUR_DIR ${CUR_DIR})
    24. function(setup_project_group)
    25. CMAKE_PARSE_ARGUMENTS(
    26. ARGV "" "CUR_DIR" "PROJ_SRCS"
    27. ${ARGN}
    28. )
    29. foreach(source IN LISTS ARGV_PROJ_SRCS)
    30. # get source path
    31. get_filename_component(source_path ${source} PATH)
    32. # get source relative path
    33. string(REPLACE "${ARGV_CUR_DIR}/./" "" source_relative ${source_path})
    34. if (MSVC OR XCODE)
    35. # get group name
    36. string(REPLACE "/" "\\" group_name ${source_relative})
    37. else()
    38. set(group_name ${source_relative})
    39. endif()
    40. if ("${source_relative}" STREQUAL "${source_path}")
    41. source_group("${group_name}" FILES "${source}")
    42. # no need group because source is in $ARGV_CUR_DIR
    43. else()
    44. # setup project group
    45. source_group("${group_name}" FILES "${source}")
    46. endif()
    47. endforeach()
    48. endfunction()
    49. function(add_source_group)
    50. CMAKE_PARSE_ARGUMENTS(
    51. ARGV "" "GROUP_NAME" "PROJ_SRCS"
    52. ${ARGN}
    53. )
    54. foreach(source IN LISTS ARGV_PROJ_SRCS)
    55. # setup project group
    56. source_group("${ARGV_GROUP_NAME}" FILES "${source}")
    57. endforeach()
    58. endfunction()
    59. function(target_precompiled_header project_target pch_source)
    60. if (MSVC)
    61. get_filename_component(pch_basename ${pch_source} NAME_WE)
    62. set(pch_header "${pch_basename}.h")
    63. set_target_properties(${project_target} PROPERTIES COMPILE_FLAGS "/Yu${pch_header}")
    64. set_source_files_properties(${pch_source} PROPERTIES COMPILE_FLAGS "/Yc${pch_header}")
    65. endif(MSVC)
    66. endfunction()

    可以看到,Moo 这个宏的表现与 C 语言中的宏类似,仅仅是做字符串的替换; Foo 函数里 arg 则是被赋值为 var 的值,在 Foo 内部可以修改这个 arg 变量的值。

    1. set(var "ABC")
    2. macro(Moo arg)
    3. message("arg = ${arg}")
    4. set(arg "abc")
    5. message("# After change the value of arg.")
    6. message("arg = ${arg}")
    7. endmacro()
    8. message("=== Call macro ===")
    9. Moo(${var})
    10. function(Foo arg)
    11. message("arg = ${arg}")
    12. set(arg "abc")
    13. message("# After change the value of arg.")
    14. message("arg = ${arg}")
    15. endfunction()
    16. message("=== Call function ===")
    17. Foo(${var})
    18. /Users/userk/codes/local_codes/cmake_test/build cmake ..
    19. === Call macro ===
    20. arg = ABC
    21. # After change the value of arg.
    22. arg = ABC
    23. === Call function ===
    24. arg = ABC
    25. # After change the value of arg.
    26. arg = abc

    7.4 用指定参数定义函数或宏 | bookstack.cn 7.5 重新定义函数和宏 | bookstack.cn


    2022-04-14: review

    参考资料快照



    https://sunocean.life/blog/blog/2021/02/26/CMakeLists-Advanced