# ============================================================================== # 宏定义:CREATE_LIBRARY_FROM_DIRS # 参数 1: TARGET_NAME - 要生成的库的名称 # 参数 2: LIB_TYPE - 库类型(STATIC 或 SHARED) # 参数 3: SOURCE_DIRS - 需要扫描源码的目录列表(分号分隔的字符串) # 参数 4: EXCLUDE_FILES - 需要额外过滤的文件名列表(分号分隔的字符串,支持正则) # ============================================================================== macro(create_library_from_dirs TARGET_NAME LIB_TYPE SOURCE_DIRS EXCLUDE_FILES) set(ALL_SOURCES "") add_library(${TARGET_NAME} ${LIB_TYPE} "") # 1. 遍历传入的每一个目录 foreach(DIR ${SOURCE_DIRS}) # 统一处理相对路径和绝对路径 if(NOT IS_ABSOLUTE "${DIR}") set(DIR "${CMAKE_CURRENT_SOURCE_DIR}/${DIR}") endif() # 检查目录是否存在,防止写错路径导致报错 if(EXISTS "${DIR}") # 2. 收集当前目录下所有的 .c, .s, .S 文件 file(GLOB ALL_FILES "${DIR}/*.c" "${DIR}/*.s" "${DIR}/*.S" ) target_include_directories(${TARGET_NAME} PUBLIC ${DIR}) message(STATUS "[${TARGET_NAME}] INCLUDE ${DIR}") foreach(FILE_PATH ${ALL_FILES}) # 获取纯文件名(例如:Compiler_GNUC.c),方便精准匹配 get_filename_component(FILE_NAME "${FILE_PATH}" NAME) # 检查是否匹配自定义的排除列表 set(SHOULD_EXCLUDE FALSE) foreach(EX_PATTERN ${EXCLUDE_FILES}) # 支持完整文件名匹配或正则表达式匹配 if("${FILE_NAME}" STREQUAL "${EX_PATTERN}" OR "${FILE_NAME}" MATCHES "${EX_PATTERN}") set(SHOULD_EXCLUDE TRUE) break() endif() endforeach() # 4. 执行过滤判断 if(FILE_PATH MATCHES "\\.t\\.c$") # 过滤单元测试文件 list(APPEND UNIT_TEST_SOURCES ${FILE_PATH}) elseif(SHOULD_EXCLUDE) # 过滤用户指定的特定文件 message(STATUS "[${TARGET_NAME}] EXCLUDED specific file: ${FILE_NAME} from target ${TARGET_NAME}") else() # 留下的才是有效的库源码 list(APPEND ALL_SOURCES ${FILE_PATH}) endif() endforeach() else() message(WARNING "[${TARGET_NAME}] Directory does not exist: ${DIR}") endif() endforeach() # 4. 确保找到了有效的源代码再创建库 list(LENGTH ALL_SOURCES SOURCE_COUNT) if(SOURCE_COUNT GREATER 0) # add_library(${TARGET_NAME} ${LIB_TYPE} ${ALL_SOURCES}) target_sources(${TARGET_NAME} PUBLIC ${ALL_SOURCES}) message(STATUS "[${TARGET_NAME}] Created ${LIB_TYPE} library '${TARGET_NAME}' with ${SOURCE_COUNT} source files.") foreach (item IN LISTS ALL_SOURCES) message(STATUS "[${TARGET_NAME}] SOURCE: ${item}") endforeach () else() message(FATAL_ERROR "No valid source files found for target: ${TARGET_NAME}") endif() list(LENGTH UNIT_TEST_SOURCES UNIT_TEST_COUNT) if(UNIT_TEST_COUNT GREATER 0) foreach (item IN LISTS UNIT_TEST_SOURCES) get_filename_component(TestUnit ${item} NAME_WLE) message(STATUS "[${TARGET_NAME}] TEST: ${TestUnit} - ${item}") add_executable(${TestUnit} ${item}) target_link_libraries(${TestUnit} PUBLIC ${TARGET_NAME}) endforeach () endif () endmacro()