前面一篇文章。编程配置 – Android CMake CMakeLists.txt 构建配置文件
# 对文件下分组
set(AllFile ${KV_SRC} ${KV_INCLUDE})
foreach(fileItem ${AllFile})
get_filename_component(PARENT_DIR "${fileItem}" DIRECTORY)
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "" GROUP "${PARENT_DIR}")
string(REPLACE "/" "\\" GROUP "${GROUP}")
set(GROUP "${GROUP}")
source_group("${GROUP}" FILES "${fileItem}")
endforeach()
这是一个 CMake generator expression。 像 $<…>这样的表达式是在 CMake 2.8 中引入的 generator exressions。这些表达式的主要特征是它们在构建时进行评估,而不是在配置时进行评估,就像正常的 CMake 变量一样。 https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html
# https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html
# $<IF:condition,true_string,false_string>
# set(COPY_SOURCE_DIR "${OpenCV_DIR}/bin/$<$<CONFIG:Debug>:Debug>$<$<NOT:$<CONFIG:Debug>>:Release>")
# set(COPY_SOURCE_DIR "${OpenCV_DIR}/bin/$<IF:$<CONFIG:Debug>,Debug,Release>")
CopyOpenCV("opencv_core453$<$<CONFIG:Debug>:d>.dll")
CopyOpenCV("opencv_imgproc453$<$<CONFIG:Debug>:d>.dll")
set(RCFILE app.rc)
source_group("rcfile" FILES ${RCFILE})
set_source_files_properties(${RCFILE} PROPERTIES LANGUAGE RC)
# MacOS -Winconsistent-missing-override
# GCC 5.1 -Werror=suggest-override
# -pthread for g++
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -pthread -Werror=return-type")
/we4715
函数每个分支都必须有返回值。/we4263
'function' : member function does not override any base class virtual member function/we4264
'virtual_function' : no override available for virtual member function from base 'class'; function is hidden/we4700
VS 下的开关。gcc 下用 -Werror=uninitialized。if (CMAKE_SYSTEM_NAME MATCHES "Windows")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /we4715 /we4013 /we4431 /we4133 /we4716 /we4457 /we4456 /we4172 /we4700 /we4477 /we4018 /we4047")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /we4715 /we4013 /we4431 /we4133 /we4716 /we4457 /we4456 /we4172 /we4700 /we4477 /we4018 /we4047")
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin")
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")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_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")
endif()
C4715:不是所有的控件路径都返回值。Two ways of doing this
#pragma warning (error : 4715)
Compiling with /we4715
option passed to cl.exe
# MacOS -Winconsistent-missing-override
# GCC 5.1 -Werror=suggest-override
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") # -pthread for g++
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /we4715") # makes missing return as error
endif()
# version specific compile flags
# 1800: Visual Studio 12 2013
# 1900: Visual Studio 14 2015
if (MSVC_VERSION VERSION_LESS 1900)
list(APPEND DEFAULT_COMPILE_FLAGS
<<CONFIG:Debug>: /Zi> # this is set in RelWithDebInfo builds for all MSVC versions
<<CONFIG:RelNoOptimization>: /Zi>
)
else() # Visual Studio 14 2015 as minimum
list(APPEND DEFAULT_COMPILE_FLAGS
/Zc:referenceBinding /Zc:strictStrings /Zc:throwingNew
# allow native edit and continue
<<CONFIG:Debug>: /ZI>
<<CONFIG:RelNoOptimization>: /ZI>
# Enable compiler generation of Control Flow Guard security checks. (incompatible with /ZI)
<<CONFIG:Release>: /guard:cf>
<<CONFIG:RelWithDebInfo>: /guard:cf>
)
endif()
source_group(main FILES ${SOURCES})
source_group(math FILES ${MATHSRC})
source_group(math\\matrix FILES ${MATSRC})
source_group(uav FILES ${UAVSRC})
# Create the source groups for source tree with root at CMAKE_CURRENT_SOURCE_DIR.
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_LIST})
# https://github.com/juj/MathGeoLib/blob/master/CommonOptions.cmake
# Add the global _DEBUG flag from WIN32 platform to all others, which is universally used in MGL to
# perform debug-mode-specific compilation.
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
if (CMAKE_CL_64)
add_definitions(-D_WIN64)
endif()
set(JSON_BuildTests OFF CACHE INTERNAL "") # 外面
# 里面:
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
if (BUILD_TESTING AND JSON_BuildTests) ...
cmake_minimum_required(VERSION 3.1)
project(hello)
function(assign_source_group)
foreach(_source IN ITEMS ${ARGN})
if (IS_ABSOLUTE "${_source}")
file(RELATIVE_PATH _source_rel "${CMAKE_CURRENT_SOURCE_DIR}" "${_source}")
else()
set(_source_rel "${_source}")
endif()
get_filename_component(_source_path "${_source_rel}" PATH)
string(REPLACE "/" "\\" _source_path_msvc "${_source_path}")
source_group("${_source_path_msvc}" FILES "${_source}")
endforeach()
endfunction(assign_source_group)
function(my_add_executable)
foreach(_source IN ITEMS ${ARGN})
assign_source_group(${_source})
endforeach()
add_executable(${ARGV})
endfunction(my_add_executable)
my_add_executable(hello include/hello.hpp src/hello.cpp)
# group source on visual project
# setup_project_group(PROJ_SRCS ${PROJ_SRCS} CUR_DIR ${CUR_DIR})
function(setup_project_group)
CMAKE_PARSE_ARGUMENTS(
ARGV "" "CUR_DIR" "PROJ_SRCS"
${ARGN}
)
foreach(source IN LISTS ARGV_PROJ_SRCS)
# get source path
get_filename_component(source_path ${source} PATH)
# get source relative path
string(REPLACE "${ARGV_CUR_DIR}/./" "" source_relative ${source_path})
if (MSVC OR XCODE)
# get group name
string(REPLACE "/" "\\" group_name ${source_relative})
else()
set(group_name ${source_relative})
endif()
if ("${source_relative}" STREQUAL "${source_path}")
source_group("${group_name}" FILES "${source}")
# no need group because source is in $ARGV_CUR_DIR
else()
# setup project group
source_group("${group_name}" FILES "${source}")
endif()
endforeach()
endfunction()
function(add_source_group)
CMAKE_PARSE_ARGUMENTS(
ARGV "" "GROUP_NAME" "PROJ_SRCS"
${ARGN}
)
foreach(source IN LISTS ARGV_PROJ_SRCS)
# setup project group
source_group("${ARGV_GROUP_NAME}" FILES "${source}")
endforeach()
endfunction()
function(target_precompiled_header project_target pch_source)
if (MSVC)
get_filename_component(pch_basename ${pch_source} NAME_WE)
set(pch_header "${pch_basename}.h")
set_target_properties(${project_target} PROPERTIES COMPILE_FLAGS "/Yu${pch_header}")
set_source_files_properties(${pch_source} PROPERTIES COMPILE_FLAGS "/Yc${pch_header}")
endif(MSVC)
endfunction()
可以看到,Moo 这个宏的表现与 C 语言中的宏类似,仅仅是做字符串的替换; Foo 函数里 arg 则是被赋值为 var 的值,在 Foo 内部可以修改这个 arg 变量的值。
set(var "ABC")
macro(Moo arg)
message("arg = ${arg}")
set(arg "abc")
message("# After change the value of arg.")
message("arg = ${arg}")
endmacro()
message("=== Call macro ===")
Moo(${var})
function(Foo arg)
message("arg = ${arg}")
set(arg "abc")
message("# After change the value of arg.")
message("arg = ${arg}")
endfunction()
message("=== Call function ===")
Foo(${var})
➜ /Users/userk/codes/local_codes/cmake_test/build cmake ..
=== Call macro ===
arg = ABC
# After change the value of arg.
arg = ABC
=== Call function ===
arg = ABC
# After change the value of arg.
arg = abc