You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用CMake链接嵌套静态库?静态链接libjpeg-turbo遇未定义引用

问题分析与解决方案

核心原因

静态库本质是目标文件的归档集合,不会自动将依赖的其他静态库内容合并进去。当你将internal_lib设为静态库并通过PUBLIC链接libjpeg.a时,CMake会在internal_lib的目标中记录这个依赖关系,但主程序通过ExternalProject_Add构建internal_lib时,主项目的CMake上下文无法感知到internal_lib内部的依赖链——因为ExternalProject是独立构建流程,主项目无法直接读取子项目的依赖信息。

而共享库模式下正常,是因为共享库会在自身的元数据中记录依赖的共享库路径,链接器最终可以自动找到这些依赖。


解决方案:让CMake自动传递依赖链

我们可以通过导出/导入CMake目标的方式,让internal_lib把自身的依赖信息传递给主程序,无需手动在主程序中添加libjpeg.a的链接。

步骤1:修改internal_lib的CMakeLists.txt

我们需要将libjpeg-turbo包装成CMake导入目标,并导出internal_lib的依赖配置:

cmake_minimum_required(VERSION 3.9)

project(internal_lib LANGUAGES C)

include(ExternalProject)
ExternalProject_Add(libjpeg-turbo
    GIT_REPOSITORY https://github.com/libjpeg-turbo/libjpeg-turbo.git
    GIT_TAG 6c87537f60941f3c265c339fe60d1e31d2a42ccf # release v3.0.0
    GIT_SHALLOW ON
    INSTALL_COMMAND ""
    CMAKE_ARGS -DENABLE_SHARED=OFF -DENABLE_STATIC=ON # 强制生成静态库
)

ExternalProject_Get_Property(libjpeg-turbo BINARY_DIR)
set(LIBJPEG_BINARY_DIR "${BINARY_DIR}")
ExternalProject_Get_Property(libjpeg-turbo SOURCE_DIR)
set(LIBJPEG_SOURCE_DIR "${SOURCE_DIR}")

# 将libjpeg.a包装为CMake导入目标,便于跟踪依赖
add_library(libjpeg STATIC IMPORTED)
add_dependencies(libjpeg libjpeg-turbo)
set_target_properties(libjpeg PROPERTIES
    IMPORTED_LOCATION "${LIBJPEG_BINARY_DIR}/libjpeg.a"
    INTERFACE_INCLUDE_DIRECTORIES "${LIBJPEG_SOURCE_DIR};${LIBJPEG_BINARY_DIR}"
)

add_library(internal_lib STATIC lib.c)
target_include_directories(internal_lib PUBLIC ./)
# 链接包装后的libjpeg目标,而非直接链接文件路径
target_link_libraries(internal_lib PUBLIC libjpeg)

# 导出internal_lib的目标配置,供主程序导入
install(TARGETS internal_lib libjpeg
    EXPORT internal_libTargets
    ARCHIVE DESTINATION lib
    INCLUDES DESTINATION include
)

install(EXPORT internal_libTargets
    FILE internal_libTargets.cmake
    DESTINATION lib/cmake/internal_lib
)

# 生成Config.cmake文件,用于find_package识别
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/internal_libConfigVersion.cmake"
    VERSION 1.0.0
    COMPATIBILITY SameMajorVersion
)

configure_package_config_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in"
    "${CMAKE_CURRENT_BINARY_DIR}/internal_libConfig.cmake"
    INSTALL_DESTINATION lib/cmake/internal_lib
)

install(FILES
    "${CMAKE_CURRENT_BINARY_DIR}/internal_libConfig.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/internal_libConfigVersion.cmake"
    DESTINATION lib/cmake/internal_lib
)

步骤2:添加internal_lib的Config.cmake.in模板文件

在internal_lib目录下新建Config.cmake.in,内容如下:

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/internal_libTargets.cmake")
check_required_components(internal_lib)

步骤3:修改主程序的CMakeLists.txt

让主程序通过find_package导入internal_lib及其依赖:

cmake_minimum_required(VERSION 3.9)

project(program LANGUAGES C)

include(ExternalProject)
ExternalProject_Add(internal_lib_project
    SOURCE_DIR "../../internal_lib"
    DOWNLOAD_COMMAND ""
    # 指定安装目录,让主程序能找到导出的配置文件
    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/internal_lib_install
)

# 等待internal_lib安装完成后,导入其目标配置
add_dependencies(main internal_lib_project)
find_package(internal_lib REQUIRED
    PATHS ${CMAKE_CURRENT_BINARY_DIR}/internal_lib_install/lib/cmake/internal_lib
    NO_DEFAULT_PATH
)

add_executable(main main.c)
# 直接链接internal_lib,CMake会自动处理其依赖的libjpeg
target_link_libraries(main PUBLIC internal_lib)

替代方案:手动传递依赖路径(不推荐,但快速验证)

如果不想用导出目标的方式,也可以在主程序中通过ExternalProject_Get_Property获取libjpeg-turbo的路径,但这种方式耦合性高,仅适合临时验证:

# 在主程序CMakeLists.txt中添加
ExternalProject_Get_Property(internal_lib_project SOURCE_DIR)
set(INTERNAL_LIB_SOURCE_DIR "${SOURCE_DIR}")

# 获取libjpeg的路径(需要从internal_lib的构建中传递,或硬编码)
ExternalProject_Get_Property(internal_lib_project BINARY_DIR)
set(LIBJPEG_BINARY_DIR "${BINARY_DIR}/libjpeg-turbo-prefix/src/libjpeg-turbo-build")

target_link_libraries(main PUBLIC internal_lib "${LIBJPEG_BINARY_DIR}/libjpeg.a")

内容的提问来源于stack exchange,提问作者crashoz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 07:55:55