Browse Source

【待合】简化library下的通用构建文件

master
Lizongdi 4 days ago
parent
commit
bc5df871f3
  1. 246
      library/CMakeLists.txt

246
library/CMakeLists.txt

@ -3,105 +3,86 @@ cmake_minimum_required(VERSION 3.10)
get_filename_component(TARGET_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) get_filename_component(TARGET_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(TOUPPER ${TARGET_NAME} TARGET_NAME_UPPER) string(TOUPPER ${TARGET_NAME} TARGET_NAME_UPPER)
if(DEFINED BUILD_${TARGET_NAME_UPPER}_HAS_TEST) # Test / Standalone
set(MY_HAS_TEST ${BUILD_${TARGET_NAME_UPPER}_HAS_TEST}) if(BUILD_${TARGET_NAME_UPPER}_HAS_TEST)
else() option(BUILD_${TARGET_NAME_UPPER}_STANDALONE
set(MY_HAS_TEST OFF) "Build ${TARGET_NAME_UPPER} as a standalone executable" OFF)
endif()
if(MY_HAS_TEST)
option(BUILD_${TARGET_NAME_UPPER}_STANDALONE "Build ${TARGET_NAME_UPPER} as a standalone executable" OFF)
# mark_as_advanced(BUILD_${TARGET_NAME_UPPER}_STANDALONE)
endif() endif()
set(FINAL_MODULE_SRCS "") # vs
set(FLAT_SRC_DIR "${CMAKE_BINARY_DIR}/flat_sources/${TARGET_NAME}")
set(NEED_FLATTEN FALSE)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(IS_TOP_LEVEL TRUE) set(IS_TOP_LEVEL TRUE)
message(STATUS "[${TARGET_NAME}] Detected Top-Level Project. Enabling recursive flatten build.") message(STATUS "[${TARGET_NAME}] Top-level project — enabling recursive flatten build.")
set(NEED_FLATTEN TRUE) set(NEED_FLATTEN TRUE)
else() else()
set(IS_TOP_LEVEL FALSE) set(IS_TOP_LEVEL FALSE)
file(GLOB ALL_C_FILES "*.c") set(NEED_FLATTEN FALSE)
set(MODULE_SRCS "")
foreach(SRC_FILE ${ALL_C_FILES})
get_filename_component(FILE_NAME ${SRC_FILE} NAME)
if(FILE_NAME MATCHES ".*~$" OR FILE_NAME MATCHES "\\.bak$" OR FILE_NAME MATCHES "\\.swp$")
continue()
else()
list(APPEND MODULE_SRCS ${SRC_FILE})
endif()
endforeach()
set(FINAL_MODULE_SRCS ${MODULE_SRCS})
endif() endif()
#
if(NOT NEED_FLATTEN)
file(GLOB MODULE_SRCS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
#
list(FILTER MODULE_SRCS EXCLUDE REGEX ".*[~]$|.*\\.bak$|.*\\.swp$")
endif()
# :
if(NEED_FLATTEN) if(NEED_FLATTEN)
message(STATUS "[${TARGET_NAME}] Searching for files in: ${CMAKE_CURRENT_SOURCE_DIR}") set(FLAT_SRC_DIR "${CMAKE_BINARY_DIR}/flat_sources/${TARGET_NAME}")
file(GLOB_RECURSE ALL_SOURCE_FILES file(GLOB_RECURSE ALL_SOURCE_FILES CONFIGURE_DEPENDS
CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/*.c" "${CMAKE_CURRENT_SOURCE_DIR}/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.h"
) )
set(FILTERED_SOURCE_FILES "") # : / CMake /
set(FILTERED_FILES "")
foreach(SRC_FILE ${ALL_SOURCE_FILES}) foreach(SRC_FILE ${ALL_SOURCE_FILES})
get_filename_component(ABS_FILE ${SRC_FILE} ABSOLUTE) get_filename_component(ABS_FILE ${SRC_FILE} ABSOLUTE)
get_filename_component(FILE_NAME ${SRC_FILE} NAME)
if(ABS_FILE MATCHES "^${CMAKE_BINARY_DIR}") if(ABS_FILE MATCHES "^${CMAKE_BINARY_DIR}")
continue() continue()
endif() endif()
if(FILE_NAME MATCHES "CMakeCCompilerId\\.c$|CMakeTmp")
get_filename_component(FILE_NAME ${SRC_FILE} NAME)
if(FILE_NAME MATCHES "CMakeCCompilerId\\.c$" OR FILE_NAME MATCHES "CMakeTmp")
continue() continue()
endif() endif()
if(FILE_NAME MATCHES "[~]$|\\.bak$|\\.swp$")
if(FILE_NAME MATCHES ".*~$" OR FILE_NAME MATCHES "\\.bak$" OR FILE_NAME MATCHES "\\.swp$")
continue() continue()
endif() endif()
list(APPEND FILTERED_SOURCE_FILES ${SRC_FILE}) list(APPEND FILTERED_FILES ${SRC_FILE})
endforeach() endforeach()
set(ALL_SOURCE_FILES ${FILTERED_SOURCE_FILES}) list(LENGTH FILTERED_FILES FILE_COUNT)
list(LENGTH ALL_SOURCE_FILES FILE_COUNT)
message(STATUS "[${TARGET_NAME}] Found ${FILE_COUNT} valid files after filtering.") message(STATUS "[${TARGET_NAME}] Found ${FILE_COUNT} valid files after filtering.")
if(NOT FILTERED_FILES)
if(NOT ALL_SOURCE_FILES) message(FATAL_ERROR "[${TARGET_NAME}] No valid source files found.")
message(FATAL_ERROR "[${TARGET_NAME}] No valid source files found after filtering.")
endif() endif()
set(FLAT_SRCS_LIST "") # flat
set(FLAT_SRCS "")
set(COPY_COMMANDS "") set(COPY_COMMANDS "")
foreach(SRC_FILE ${FILTERED_FILES})
foreach(SRC_FILE ${ALL_SOURCE_FILES})
get_filename_component(FILE_NAME ${SRC_FILE} NAME) get_filename_component(FILE_NAME ${SRC_FILE} NAME)
get_filename_component(FILE_EXT ${SRC_FILE} EXT) get_filename_component(FILE_EXT ${SRC_FILE} EXT)
set(DEST_FILE "${FLAT_SRC_DIR}/${FILE_NAME}") set(DEST_FILE "${FLAT_SRC_DIR}/${FILE_NAME}")
if(EXISTS "${DEST_FILE}") if(EXISTS "${DEST_FILE}")
message(WARNING "[${TARGET_NAME}] Filename conflict: '${FILE_NAME}'. Skipping ${SRC_FILE}.") message(WARNING "[${TARGET_NAME}] Filename conflict: '${FILE_NAME}', skipping ${SRC_FILE}")
continue() continue()
endif() endif()
list(APPEND COPY_COMMANDS list(APPEND COPY_COMMANDS
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SRC_FILE} ${DEST_FILE} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SRC_FILE} ${DEST_FILE}
) )
if(FILE_EXT STREQUAL ".c") if(FILE_EXT STREQUAL ".c")
list(APPEND FLAT_SRCS_LIST ${DEST_FILE}) list(APPEND FLAT_SRCS ${DEST_FILE})
endif() endif()
endforeach() endforeach()
set(FINAL_MODULE_SRCS ${FLAT_SRCS_LIST}) if(NOT FLAT_SRCS)
message(FATAL_ERROR "[${TARGET_NAME}] No .c files to compile!")
if(NOT FINAL_MODULE_SRCS)
message(FATAL_ERROR "[${TARGET_NAME}] No .c files found to compile!")
endif() endif()
add_custom_target(${TARGET_NAME}_flatten_sources add_custom_target(${TARGET_NAME}_flatten_sources
@ -109,161 +90,124 @@ if(NEED_FLATTEN)
COMMENT "[${TARGET_NAME}] Flattening sources..." COMMENT "[${TARGET_NAME}] Flattening sources..."
BYPRODUCTS ${FLAT_SRC_DIR} BYPRODUCTS ${FLAT_SRC_DIR}
) )
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${FLAT_SRC_DIR}") set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${FLAT_SRC_DIR}")
endif()
set(MODULE_SRCS ${FINAL_MODULE_SRCS}) set(MODULE_SRCS ${FLAT_SRCS})
set_source_files_properties(${MODULE_SRCS} PROPERTIES GENERATED TRUE)
endif()
if(NOT MODULE_SRCS AND NOT NEED_FLATTEN) # header-only INTERFACE
if(NOT IS_TOP_LEVEL) if(NOT MODULE_SRCS AND NOT IS_TOP_LEVEL)
message(STATUS "[${TARGET_NAME}] No source files found. Creating INTERFACE (header-only) library.") message(STATUS "[${TARGET_NAME}] No source files — creating INTERFACE (header-only) library.")
add_library(${TARGET_NAME} INTERFACE) add_library(${TARGET_NAME} INTERFACE)
set(INTERFACE_INCLUDES "") set(INTERFACE_INCLUDES "")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/include") foreach(inc
list(APPEND INTERFACE_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/include") "${CMAKE_CURRENT_SOURCE_DIR}/include"
endif() "${PROJECT_SOURCE_DIR}/include/${TARGET_NAME}"
if(EXISTS "${PROJECT_SOURCE_DIR}/include/${TARGET_NAME}") "${PROJECT_SOURCE_DIR}/include"
list(APPEND INTERFACE_INCLUDES "${PROJECT_SOURCE_DIR}/include/${TARGET_NAME}") )
endif() if(EXISTS "${inc}")
if(EXISTS "${PROJECT_SOURCE_DIR}/include") list(APPEND INTERFACE_INCLUDES "${inc}")
list(APPEND INTERFACE_INCLUDES "${PROJECT_SOURCE_DIR}/include")
endif() endif()
endforeach()
target_include_directories(${TARGET_NAME} INTERFACE ${INTERFACE_INCLUDES}) target_include_directories(${TARGET_NAME} INTERFACE ${INTERFACE_INCLUDES})
message(STATUS "[${TARGET_NAME}] INTERFACE includes: ${INTERFACE_INCLUDES}") message(STATUS "[${TARGET_NAME}] INTERFACE includes: ${INTERFACE_INCLUDES}")
return() return()
endif()
endif() endif()
set(EXPLICIT_STANDALONE OFF) #
if(DEFINED BUILD_${TARGET_NAME_UPPER}_STANDALONE AND BUILD_${TARGET_NAME_UPPER}_STANDALONE) set(SHOULD_BUILD_EXECUTABLE FALSE)
set(EXPLICIT_STANDALONE ON) if(BUILD_${TARGET_NAME_UPPER}_STANDALONE)
endif() set(SHOULD_BUILD_EXECUTABLE TRUE)
elseif(IS_TOP_LEVEL AND MAIN)
set(IMPLICIT_STANDALONE OFF)
if(IS_TOP_LEVEL AND DEFINED MAIN AND MAIN)
set(IMPLICIT_STANDALONE ON)
endif()
if(EXPLICIT_STANDALONE OR IMPLICIT_STANDALONE)
set(SHOULD_BUILD_EXECUTABLE TRUE) set(SHOULD_BUILD_EXECUTABLE TRUE)
else()
set(SHOULD_BUILD_EXECUTABLE FALSE)
endif()
if(NEED_FLATTEN AND FINAL_MODULE_SRCS)
set_source_files_properties(${FINAL_MODULE_SRCS} PROPERTIES GENERATED TRUE)
endif() endif()
#
if(SHOULD_BUILD_EXECUTABLE) if(SHOULD_BUILD_EXECUTABLE)
set(CURRENT_TARGET_NAME ${TARGET_NAME}) add_executable(${TARGET_NAME} ${MODULE_SRCS})
add_executable(${CURRENT_TARGET_NAME} ${MODULE_SRCS}) target_compile_definitions(${TARGET_NAME} PRIVATE MAIN STANDALONE_BUILD)
set_target_properties(${TARGET_NAME} PROPERTIES
if(CMAKE_BUILD_TYPE STREQUAL "Debug") RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output
target_compile_definitions(${CURRENT_TARGET_NAME} PUBLIC DEBUG) )
endif()
target_compile_definitions(${TARGET_NAME} PRIVATE ${GLOBAL_ENABLED_MACROS})
if(NEED_FLATTEN)
add_dependencies(${CURRENT_TARGET_NAME} ${TARGET_NAME}_flatten_sources)
target_include_directories(${CURRENT_TARGET_NAME} PRIVATE ${FLAT_SRC_DIR})
endif()
target_compile_definitions(${CURRENT_TARGET_NAME} PRIVATE MAIN STANDALONE_BUILD)
set_target_properties(${CURRENT_TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output)
message(STATUS "[${TARGET_NAME}] Building Standalone: ${CURRENT_TARGET_NAME} (Sources count: ${MODULE_SRCS})")
else() else()
set(CURRENT_TARGET_NAME ${TARGET_NAME})
if(MY_BUILD_STATIC) if(MY_BUILD_STATIC)
add_library(${TARGET_NAME} STATIC ${MODULE_SRCS}) add_library(${TARGET_NAME} STATIC ${MODULE_SRCS})
elseif(MY_BUILD_SHARED_LIBS)
add_library(${TARGET_NAME} SHARED ${MODULE_SRCS})
else() else()
if(A_BUILD_MAIN_AS_STATIC_LIB)
add_library(${TARGET_NAME} OBJECT ${MODULE_SRCS}) add_library(${TARGET_NAME} OBJECT ${MODULE_SRCS})
else()
add_library(${TARGET_NAME} SHARED ${MODULE_SRCS})
endif()
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(${TARGET_NAME} PUBLIC DEBUG)
endif()
target_compile_definitions(${TARGET_NAME} PRIVATE ${GLOBAL_ENABLED_MACROS})
if(NEED_FLATTEN)
add_dependencies(${CURRENT_TARGET_NAME} ${TARGET_NAME}_flatten_sources)
target_include_directories(${CURRENT_TARGET_NAME} PRIVATE ${FLAT_SRC_DIR})
endif() endif()
set_target_properties(${TARGET_NAME} PROPERTIES set_target_properties(${TARGET_NAME} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output
LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/output
) )
endif() endif()
set(MY_PUBLIC_INCLUDES "") message(STATUS "[${TARGET_NAME}] Configured target: ${TARGET_NAME} (Sources: ${MODULE_SRCS})")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/include") # Flatten
list(APPEND MY_PUBLIC_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/include") if(NEED_FLATTEN)
message(STATUS "[${TARGET_NAME}] Found local include: ${CMAKE_CURRENT_SOURCE_DIR}/include") add_dependencies(${TARGET_NAME} ${TARGET_NAME}_flatten_sources)
target_include_directories(${TARGET_NAME} PRIVATE ${FLAT_SRC_DIR})
endif() endif()
if(EXISTS "${PROJECT_SOURCE_DIR}/include/${TARGET_NAME}") #
list(APPEND MY_PUBLIC_INCLUDES "${PROJECT_SOURCE_DIR}/include/${TARGET_NAME}") target_compile_definitions(${TARGET_NAME}
message(STATUS "[${TARGET_NAME}] Found global sub-include: ${PROJECT_SOURCE_DIR}/include/${TARGET_NAME}") PRIVATE ${GLOBAL_ENABLED_MACROS}
endif() $<$<CONFIG:Debug>:DEBUG>
)
if(EXISTS "${PROJECT_SOURCE_DIR}/include") # Include
list(APPEND MY_PUBLIC_INCLUDES "${PROJECT_SOURCE_DIR}/include") set(MY_PUBLIC_INCLUDES "")
message(STATUS "[${TARGET_NAME}] Found global root include: ${PROJECT_SOURCE_DIR}/include") foreach(inc
endif() "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${PROJECT_SOURCE_DIR}/include/${TARGET_NAME}"
"${PROJECT_SOURCE_DIR}/include"
)
if(EXISTS "${inc}")
list(APPEND MY_PUBLIC_INCLUDES "${inc}")
message(STATUS "[${TARGET_NAME}] Found include: ${inc}")
endif()
endforeach()
if(NOT MY_PUBLIC_INCLUDES) if(NOT MY_PUBLIC_INCLUDES)
if(NEED_FLATTEN)
list(APPEND MY_PUBLIC_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}") list(APPEND MY_PUBLIC_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}")
else() message(STATUS "[${TARGET_NAME}] Fallback include: source dir")
list(APPEND MY_PUBLIC_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
message(STATUS "[${TARGET_NAME}] Fallback to source dir: ${CMAKE_CURRENT_SOURCE_DIR}")
endif() endif()
target_include_directories(${CURRENT_TARGET_NAME} target_include_directories(${TARGET_NAME}
PUBLIC ${MY_PUBLIC_INCLUDES} PUBLIC ${MY_PUBLIC_INCLUDES}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
) )
target_link_libraries(${CURRENT_TARGET_NAME} #
PRIVATE m target_link_libraries(${TARGET_NAME} PRIVATE m)
)
string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME_LOWER) string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME_LOWER)
if(CMAKE_CROSSCOMPILING AND NOT SYSTEM_NAME_LOWER MATCHES "linux|windows|darwin|android") if(CMAKE_CROSSCOMPILING AND NOT SYSTEM_NAME_LOWER MATCHES "linux|windows|darwin|android")
message(STATUS ">>> 检测到裸机/RTOS 环境 (${CMAKE_SYSTEM_NAME}),屏蔽 pthread") message(STATUS ">>> 裸机/RTOS 环境 (${CMAKE_SYSTEM_NAME}),屏蔽 pthread")
else() else()
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
target_link_libraries(${CURRENT_TARGET_NAME} target_link_libraries(${TARGET_NAME}
PUBLIC Threads::Threads PUBLIC Threads::Threads
PRIVATE ${CMAKE_DL_LIBS} PRIVATE ${CMAKE_DL_LIBS}
) )
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(${CURRENT_TARGET_NAME} PRIVATE rt) target_link_libraries(${TARGET_NAME} PRIVATE rt)
endif() endif()
endif() endif()
target_compile_options(${CURRENT_TARGET_NAME} #
PRIVATE target_compile_options(${TARGET_NAME} PRIVATE
-Wall -Wall -Werror
-Werror -ffunction-sections -fdata-sections
$<$<CONFIG:Debug>:-g -O0> $<$<CONFIG:Debug>:-g -O0>
$<$<CONFIG:Release>:-O2> $<$<CONFIG:Release>:-O2>
-ffunction-sections -fdata-sections
) )
target_link_options(${CURRENT_TARGET_NAME} target_link_options(${TARGET_NAME} PRIVATE
PRIVATE
-Wl,--gc-sections -Wl,--gc-sections
$<$<CONFIG:Release>:-s> $<$<CONFIG:Release>:-s>
) )
message(STATUS "[${TARGET_NAME}] Configured target: ${CURRENT_TARGET_NAME}")
Loading…
Cancel
Save