set(prefix __PSC_) macro(_clear_and_cache name) set(_var_name "${prefix}${name}") if( "${${_var_name}}" STREQUAL "") set(${_var_name} ${${name}} CACHE STRING "" FORCE) set(${name} "" CACHE STRING "" FORCE) endif() endmacro() macro(_clear_and_cache2 name) set(${prefix}${name} ${${name}} PARENT_SCOPE) set(${name} "" PARENT_SCOPE) endmacro() set(build_type_list DEBUG RELEASE RELWITHDEBINFO MINSIZEREL) function(_clear_env) set(language_list C CXX) foreach(language IN LISTS language_list) set(list CMAKE_${language}_FLAGS CMAKE_${language}_STANDARD_LIBRARIES ) foreach(bt IN LISTS build_type_list) list(APPEND list CMAKE_${language}_FLAGS_${bt}) endforeach() foreach(li IN LISTS list) _clear_and_cache(${li}) endforeach() endforeach() foreach(language IN LISTS language_list) set(list CMAKE_${language}_CREATE_CONSOLE_EXE CMAKE_${language}_CREATE_WIN32_EXE ) foreach(li IN LISTS list) _clear_and_cache2(${li}) endforeach() endforeach() set(target_type_list EXE MODULE SHARED STATIC ) foreach(target_type IN LISTS target_type_list) set(list CMAKE_${target_type}_LINKER_FLAGS) foreach(bt IN LISTS build_type_list) list(APPEND list CMAKE_${target_type}_LINKER_FLAGS_${bt}) endforeach() foreach(li IN LISTS list) _clear_and_cache(${li}) endforeach() endforeach() endfunction() function(_target_isolate_global tgt) # ========== 1. 编译选项隔离 ========== set_target_properties(${tgt} PROPERTIES COMPILE_OPTIONS "" ) # ========== 2. 宏定义隔离 ========== set_target_properties(${tgt} PROPERTIES COMPILE_DEFINITIONS "" ) # ========== 3. 头文件路径隔离 ========== set_target_properties(${tgt} PROPERTIES INCLUDE_DIRECTORIES "" ) # ========== 4. 链接选项隔离 ========== set_target_properties(${tgt} PROPERTIES LINK_FLAGS "" LINK_FLAGS_DEBUG "" LINK_FLAGS_RELEASE "" LINK_OPTIONS "" ) # ========== 5. 运行时库隔离 ========== set_target_properties(${tgt} PROPERTIES C_STANDARD_LIBRARIES "" CXX_STANDARD_LIBRARIES "" ) # Windows MSVC 运行时隔离 set_target_properties(${tgt} PROPERTIES WIN32_EXECUTABLE FALSE ) if(MSVC) set_target_properties(${tgt} PROPERTIES MSVC_RUNTIME_LIBRARY "" MSVC_DEBUG_INFORMATION_FORMAT "" MSVC_RUNTIME_CHECKS "" MSVC_RUNTIME_LIBRARY "" ) endif() endfunction() function(_get_mapped_target_type out_var tgt) if(NOT TARGET ${tgt}) message(FATAL_ERROR "get_mapped_target_type: target '${tgt}' does not exist") endif() get_target_property(_cmake_type ${tgt} TYPE) if(_cmake_type STREQUAL "EXECUTABLE") set(_mapped_type "EXE") elseif(_cmake_type STREQUAL "MODULE_LIBRARY") set(_mapped_type "MODULE") elseif(_cmake_type STREQUAL "SHARED_LIBRARY") set(_mapped_type "SHARED") elseif(_cmake_type STREQUAL "STATIC_LIBRARY") set(_mapped_type "STATIC") else() set(_mapped_type "") endif() set(${out_var} "${_mapped_type}" PARENT_SCOPE) endfunction() macro(_gather_list list_name input_name) set(cur_list) separate_arguments(cur_list NATIVE_COMMAND "${${input_name}}") list(APPEND ${list_name} ${cur_list}) endmacro() # 给target添加上默认的 编译选项 # _build_type 填入空值的话那么就是使用默认构建类型 function(_attach_target _target _build_type) if(NOT TARGET "${_target}") return() endif() if(_build_type STREQUAL "") set(_build_type ${CMAKE_BUILD_TYPE}) endif() string(TOUPPER "${_build_type}" _build_type) if(NOT _build_type IN_LIST build_type_list) message(FATAL_ERROR "attach_target Invalid build type: ${_build_type}") endif() # ---------- 防止同一个 target / build_type 重复 attach ---------- get_property(_has_attached_build_types TARGET "${_target}" PROPERTY PSC_ATTACHED_BUILD_TYPES SET ) if(_has_attached_build_types) get_property(_attached_build_types TARGET "${_target}" PROPERTY PSC_ATTACHED_BUILD_TYPES ) else() set(_attached_build_types "") endif() if("${_build_type}" IN_LIST _attached_build_types) message(STATUS "skip already attached target: ${_target}, build_type=${_build_type}") return() else() message(STATUS "attached target: ${_target}, build_type=${_build_type}") endif() set(target_type) set(link_options) set(flags) set(link_libraries) set(language CXX) _get_mapped_target_type(target_type ${_target}) _gather_list(link_options ${prefix}CMAKE_${target_type}_LINKER_FLAGS) _gather_list(link_options ${prefix}CMAKE_${target_type}_LINKER_FLAGS_${_build_type}) _gather_list(flags ${prefix}CMAKE_${language}_FLAGS) _gather_list(flags ${prefix}CMAKE_${language}_FLAGS_${_build_type}) _gather_list(link_libraries ${prefix}CMAKE_${language}_STANDARD_LIBRARIES) # ---------- 列表自身去重 ---------- list(REMOVE_DUPLICATES link_options) list(REMOVE_DUPLICATES flags) list(REMOVE_DUPLICATES link_libraries) set(options) set(definitions) foreach(_flag IN LISTS flags) # /DWIN32, /D_WINDOWS, /DNDEBUG # -DWIN32 也兼容 if(_flag MATCHES "^[/\\-]D(.+)$") set(_def "${CMAKE_MATCH_1}") # 去掉可能存在的外层双引号,例如 /D"NAME=VALUE" string(REGEX REPLACE "^\"(.*)\"$" "\\1" _def "${_def}") list(APPEND definitions "${_def}") else() list(APPEND options "${_flag}") endif() endforeach() list(REMOVE_DUPLICATES options) list(REMOVE_DUPLICATES definitions) # ---------- 非空才调用,避免空 PUBLIC 调用污染 target_link_libraries 模式 ---------- if(link_options) target_link_options(${_target} PUBLIC ${link_options}) endif() if(options) target_compile_options(${_target} PUBLIC ${options}) endif() if(definitions) target_compile_definitions(${_target} PUBLIC ${definitions}) endif() if(link_libraries) target_link_libraries(${_target} PUBLIC ${link_libraries}) endif() # ---------- 标记已经 attach 过 ---------- list(APPEND _attached_build_types "${_build_type}") list(REMOVE_DUPLICATES _attached_build_types) set_property( TARGET "${_target}" PROPERTY PSC_ATTACHED_BUILD_TYPES "${_attached_build_types}" ) # if(G_Enable_CCache AND MSVC) # set_target_properties("${_target}" PROPERTIES # MSVC_DEBUG_INFORMATION_FORMAT "Embedded" # ) # endif() endfunction() # 这个库的影响是会 影响 add_subdirectory 的目标 针对 不同的选项没了 默认优化参数 # 可以通过 最外层拿 BUILDSYSTEM_TARGETS 但是考虑 递归add_subdirectory 只能覆盖拦截处理 function(add_subdirectory) set(source_dir "${ARGV0}") # message("start ============ add_subdirectory ARGV: ${ARGV} ${CMAKE_CURRENT_LIST_FILE}") _add_subdirectory(${ARGV}) if(IS_ABSOLUTE "${source_dir}") set(source_dir_abs "${source_dir}") else() get_filename_component( source_dir_abs "${CMAKE_CURRENT_SOURCE_DIR}/${source_dir}" ABSOLUTE ) endif() get_property( subdir_targets DIRECTORY "${source_dir_abs}" PROPERTY BUILDSYSTEM_TARGETS ) #message(STATUS "targets in ${source_dir}: ${subdir_targets}") if(subdir_targets) foreach(target IN LISTS subdir_targets) if(NOT TARGET "${target}") continue() endif() get_target_property(target_type "${target}" TYPE) if(target_type STREQUAL "INTERFACE_LIBRARY" OR target_type STREQUAL "UTILITY" OR target_type STREQUAL "UNKNOWN_LIBRARY" OR target_type STREQUAL "OBJECT_LIBRARY" # OR target_type STREQUAL "STATIC_LIBRARY" ) message(STATUS "skip target: ${target}, type=${target_type}") continue() endif() _attach_target("${target}" "") endforeach() endif() # message("end ============ add_subdirectory ARGV: ${ARGV}") endfunction() macro(attach_current_source_dir ) get_property(_targets DIRECTORY "." PROPERTY BUILDSYSTEM_TARGETS) foreach(target IN LISTS _targets) get_target_property(target_type "${target}" TYPE) if(target_type STREQUAL "INTERFACE_LIBRARY" OR target_type STREQUAL "UTILITY" OR target_type STREQUAL "UNKNOWN_LIBRARY" OR target_type STREQUAL "OBJECT_LIBRARY" # OR target_type STREQUAL "STATIC_LIBRARY" ) #message(STATUS "skip target: ${target}, type=${target_type}") continue() endif() _attach_target("${target}" "") endforeach() endmacro() #/DRIVER #/SUBSYSTEM:NATIVE #/ENTRY:DriverEntry #/NODEFAULTLIB #/DRIVER #/DRIVER:WDM #/DRIVER:UPONLY #/SUBSYSTEM:CONSOLE 用户态控制台程序 #/SUBSYSTEM:WINDOWS 用户态 GUI 程序 #/SUBSYSTEM:NATIVE Native 子系统,驱动常用