123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- cmake_minimum_required(VERSION 3.12)
- # 项目名称:log4cpp_wrapper(避免与系统log4cpp库冲突),版本1.0.0
- project(log4cpp_wrapper VERSION 1.0.0 LANGUAGES CXX)
- # === 1. 基础配置 ===
- # 强制C++17标准,禁用扩展
- set(CMAKE_CXX_STANDARD 17)
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
- set(CMAKE_CXX_EXTENSIONS OFF)
- # 动态库必须开启位置无关代码
- set(CMAKE_POSITION_INDEPENDENT_CODE ON)
- # 编译选项:调试信息、位置无关代码、警告增强
- add_compile_options(-g -fPIC)
- # Debug模式启用地址 sanitizer(检测内存错误,Release模式自动关闭)
- set(SANITIZE_OPTIONS -fsanitize=address)
- add_compile_options($<$<CONFIG:Debug>:${SANITIZE_OPTIONS}>)
- link_libraries($<$<CONFIG:Debug>:${SANITIZE_OPTIONS}>)
- # === 2. 输出目录配置(统一产物路径) ===
- set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) # 静态库
- set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) # 动态库(.so)
- set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # 可执行文件(如测试程序)
- # === 3. 路径配置(明确源文件/头文件/交付目录) ===
- set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) # 源文件目录(当前CMake所在目录)
- set(INCLUDE_DIR ${SRC_DIR}) # 头文件目录(Log4CPP.h在当前目录)
- # 交付目录:参考你的示例路径,可通过外部参数修改
- set(DELIVER_DIR "${CMAKE_BINARY_DIR}/../../Deliver" CACHE PATH "动态库交付目录(供其他模块使用)")
- get_filename_component(DELIVER_DIR ${DELIVER_DIR} ABSOLUTE) # 转为绝对路径
- message(STATUS "=== 路径配置 ===")
- message(STATUS "源文件目录: ${SRC_DIR}")
- message(STATUS "头文件目录: ${INCLUDE_DIR}")
- message(STATUS "交付目录: ${DELIVER_DIR}")
- # === 4. 源文件与头文件列表(仅包含核心Log4CPP代码,排除测试文件) ===
- set(SRC_FILES
- ${SRC_DIR}/Log4CPP.cpp # 核心实现文件
- )
- set(HEADER_FILES
- ${INCLUDE_DIR}/Log4CPP.h # 对外暴露的头文件(供其他模块引用)
- )
- # 验证核心文件是否存在(避免编译失败)
- message(STATUS "=== 文件验证 ===")
- foreach(file ${SRC_FILES} ${HEADER_FILES})
- if(NOT EXISTS ${file})
- message(FATAL_ERROR "关键文件缺失: ${file}")
- else()
- message(STATUS "找到文件: ${file}")
- endif()
- endforeach()
- # === 5. 依赖查找(关键:找到系统中的log4cpp库) ===
- message(STATUS "=== 依赖查找(log4cpp) ===")
- # 1. 查找log4cpp头文件(需包含 <log4cpp/Category.hh>)
- find_path(LOG4CPP_INCLUDE_DIR
- NAMES log4cpp/Category.hh # 要查找的头文件路径
- PATHS /usr/include # 系统默认头文件目录(apt安装后路径)
- NO_DEFAULT_PATH # 仅搜索指定路径,避免冲突
- )
- # 2. 查找log4cpp库文件(动态库:liblog4cpp.so)
- find_library(LOG4CPP_LIB
- NAMES log4cpp liblog4cpp # 库名(Linux下会自动加lib前缀,故两种都检查)
- PATHS /usr/lib/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu # 系统库目录(aarch64架构)
- NO_DEFAULT_PATH
- )
- # 验证log4cpp依赖是否找到
- if(NOT LOG4CPP_INCLUDE_DIR)
- message(FATAL_ERROR "未找到log4cpp头文件!请先安装:sudo apt install liblog4cpp5-dev")
- endif()
- if(NOT LOG4CPP_LIB)
- message(FATAL_ERROR "未找到log4cpp库文件!请先安装:sudo apt install liblog4cpp5-dev")
- else()
- message(STATUS "找到log4cpp头文件: ${LOG4CPP_INCLUDE_DIR}")
- message(STATUS "找到log4cpp库: ${LOG4CPP_LIB}")
- endif()
- # === 6. 构建动态库(核心目标:log4cpp_wrapper.so) ===
- add_library(log4cpp_wrapper SHARED # SHARED表示动态库
- ${SRC_FILES}
- ${HEADER_FILES} # 头文件加入目标,便于IDE识别(非编译必需)
- )
- # === 7. 动态库属性配置(控制库的版本、名称等) ===
- set_target_properties(log4cpp_wrapper PROPERTIES
- VERSION ${PROJECT_VERSION} # 完整版本:1.0.0
- SOVERSION 1 # 主版本:1(兼容1.x.x版本)
- OUTPUT_NAME "log4cpp_wrapper" # 最终库文件名:liblog4cpp_wrapper.so
- PUBLIC_HEADER "${HEADER_FILES}" # 对外暴露的头文件(安装时会复制到include目录)
- # CXX_VISIBILITY_PRESET hidden # 隐藏内部符号,仅暴露必要接口(减少冲突)
- # VISIBILITY_INLINES_HIDDEN ON
- )
- # === 8. 编译选项(增强代码质量与兼容性) ===
- message(STATUS "=== 编译选项 ===")
- if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") # 适配GCC和Clang编译器
- target_compile_options(log4cpp_wrapper PRIVATE
- -Wall # 开启所有警告
- -Wextra # 额外警告
- -Wpedantic # 严格遵循C++标准
- -Werror=return-type # 函数无返回值时报错(避免逻辑漏洞)
- -Wno-unused-parameter # 可选:关闭未使用参数警告(根据需求调整)
- )
- message(STATUS "启用警告选项:-Wall -Wextra -Wpedantic -Werror=return-type")
- endif()
- # === 9. 依赖关联(让动态库知道去哪里找头文件和链接库) ===
- # 1. 头文件路径(当前项目头文件 + log4cpp头文件)
- target_include_directories(log4cpp_wrapper
- PUBLIC # 外部模块引用此库时,会自动包含这些目录
- $<BUILD_INTERFACE:${INCLUDE_DIR}> # 编译时:当前项目头文件
- $<BUILD_INTERFACE:${LOG4CPP_INCLUDE_DIR}> # 编译时:log4cpp头文件
- $<INSTALL_INTERFACE:include> # 安装后:外部引用时的头文件目录
- )
- # 添加 tinyxml2 依赖
- find_package(PkgConfig REQUIRED)
- pkg_check_modules(TINYXML2 REQUIRED tinyxml2)
- # 添加包含目录
- include_directories(
- ${TINYXML2_INCLUDE_DIRS}
- )
- # 添加链接库
- target_link_libraries(log4cpp_wrapper
- PUBLIC
- ${LOG4CPP_LIB}
- ${TINYXML2_LIBRARIES}
- PRIVATE
- pthread
- dl
- )
- message(STATUS "链接依赖:${LOG4CPP_LIB} pthread dl")
- # === 10. 交付配置(改为创建符号链接,而非复制) ===
- message(STATUS "=== 交付配置 ===")
- # 创建交付目录
- file(MAKE_DIRECTORY ${DELIVER_DIR}/lib ${DELIVER_DIR}/include)
- # 1. 复制核心文件(只有这一个是真实文件,其他两个是链接)
- add_custom_command(TARGET log4cpp_wrapper POST_BUILD
- COMMENT "=== 复制核心库+创建符号链接到交付目录: ${DELIVER_DIR} ==="
- # 第一步:复制核心文件(liblog4cpp_wrapper.so.1.0.0)到交付目录
- COMMAND ${CMAKE_COMMAND} -E copy_if_different
- $<TARGET_FILE:log4cpp_wrapper> # 源:核心文件(.so.1.0.0)
- ${DELIVER_DIR}/lib/ # 目标:交付目录的lib文件夹
- # 第二步:创建主版本符号链接(.so.1 → .so.1.0.0)
- COMMAND ${CMAKE_COMMAND} -E create_symlink
- $<TARGET_FILE_NAME:log4cpp_wrapper> # 链接指向的目标文件名(.so.1.0.0)
- ${DELIVER_DIR}/lib/$<TARGET_SONAME_FILE_NAME:log4cpp_wrapper> # 链接文件本身(.so.1)
- # 第三步:创建通用符号链接(.so → .so.1)
- COMMAND ${CMAKE_COMMAND} -E create_symlink
- $<TARGET_SONAME_FILE_NAME:log4cpp_wrapper> # 链接指向的目标文件名(.so.1)
- ${DELIVER_DIR}/lib/$<TARGET_LINKER_FILE_NAME:log4cpp_wrapper> # 链接文件本身(.so)
- # 复制头文件(这部分不变)
- COMMAND ${CMAKE_COMMAND} -E copy_if_different
- ${HEADER_FILES}
- ${DELIVER_DIR}/include/
- )
- # === 11. 安装配置(支持通过sudo make install安装到系统,便于全局引用) ===
- message(STATUS "=== 安装配置 ===")
- install(TARGETS log4cpp_wrapper
- EXPORT log4cppWrapperTargets # 导出目标配置(供其他项目find_package使用)
- LIBRARY DESTINATION lib # 安装动态库到系统/lib目录
- ARCHIVE DESTINATION lib # 若有静态库,安装到系统/lib目录
- PUBLIC_HEADER DESTINATION include # 安装头文件到系统/include目录
- PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ # 设置文件权限
- )
- # 导出配置文件(让其他项目通过find_package(log4cpp_wrapper)找到此库)
- install(EXPORT log4cppWrapperTargets
- FILE log4cppWrapperConfig.cmake
- DESTINATION lib/cmake/log4cpp_wrapper # 配置文件安装路径
- EXPORT_LINK_INTERFACE_LIBRARIES # 导出链接依赖(避免外部项目手动链接log4cpp)
- )
- message(STATUS "安装路径:系统lib -> /usr/local/lib,系统include -> /usr/local/include")
- # === 13. 调试信息输出(确认所有配置正确) ===
- message(STATUS "=== 最终配置汇总 ===")
- message(STATUS "动态库名称: lib${CMAKE_PROJECT_NAME}.so (实际:liblog4cpp_wrapper.so)")
- message(STATUS "动态库输出: ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
- message(STATUS "交付目录: ${DELIVER_DIR}")
- message(STATUS "是否构建测试: ${BUILD_TEST}")
|