Files
2026-07-28 03:21:34 +08:00

202 lines
7.2 KiB
CMake

cmake_minimum_required(VERSION 3.15)
# 项目根目录
project(InfProjects C)
# 设置默认构建类型(可选)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
# 手动指定项目文件夹列表(根据需要修改)
set(PROJECT_DIRECTORIES
Install
RegistryOverride
Service
# SubstituteExecution
TemplateMatcher
Test
Tools
Update
)
# 设置输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/.bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/.lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/.static")
# 全局编译选项
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
set(CMAKE_C_FLAGS_RELEASE "-O2 -s -fno-stack-protector -fno-PIC")
# 遍历所有子目录
foreach(SUBDIR ${PROJECT_DIRECTORIES})
message(STATUS "Processing directory: ${SUBDIR}")
# 检查目录是否存在
if(NOT IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR})
message(WARNING "Directory ${SUBDIR} does not exist - skipping")
continue()
endif()
# 检查子目录是否有 CMakeLists.txt
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/CMakeLists.txt)
message(WARNING "No CMakeLists.txt in ${SUBDIR} - skipping")
continue()
endif()
message(STATUS "Found valid project directory: ${SUBDIR}")
# 清除可能存在的旧缓存变量
unset(${SUBDIR}_PROJECT_NAME CACHE)
unset(${SUBDIR}_MAIN_SOURCE_FILE CACHE)
unset(${SUBDIR}_RESOURCE_FILE CACHE)
unset(${SUBDIR}_MANIFEST_FILE CACHE)
unset(${SUBDIR}_BUILD_AS_DLL CACHE)
unset(${SUBDIR}_LIBRARY_DIRS CACHE) # 库目录变量
unset(${SUBDIR}_INCLUDE_DIRS CACHE) # 头文件目录变量
unset(${SUBDIR}_LINK_LIBRARIES CACHE) # 链接库变量
# 进入子目录,让其定义缓存变量
add_subdirectory(${SUBDIR})
# 重命名缓存变量,添加子目录前缀以避免冲突
set(PROJECT_NAME "${${SUBDIR}_PROJECT_NAME}")
set(MAIN_SOURCE_FILE "${${SUBDIR}_MAIN_SOURCE_FILE}")
set(RESOURCE_FILE "${${SUBDIR}_RESOURCE_FILE}")
set(MANIFEST_FILE "${${SUBDIR}_MANIFEST_FILE}")
set(BUILD_AS_DLL "${${SUBDIR}_BUILD_AS_DLL}")
set(LIBRARY_DIRS "${${SUBDIR}_LIBRARY_DIRS}") # 获取子项目指定的库目录
set(INCLUDE_DIRS "${${SUBDIR}_INCLUDE_DIRS}") # 获取子项目指定的头文件目录
set(LINK_LIBRARIES "${${SUBDIR}_LINK_LIBRARIES}") # 获取子项目需要链接的库
# 验证必要变量是否定义
set(REQUIRED_VARS PROJECT_NAME MAIN_SOURCE_FILE)
set(MISSING_VARS "")
foreach(VAR ${REQUIRED_VARS})
if(NOT DEFINED ${VAR} OR "${${VAR}}" STREQUAL "")
list(APPEND MISSING_VARS ${VAR})
endif()
endforeach()
if(MISSING_VARS)
message(WARNING "Missing required variables in ${SUBDIR}: ${MISSING_VARS} - skipping project")
continue()
endif()
# 检查主源文件是否存在
set(MAIN_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/${MAIN_SOURCE_FILE}")
if(NOT EXISTS ${MAIN_FILE_PATH})
message(WARNING "Main source file ${MAIN_SOURCE_FILE} not found in ${SUBDIR} (looked for: ${MAIN_FILE_PATH}) - skipping project")
continue()
endif()
# 收集源文件
set(SOURCES "${SUBDIR}/${MAIN_SOURCE_FILE}")
# 处理资源文件(如果定义且存在)
if(NOT "${RESOURCE_FILE}" STREQUAL "" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/${RESOURCE_FILE}")
list(APPEND SOURCES "${SUBDIR}/${RESOURCE_FILE}")
message(STATUS "Added resource file for ${PROJECT_NAME}")
endif()
# 处理清单文件(如果定义且存在)
set(MANIFEST_PATH "")
if(NOT "${MANIFEST_FILE}" STREQUAL "" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/${MANIFEST_FILE}")
set(MANIFEST_PATH "${SUBDIR}/${MANIFEST_FILE}")
list(APPEND SOURCES ${MANIFEST_PATH})
message(STATUS "Added manifest file for ${PROJECT_NAME}")
endif()
# 判断是构建 DLL 还是 EXE
if(BUILD_AS_DLL)
message(STATUS "Building ${PROJECT_NAME} as DLL")
add_library(${PROJECT_NAME} SHARED ${SOURCES})
set_target_properties(${PROJECT_NAME} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/.static"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/.lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/.lib"
)
if(WIN32)
target_compile_definitions(${PROJECT_NAME} PRIVATE
${PROJECT_NAME}_EXPORTS
)
endif()
else()
message(STATUS "Building ${PROJECT_NAME} as EXE")
add_executable(${PROJECT_NAME} ${SOURCES})
endif()
# 设置清单文件(如果存在)
if(NOT "${MANIFEST_PATH}" STREQUAL "" AND MSVC)
set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY LINK_FLAGS
"/MANIFEST:EMBED /MANIFESTINPUT:${MANIFEST_PATH}")
endif()
# 添加子项目指定的库目录和头文件目录
if(LIBRARY_DIRS)
message(STATUS "Adding library directories for ${PROJECT_NAME}: ${LIBRARY_DIRS}")
target_link_directories(${PROJECT_NAME} PRIVATE ${LIBRARY_DIRS})
endif()
if(INCLUDE_DIRS)
message(STATUS "Adding include directories for ${PROJECT_NAME}: ${INCLUDE_DIRS}")
target_include_directories(${PROJECT_NAME} PRIVATE ${INCLUDE_DIRS})
endif()
# 链接库 - 先链接全局库,再链接子项目指定的库
target_link_libraries(${PROJECT_NAME}
advapi32
user32
wtsapi32
userenv
psapi
shell32
kernel32
gdi32
netapi32
${LINK_LIBRARIES}
)
# 添加默认链接目录
target_link_directories(${PROJECT_NAME} PRIVATE
./.Link
)
# 添加默认头文件目录
target_include_directories(${PROJECT_NAME} PRIVATE
./.Link
)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"$<TARGET_FILE:${PROJECT_NAME}>"
"${CMAKE_BINARY_DIR}/.dat/${PROJECT_NAME}$<$<BOOL:${BUILD_AS_DLL}>:.dll>.dat"
COMMENT "Copying $<TARGET_FILE_NAME:${PROJECT_NAME}> to ${PROJECT_NAME}$<$<BOOL:${BUILD_AS_DLL}>:.dll>.dat"
)
message(STATUS "Successfully configured project: ${PROJECT_NAME}")
# 清除变量,避免影响其他项目
unset(PROJECT_NAME)
unset(MAIN_SOURCE_FILE)
unset(RESOURCE_FILE)
unset(MANIFEST_FILE)
unset(BUILD_AS_DLL)
unset(LIBRARY_DIRS)
unset(INCLUDE_DIRS)
unset(LINK_LIBRARIES)
endforeach()
add_custom_target(clean-all
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/.bin"
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/.lib"
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/.dat"
COMMAND ${CMAKE_COMMAND} -E remove "${CMAKE_BINARY_DIR}/CMakeCache.txt"
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/CMakeFiles"
COMMENT "Cleaning all build outputs and cache..."
)