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

CMake新手求助:构建依赖共享库的静态库及关联可执行文件时出现链接错误

Fixing CMake Static Library Dependencies & Undefined Symbol Errors

Hey there, let's break down what's going wrong with your CMake setup and fix it step by step. The core issues are related to incorrect dependency handling (using find_library for your own libraries instead of CMake targets) and missing dependency propagation (static libraries don't carry their dependencies automatically). Here's how to fix each part:

Key Issues in Your Current Setup

  • You’re using find_library to locate your own built libraries (lib1, lib2), but CMake already tracks these as targets when you use add_subdirectory—no need to hunt for .a files manually.
  • Your target_include_directories has a syntax error: {CMAKE_CURRENT_SOURCE_DIR} should be ${CMAKE_CURRENT_SOURCE_DIR} (missing the $ sign), so the include paths weren’t being set correctly.
  • Static libraries don’t embed their dependencies, so you need to use CMake’s PUBLIC/PRIVATE keywords to pass dependencies down the chain (e.g., lib1’s dependencies on rt/pthread need to be visible to lib2 and your executable).
  • You’re repeating redundant find_library calls which aren’t necessary.

Corrected CMakeLists Files

1. Root CMakeLists.txt (CMakeLists1.txt)

This one is mostly fine, but we can add a C standard requirement to make it cleaner:

cmake_minimum_required(VERSION 3.14)
project(MainApp VERSION 0.1 DESCRIPTION "Main Application CMake compilation project" LANGUAGES C)

# Set C standard (adjust to your needs)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(executable)

2. lib1/CMakeLists.txt (CMakeLists2.txt)

We’ll clean up redundant calls and use proper dependency propagation:

cmake_minimum_required(VERSION 3.14)
project(lib1 VERSION 0.1 DESCRIPTION "lib1 library" LANGUAGES C)

# List your source files
list(APPEND SRCS source1.c source2.c)

# Create static library
add_library(lib1 STATIC ${SRCS})

# Link required system libraries (use PRIVATE if lib1's headers don't expose these symbols)
target_link_libraries(lib1 PRIVATE rt pthread)

# Expose lib1's headers to dependent targets automatically
target_include_directories(lib1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
  • PRIVATE means rt/pthread are only needed for compiling lib1, but their linkage will still be propagated to targets that link lib1 (thanks to CMake’s target system).
  • PUBLIC on target_include_directories lets other targets (like lib2) automatically find lib1’s headers without hardcoding paths.

3. lib2/CMakeLists.txt (CMakeLists3.txt)

No more find_library for lib1—just use the target directly, and fix the include path syntax:

cmake_minimum_required(VERSION 3.14)
project(lib2 VERSION 0.1 DESCRIPTION "lib2 library" LANGUAGES C)

list(APPEND SRCS source1.c source2.c)

add_library(lib2 STATIC ${SRCS})

# Link lib1 (and automatically get its dependencies: rt/pthread)
target_link_libraries(lib2 PRIVATE lib1)

# Expose lib2's headers to dependent targets
target_include_directories(lib2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
  • We don’t need to re-link rt/pthread here—CMake will pull those in automatically from lib1’s dependency chain.
  • No need to manually add lib1’s include path anymore, since we linked against the lib1 target (which already exposes its headers via PUBLIC).

4. executable/CMakeLists.txt (CMakeLists4.txt)

Simplify by only linking lib2—all upstream dependencies (lib1, rt, pthread) will be propagated automatically:

cmake_minimum_required(VERSION 3.14)
project(Executable VERSION 0.1 DESCRIPTION "MainApp executable" LANGUAGES C)

list(APPEND SRCS source1.c source2.c)

add_executable(Executable ${SRCS})

# Link against lib2—all dependencies (lib1, rt, pthread) come along for the ride
target_link_libraries(Executable PRIVATE lib2)

# Headers from lib1 and lib2 are available via their respective targets
target_include_directories(Executable PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

Why This Fixes Your Undefined Symbol Error

The original issue was that when you linked lib1 to lib2 (and lib2 to your executable), the rt/pthread libraries weren’t being included in the final link step. Static libraries don’t store their dependency info, so CMake needs explicit instructions to pass those dependencies down. By using PRIVATE/PUBLIC and linking directly to targets instead of raw .a files, CMake automatically handles the full dependency chain—including linking rt/pthread where needed.

Quick Notes for Cross-Compilation

Since you’re cross-compiling, this target-based approach is even better: CMake uses the cross-compiler’s search paths automatically, so you don’t have to manually specify paths to .a files or system libraries. Your existing cross-compile environment setup should work seamlessly with these changes.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 15:44:06