592 lines
21 KiB
CMake
592 lines
21 KiB
CMake
include_guard(GLOBAL)
|
|
include(CMakePackageConfigHelpers)
|
|
include(CheckCXXCompilerFlag)
|
|
check_cxx_compiler_flag("-fsanitize=address" HAS_ASAN)
|
|
|
|
include(${CMAKE_CURRENT_LIST_DIR}/core_file_operation.cmake)
|
|
include(${CMAKE_CURRENT_LIST_DIR}/core_string_operation.cmake)
|
|
|
|
|
|
# TODO: 库设计思路
|
|
# list 操作 https://cmake.org/cmake/help/v3.27/command/list.html#list
|
|
# string 操作 https://cmake.org/cmake/help/v3.27/command/string.html#string
|
|
# property文档: https://cmake.org/cmake/help/v3.31/manual/cmake-commands.7.html
|
|
# Initial definition
|
|
# https://cmake.org/cmake/help/v3.31/command/define_property.html
|
|
# 在target上的属性
|
|
# https://cmake.org/cmake/help/v3.31/manual/cmake-properties.7.html#target-properties
|
|
|
|
|
|
#macro(__append_prop target prop)
|
|
# set(_cur_temp_list_ "${ARGN}")
|
|
# get_property(_temp_list_ TARGET ${target} PROPERTY ${prop})
|
|
# list(APPEND _temp_list_ ${_cur_temp_list_})
|
|
# set_property(TARGET ${target} PROPERTY ${prop} ${_temp_list_})
|
|
#endmacro()
|
|
|
|
macro(__append_prop target prop)
|
|
set(_cur_temp_list_ "${ARGN}")
|
|
# 取已有属性值(如果没设置过,避免报错)
|
|
get_property(_temp_list_ TARGET ${target} PROPERTY ${prop} SET)
|
|
if(_temp_list_)
|
|
get_property(_temp_list_ TARGET ${target} PROPERTY ${prop})
|
|
else()
|
|
set(_temp_list_ "")
|
|
endif()
|
|
# 追加新值
|
|
list(APPEND _temp_list_ ${_cur_temp_list_})
|
|
# 去重
|
|
list(REMOVE_DUPLICATES _temp_list_)
|
|
# 写回 target 属性
|
|
set_property(TARGET ${target} PROPERTY ${prop} ${_temp_list_})
|
|
endmacro()
|
|
|
|
|
|
# 自定义函数:向 ELF 文件添加自定义段并嵌入自定义内容
|
|
function(_add_custom_section_to_elf_with_temp_file target_name section_name content)
|
|
# 创建一个临时文件
|
|
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/temp)
|
|
set(TEMP_METADATA_FILE "${CMAKE_BINARY_DIR}/temp/${target_name}_${section_name}_metadata.txt")
|
|
# 将自定义内容写入临时文件
|
|
file(WRITE ${TEMP_METADATA_FILE} "${content}")
|
|
# 确保 objcopy 命令可用
|
|
if (NOT CMAKE_OBJCOPY)
|
|
find_program(OBJCOPY objcopy)
|
|
if (NOT OBJCOPY)
|
|
message(FATAL_ERROR "objcopy not found!")
|
|
endif ()
|
|
else ()
|
|
set(OBJCOPY ${CMAKE_OBJCOPY})
|
|
endif ()
|
|
get_target_property(EXE_PATH ${target_name} _default_name_)
|
|
# message("${target_name} EXE_PATH ${EXE_PATH}")
|
|
# 使用 add_custom_command 延迟执行,确保在目标构建之后执行
|
|
add_custom_command(TARGET ${target_name} POST_BUILD
|
|
COMMAND ${OBJCOPY} --add-section ${section_name}=${TEMP_METADATA_FILE} ${EXE_PATH}
|
|
COMMENT "Adding ${section_name} section to ${target_name}"
|
|
)
|
|
endfunction()
|
|
|
|
function(_add_metadata_win target_name)
|
|
set(FILE_VERSION "1,0,0,0") # 文件版本
|
|
set(PRODUCT_VERSION "1,0,0,0") # 产品版本
|
|
set(COMPANY_NAME "wang-yong-chen")
|
|
set(FILE_DESCRIPTION "${G_Architecture_Name}") #描述
|
|
set(INTERNAL_NAME "INTERNAL_NAME")
|
|
set(COPYRIGHT "wang-yong-chen") #版权
|
|
set(ORIGINAL_FILENAME "${target_name}_${G_Architecture_Name}") #原始文件名
|
|
set(PRODUCT_NAME "${target_name}")
|
|
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/temp)
|
|
set(TEMP_METADATA_FILE "${CMAKE_BINARY_DIR}/temp/${target_name}_${section_name}_metadata.rc")
|
|
configure_file(${CMAKE_SOURCE_DIR}/0_cmake_library/rc.in ${TEMP_METADATA_FILE})
|
|
|
|
# 有了这个所以不需要链接空文件占位了
|
|
target_sources(${target_name} PRIVATE "${TEMP_METADATA_FILE}")
|
|
endfunction()
|
|
|
|
|
|
|
|
|
|
macro(__core_load_base_prop)
|
|
get_property(_type_ TARGET ${_name_} PROPERTY _type)
|
|
get_property(_rely_domain_ TARGET ${_name_} PROPERTY _rely_domain_)
|
|
get_property(_include_domain_ TARGET ${_name_} PROPERTY _include_domain_)
|
|
endmacro()
|
|
function(_create _type_ _name_)
|
|
set(_rely_domain_)
|
|
set(_include_domain_)
|
|
if (_type_ MATCHES "sys")
|
|
set(_rely_domain_ PUBLIC)
|
|
set(_include_domain_ PUBLIC)
|
|
add_executable(${_name_})
|
|
set_target_properties(${_name_} PROPERTIES SUFFIX ".sys")
|
|
_target_isolate_global(${_name_})
|
|
endif ()
|
|
if (_type_ MATCHES "sys_lib")
|
|
set(_rely_domain_ PUBLIC)
|
|
set(_include_domain_ PUBLIC)
|
|
endif ()
|
|
if (_type_ MATCHES "custom")
|
|
set(_rely_domain_ PUBLIC)
|
|
set(_include_domain_ PUBLIC)
|
|
add_custom_target(${_name_})
|
|
endif ()
|
|
if (_type_ MATCHES "object")
|
|
set(_rely_domain_ PRIVATE)
|
|
set(_include_domain_ PRIVATE)
|
|
add_library(${_name_} OBJECT )
|
|
endif ()
|
|
if (_type_ MATCHES "interface")
|
|
set(_rely_domain_ INTERFACE)
|
|
set(_include_domain_ INTERFACE)
|
|
add_library(${_name_} INTERFACE)
|
|
endif ()
|
|
if (_type_ MATCHES "exe")
|
|
set(_rely_domain_ PRIVATE)
|
|
set(_include_domain_ PRIVATE)
|
|
add_executable(${_name_})
|
|
target_compile_definitions(${_name_} PRIVATE "${_name_}_build_exe")
|
|
if (MSVC)
|
|
set_property(TARGET ${_name_} PROPERTY _default_name_ "${_name_}.exe")
|
|
else ()
|
|
set_property(TARGET ${_name_} PROPERTY _default_name_ "${_name_}")
|
|
endif ()
|
|
endif ()
|
|
if (_type_ MATCHES "lib")
|
|
set(_rely_domain_ PRIVATE)
|
|
set(_include_domain_ PRIVATE)
|
|
add_library(${_name_} STATIC)
|
|
target_compile_definitions(${_name_} PRIVATE "${_name_}_build_lib")
|
|
if (MSVC)
|
|
set_property(TARGET ${_name_} PROPERTY _default_name_ "${_name_}.lib")
|
|
else ()
|
|
set_property(TARGET ${_name_} PROPERTY _default_name_ "lib${_name_}.a")
|
|
endif ()
|
|
endif ()
|
|
if (_type_ MATCHES "dll")
|
|
set(_rely_domain_ PRIVATE)
|
|
set(_include_domain_ PRIVATE)
|
|
add_library(${_name_} SHARED ${empty_file})
|
|
target_compile_definitions(${_name_} PRIVATE "${_name_}_build_dll")
|
|
if (MSVC)
|
|
set_property(TARGET ${_name_} PROPERTY _default_name_ "${_name_}.dll")
|
|
else ()
|
|
set_property(TARGET ${_name_} PROPERTY _default_name_ "lib${_name_}.so")
|
|
endif ()
|
|
endif ()
|
|
set_property(TARGET ${_name_} PROPERTY _id ${_name_})
|
|
set_property(TARGET ${_name_} PROPERTY _type ${_type_})
|
|
set_property(TARGET ${_name_} PROPERTY _rely_domain_ ${_rely_domain_})
|
|
set_property(TARGET ${_name_} PROPERTY _include_domain_ ${_include_domain_})
|
|
|
|
|
|
|
|
|
|
if (
|
|
_type_ MATCHES "exe" OR
|
|
_type_ MATCHES "lib" OR
|
|
_type_ MATCHES "dll"
|
|
)
|
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
set(content "")
|
|
string(APPEND content "[arch]:${G_Architecture_Name} ")
|
|
string(APPEND content "[author]: wang-yong-chen\n")
|
|
_add_custom_section_to_elf_with_temp_file(${_name_} info "${content}")
|
|
else ()
|
|
_add_metadata_win(${_name_})
|
|
endif ()
|
|
_attach_target(${_name_} "")
|
|
else()
|
|
# 其他类型不能使用下面的选项处理
|
|
return()
|
|
endif ()
|
|
|
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|
target_compile_options(
|
|
${_name_} ${_rely_domain_}
|
|
-fvisibility=hidden
|
|
-fvisibility-inlines-hidden
|
|
-Wall
|
|
-Wextra
|
|
-Wpedantic
|
|
-Wshadow
|
|
-Wconversion
|
|
-Wsign-conversion
|
|
)
|
|
endif()
|
|
|
|
|
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
|
|
|
get_directory_property(current_compile_options COMPILE_OPTIONS)
|
|
|
|
target_compile_options(
|
|
${_name_} ${_rely_domain_}
|
|
/wd4819
|
|
/utf-8
|
|
/Zc:preprocessor /DNOMINMAX /D_USE_MATH_DEFINES /EHsc /bigobj
|
|
)
|
|
|
|
|
|
|
|
|
|
#add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
|
if (${CMAKE_BUILD_TYPE} STREQUAL "Release")
|
|
# /PROFILE 是 Microsoft Visual Studio 中的一个链接选项,用于生成可用于性能分析的可执行文件。
|
|
# 性能分析最好不用debug
|
|
target_link_options(${_name_} ${_rely_domain_} /PROFILE)
|
|
else()
|
|
# target_link_options(${_name_} ${_rely_domain_} DbgHelp)
|
|
endif ()
|
|
#不要加这句话 Release 在很多时候是
|
|
#set(global_public_compile_definition ${CMAKE_BUILD_TYPE})
|
|
target_compile_options(${_name_} ${_rely_domain_})
|
|
# target_compile_options(${_name_} ${_rely_domain_} /EHc-) # 可能会重复添加也没有关系
|
|
|
|
|
|
# 默认启用 C++ 异常和 SEH(结构化异常处理)
|
|
|
|
#/EHsc:默认启用 C++ 异常 和 结构化异常处理(SEH)。适用于大多数 C++ 项目,这种模式会让 C++ 异常和 SEH 异常都得到处理。您可以将这一行保留,并根据需要修改。
|
|
#/EHs:启用 结构化异常处理(SEH),但禁用 C++ 异常处理。这种设置通常用于低级编程,例如与 Windows API 或 COM 接口打交道时。将这一行解注释来启用此选项。
|
|
#/EHa:启用所有异常(包括 C++ 异常 和 SEH 异常)。这种设置适用于需要处理所有类型异常的情况。
|
|
#/EHc-:禁用 C++ 异常(即禁用 throw 和 catch),但 SEH 仍然启用。这会完全禁用 C++ 异常的支持,适用于对性能有高要求,且不依赖 C++ 异常的场景。
|
|
|
|
else ()
|
|
# 这样不可以继承
|
|
|
|
|
|
# set_target_properties(${_name_} PROPERTIES
|
|
# BUILD_RPATH "$ORIGIN:$ORIGIN/../lib:$ORIGIN/lib"
|
|
# )
|
|
# target_link_options(${_name_} ${_rely_domain_} "-Wl,-rpath,$ORIGIN:$ORIGIN/../lib:$ORIGIN/lib")
|
|
# target_link_options(${_name_} ${_rely_domain_} "-fno-exceptions")
|
|
|
|
# -fsanitize=address 和 -g 其实是两个独立的编译选项:
|
|
# -fsanitize=address:启用 AddressSanitizer(内存检测)
|
|
# -g:生成调试信息(这样报错时能看到源码行号)
|
|
# 它们可以分开用,但建议一起用!
|
|
|
|
|
|
target_compile_options(
|
|
${_name_} ${_rely_domain_}
|
|
-Wall -Wextra -Werror=return-type
|
|
)
|
|
set(USE_RUNPATH 1)
|
|
if (${USE_RUNPATH})
|
|
target_link_options(${_name_} ${_rely_domain_}
|
|
-Wl,--enable-new-dtags
|
|
)
|
|
else()
|
|
target_link_options(${_name_} ${_rely_domain_}
|
|
-Wl,--disable-new-dtags
|
|
)
|
|
endif()
|
|
|
|
|
|
|
|
if (HAS_ASAN)
|
|
#message(STATUS "支持 AddressSanitizer")
|
|
target_compile_options(${_name_} ${_rely_domain_} -fsanitize=address)
|
|
target_link_options(${_name_} ${_rely_domain_} -fsanitize=address)
|
|
else ()
|
|
#message(STATUS "不支持 AddressSanitizer")
|
|
endif ()
|
|
endif ()
|
|
endfunction()
|
|
|
|
|
|
|
|
|
|
|
|
function(_depend_Ex _name_ _cur_dependency_list_var_name_)
|
|
__check_none_extr_params(${ARGC} "${ARGN}" "${ARGV}")
|
|
__append_prop(${_name_} _dependency_list_ ${${_cur_dependency_list_var_name_}})
|
|
get_property(_rely_domain_ TARGET ${_name_} PROPERTY _rely_domain_)
|
|
|
|
foreach (_need_by_ ${${_cur_dependency_list_var_name_}})
|
|
__append_prop(${_need_by_} _need_by_list_ ${_name_})
|
|
|
|
# message("======== ${_name_} rely ${_need_by_}")
|
|
target_link_libraries(${_name_} ${_rely_domain_}
|
|
"${_need_by_}"
|
|
)
|
|
endforeach ()
|
|
endfunction()
|
|
|
|
|
|
# 刷新一些自己重新解释的属性 看看这个是否有用· TODO: https://cmake.org/cmake/help/v3.31/command/define_property.html#command:define_property
|
|
function(_prase_update _name_)
|
|
set(has_qt 0)
|
|
# 自身是否标记 use_qt
|
|
get_property(_has_qt_prop TARGET ${_name_} PROPERTY _use_qt_ SET)
|
|
if(_has_qt_prop)
|
|
get_property(_qt_value TARGET ${_name_} PROPERTY _use_qt_)
|
|
if(_qt_value)
|
|
set(has_qt 1)
|
|
endif()
|
|
endif()
|
|
# 如果自身没 Qt,就检查依赖
|
|
if(NOT has_qt)
|
|
get_property(_cur_dependency_list TARGET ${_name_} PROPERTY _dependency_list_)
|
|
foreach (_need_by_ ${_cur_dependency_list})
|
|
get_property(_qt_flag TARGET ${_need_by_} PROPERTY _use_qt_ SET)
|
|
if(_qt_flag)
|
|
get_property(_qt_value TARGET ${_need_by_} PROPERTY _use_qt_)
|
|
if(_qt_value)
|
|
set(has_qt 1)
|
|
break()
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
|
|
# 如果确定需要 Qt,则开启自动 moc/uic/rcc
|
|
if(has_qt)
|
|
set_target_properties(${_name_} PROPERTIES
|
|
AUTOMOC ON
|
|
AUTOUIC ON
|
|
AUTORCC ON
|
|
)
|
|
endif()
|
|
endfunction()
|
|
|
|
|
|
|
|
macro(__glob _suffix_)
|
|
if (_ext_ STREQUAL ".${_suffix_}")
|
|
set(_cur_abs_list_name_ _abs_${_name_}_${_base_name_}_${_suffix_})
|
|
set(_cur_rel_list_name_ _rel_${_name_}_${_base_name_}_${_suffix_})
|
|
list(APPEND ${_cur_abs_list_name_} ${_abs_})
|
|
file(RELATIVE_PATH _rel_ ${_base_path_} ${_abs_})
|
|
list(APPEND ${_cur_rel_list_name_} ${_rel_})
|
|
list(APPEND _srcs_ ${_abs_})
|
|
continue()
|
|
endif ()
|
|
endmacro()
|
|
macro(__att _suffix_)
|
|
# set(_cur_abs_list_name_ _abs_${_name_}_${_base_name_}_${_suffix_})
|
|
# set(_cur_rel_list_name_ _rel_${_name_}_${_base_name_}_${_suffix_})
|
|
# set_property(TARGET ${_name_} PROPERTY ${_suffix_}_${_base_name_} ${${_cur_abs_list_name_}})
|
|
# set_property(TARGET ${_name_} PROPERTY rel_${_suffix_}_${_base_name_} ${${_cur_rel_list_name_}})
|
|
endmacro()
|
|
|
|
function(_attach_include_dir_Ex _name_ file_list_var_name)
|
|
__append_prop(${_name_} _attach_include_list_ ${${file_list_var_name}})
|
|
set(_includes_ ${${file_list_var_name}})
|
|
__core_load_base_prop()
|
|
if (_type_ MATCHES "interface")
|
|
target_include_directories(${_name_} ${_include_domain_} "${_includes_}")
|
|
elseif (_type_ MATCHES "object")
|
|
target_include_directories(${_name_} ${_include_domain_} "${_includes_}")
|
|
elseif (_type_ MATCHES "custom")
|
|
elseif (_type_ MATCHES "lib")
|
|
target_include_directories(${_name_} ${_include_domain_} "${_includes_}")
|
|
elseif (_type_ MATCHES "dll")
|
|
target_include_directories(${_name_} ${_include_domain_} "${_includes_}")
|
|
elseif (_type_ MATCHES "exe")
|
|
target_include_directories(${_name_} ${_include_domain_} "${_includes_}")
|
|
elseif (_type_ MATCHES "sys")
|
|
target_include_directories(${_name_} ${_include_domain_} "${_includes_}")
|
|
endif ()
|
|
endfunction()
|
|
|
|
function(_attach_source_file_Ex _name_ file_list_var_name)
|
|
__append_prop(${_name_} _attach_file_list_ ${${file_list_var_name}})
|
|
__core_load_base_prop()
|
|
set(_srcs_ ${${file_list_var_name}})
|
|
if (_type_ MATCHES "interface")
|
|
target_sources(${_name_} INTERFACE "${_srcs_}")
|
|
elseif (_type_ MATCHES "object")
|
|
target_sources(${_name_} PRIVATE "${_srcs_}")
|
|
elseif (_type_ MATCHES "custom")
|
|
elseif (_type_ MATCHES "lib")
|
|
target_sources(${_name_} PRIVATE "${_srcs_}")
|
|
elseif (_type_ MATCHES "dll")
|
|
target_sources(${_name_} PRIVATE "${_srcs_}")
|
|
elseif (_type_ MATCHES "exe")
|
|
target_sources(${_name_} PRIVATE "${_srcs_}")
|
|
elseif (_type_ MATCHES "sys")
|
|
target_sources(${_name_} PRIVATE "${_srcs_}")
|
|
endif ()
|
|
endfunction()
|
|
|
|
function(_attach_source_dir_Ex _name_ _list_var_)
|
|
__check_none_extr_params(${ARGC} "${ARGN}" "${ARGV}")
|
|
__append_prop(${_name_} _attach_source_list_ ${${_list_var_}})
|
|
set(_base_path_)
|
|
set(_srcs_)
|
|
set(_rels_)
|
|
__core_load_base_prop()
|
|
set(build_path_list)
|
|
foreach (_base_path_ ${${_list_var_}})# 检查路径是否是目录
|
|
if(NOT IS_DIRECTORY "${_base_path_}")
|
|
message(WARNING "The path '${_base_path_}' is not a valid directory.")
|
|
endif()
|
|
get_filename_component(_base_name_ "${_base_path_}" NAME)
|
|
file(GLOB_RECURSE _files_ ${_base_path_}/*.*)
|
|
foreach (_abs_ ${_files_})
|
|
get_filename_component(_ext_ ${_abs_} EXT)
|
|
# string(TOLOWER "${_ext_}" _ext_) # 可选:转小写以统一判断
|
|
__glob(h)
|
|
__glob(cpp)
|
|
__glob(c)
|
|
__glob(hpp)
|
|
__glob(qrc)
|
|
__glob(qml)
|
|
__glob(cc)
|
|
__glob(ui)
|
|
__glob(ipp)
|
|
endforeach ()
|
|
__att(h)
|
|
__att(cpp)
|
|
__att(c)
|
|
__att(hpp)
|
|
__att(qrc)
|
|
__att(qml)
|
|
__att(cc)
|
|
__att(ui)
|
|
__att(ipp)
|
|
endforeach ()
|
|
if(NOT _srcs_)
|
|
message(FATAL_ERROR "${_name_} empty ${_list_var_}")
|
|
endif()
|
|
if (_type_ MATCHES "interface")
|
|
target_sources(${_name_} ${_rely_domain_} "${_srcs_}")
|
|
elseif (_type_ MATCHES "object")
|
|
target_sources(${_name_} ${_rely_domain_} "${_srcs_}")
|
|
elseif (_type_ MATCHES "custom")
|
|
elseif (_type_ MATCHES "lib")
|
|
target_sources(${_name_} ${_rely_domain_} "${_srcs_}")
|
|
elseif (_type_ MATCHES "dll")
|
|
target_sources(${_name_} ${_rely_domain_} "${_srcs_}")
|
|
elseif (_type_ MATCHES "exe")
|
|
target_sources(${_name_} ${_rely_domain_} "${_srcs_}")
|
|
elseif (_type_ MATCHES "sys")
|
|
target_sources(${_name_} ${_rely_domain_} "${_srcs_}")
|
|
endif ()
|
|
endfunction()
|
|
|
|
|
|
|
|
# 遍历如果是目录就添加源码 并且上一级 include
|
|
#function(_attach_Ex _name_ _cur_attach_include_list_var_name_)
|
|
# set(source_dir_list)
|
|
# set(source_file_list)
|
|
# set(include_dir_list)
|
|
# foreach(_base_path_ ${${_cur_attach_include_list_var_name_}})
|
|
# if(EXISTS "${_base_path_}")
|
|
# #message(STATUS "存在: ${_base_path_}")
|
|
# if(IS_DIRECTORY "${_base_path_}")
|
|
# #message(STATUS "是目录")
|
|
# list(APPEND source_dir_list ${_base_path_})
|
|
# get_filename_component(include_dir "${_base_path_}/../" REALPATH)
|
|
# list(APPEND include_dir_list ${include_dir})
|
|
# else()
|
|
# #message(STATUS "是文件")
|
|
# list(APPEND source_file_list ${build_path})
|
|
# endif()
|
|
# else()
|
|
# message(STATUS "不存在: ${_base_path_}")
|
|
# endif()
|
|
# endforeach()
|
|
# _attach_source_file_Ex(${_name_} source_file_list)
|
|
# _attach_source_dir_Ex(${_name_} source_dir_list)
|
|
# _attach_include_dir_Ex(${_name_} include_dir_list)
|
|
#endfunction()
|
|
|
|
|
|
|
|
|
|
# 用于遍历所有目标及其依赖一起安装
|
|
function(__bfs_traverse_targets _prop_name_ _init_target_list_ _ret_name_)
|
|
set(_visited_targets_ "") # 存储已经访问过的目标
|
|
set(_queue_ ${${_init_target_list_}}) # 初始化队列,将根目标放入队列
|
|
while (_queue_)
|
|
list(POP_FRONT _queue_ _current_target_)
|
|
if ("${_current_target_}" IN_LIST _visited_targets_)
|
|
continue()
|
|
endif ()
|
|
list(APPEND _visited_targets_ ${_current_target_})
|
|
get_property(_deps_ TARGET ${_current_target_} PROPERTY ${_prop_name_})
|
|
if (_deps_)
|
|
foreach (_dep_ IN LISTS _deps_)
|
|
if (NOT "${_dep_}" IN_LIST _visited_targets_)
|
|
list(APPEND _queue_ ${_dep_})
|
|
endif ()
|
|
endforeach ()
|
|
endif ()
|
|
endwhile ()
|
|
list(REMOVE_DUPLICATES _visited_targets_)
|
|
set(${_ret_name_} ${_visited_targets_} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
|
|
|
|
# 核心的三个函数
|
|
function(_depend _name_)
|
|
set(_temp_list_ "${ARGN}")
|
|
_depend_Ex(${_name_} _temp_list_)
|
|
endfunction()
|
|
|
|
#function(_attach _name_)
|
|
# set(_temp_list_ "${ARGN}")
|
|
# _attach_Ex(${_name_} _temp_list_)
|
|
#endfunction()
|
|
|
|
|
|
|
|
# 不能传入目录 传目录是空文件夹
|
|
function(_attach_post_build_file_Ex _name_ _file_list_var_name_)
|
|
add_custom_command(
|
|
TARGET ${_name_}
|
|
POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
${${_file_list_var_name_}}
|
|
${CMAKE_CURRENT_BINARY_DIR}
|
|
COMMENT "拷贝配置文件到目标目录"
|
|
)
|
|
endfunction()
|
|
|
|
function(_attach_post_build_dir_Ex _name_ _dir_list_var_name_)
|
|
add_custom_command(
|
|
TARGET ${_name_}
|
|
POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
${${_file_list_var_name_}}
|
|
${CMAKE_CURRENT_BINARY_DIR}
|
|
COMMENT "拷贝配置文件到目标目录"
|
|
)
|
|
endfunction()
|
|
|
|
function(_attach_post_build_file _name_)
|
|
set(_temp_list_ "${ARGN}")
|
|
_attach_post_build_file_Ex(${_name_} _temp_list_)
|
|
endfunction()
|
|
|
|
function(_attach_post_build_dir _name_)
|
|
set(_temp_list_ "${ARGN}")
|
|
_attach_post_build_dir_Ex(${_name_} _temp_list_)
|
|
endfunction()
|
|
|
|
function(_attach_include_dir _name_)
|
|
set(_temp_list_ "${ARGN}")
|
|
_attach_include_dir_Ex(${_name_} _temp_list_)
|
|
endfunction()
|
|
|
|
function(_attach_source_file _name_)
|
|
set(_temp_list_ "${ARGN}")
|
|
_attach_source_file_Ex(${_name_} _temp_list_)
|
|
endfunction()
|
|
|
|
function(_attach_source_dir _name_)
|
|
set(_temp_list_ "${ARGN}")
|
|
_attach_source_dir_Ex(${_name_} _temp_list_)
|
|
endfunction()
|
|
|
|
|
|
# 此目录为 _attach_file 安装的时候相对的目录
|
|
function(_set_main_dir _name_ _main_dir_)
|
|
set_property(TARGET ${_name_} PROPERTY _main_dir_ "${_main_dir_}")
|
|
endfunction()
|
|
|
|
|
|
|
|
|
|
function(_attach_test_Ex target_list_var_name)
|
|
if (NOT GTest_FOUND)
|
|
find_package(GTest)
|
|
endif()
|
|
if (NOT GTest_FOUND)
|
|
add_subdirectory(${CMAKE_SOURCE_DIR}/3rdParty/GTest)
|
|
endif()
|
|
foreach(target ${${target_list_var_name}})
|
|
get_property(_rely_domain_ TARGET ${target} PROPERTY _rely_domain_)
|
|
target_link_libraries(${target} ${_rely_domain_} GTest::gtest GTest::gmock)
|
|
target_compile_definitions(${target} ${_rely_domain_} _USE_GTEST)
|
|
endforeach()
|
|
endfunction()
|
|
|
|
function(_attach_test)
|
|
set(_temp_list_ "${ARGN}")
|
|
_attach_test_Ex(_temp_list_)
|
|
endfunction() |