如何在CMake中为多目标使用带不同静态依赖的库?
Absolutely! The key issue here is that your printsth library is currently built as a single global target, but it needs to be compiled twice—once with each app's include directory to pick up the correct print_usr.h macro. Here are two solid approaches to make this work with CMake:
Approach 1: Use an OBJECT Library to Reuse Source Code
OBJECT libraries let us compile source files without linking them into a final library, so we can pair them with each executable's unique include path.
Step 1: Update extern/printsth/src/CMakeLists.txt
Replace the existing library definition with an OBJECT target:
add_library(printsth_obj OBJECT printsth.cpp) target_include_directories(printsth_obj PUBLIC ../include)
Step 2: Update Each App's CMakeLists.txt
For apps/printyes/CMakeLists.txt:
add_executable(printyes main.cpp $<TARGET_OBJECTS:printsth_obj>) # Add the app's directory to include paths so printsth.cpp finds print_usr.h target_include_directories(printyes PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(printyes PRIVATE printsth_obj)
For apps/printno/CMakeLists.txt:
add_executable(printno main.cpp $<TARGET_OBJECTS:printsth_obj>) target_include_directories(printno PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(printno PRIVATE printsth_obj)
Step 3: Adjust Root CMakeLists.txt Order
Make sure the library is processed before the apps:
cmake_minimum_required(VERSION 3.11...3.16) project(printexamples VERSION 0.1 DESCRIPTION "Print examples" LANGUAGES CXX) add_subdirectory(extern/printsth) add_subdirectory(apps/printyes) add_subdirectory(apps/printno)
Approach 2: Create App-Specific Library Targets
This method builds a unique copy of the printsth library for each executable, each with its own include path.
Step 1: Update extern/printsth/CMakeLists.txt
Expose the library's source and include paths as variables:
cmake_minimum_required(VERSION 3.11...3.16) project(printsth VERSION 0.1 DESCRIPTION "Print something" LANGUAGES CXX) # Store paths for reuse in app targets set(PRINTSTH_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/printsth.cpp) set(PRINTSTH_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/include)
Step 2: Update Each App's CMakeLists.txt
For apps/printyes/CMakeLists.txt:
add_executable(printyes main.cpp) # Build a unique library for this app add_library(printsth_printyes STATIC ${PRINTSTH_SRC}) target_include_directories(printsth_printyes PUBLIC ${PRINTSTH_INCLUDE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} # Access this app's print_usr.h ) target_link_libraries(printyes PRIVATE printsth_printyes)
For apps/printno/CMakeLists.txt:
add_executable(printno main.cpp) add_library(printsth_printno STATIC ${PRINTSTH_SRC}) target_include_directories(printsth_printno PUBLIC ${PRINTSTH_INCLUDE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) target_link_libraries(printno PRIVATE printsth_printno)
Why Your Original Setup Failed
Your initial config built printsth once as a single global library. When linking both executables, they shared this pre-compiled library—which had no knowledge of either app's include directory (hence the missing header error). Both approaches above ensure the printsth source is compiled separately for each app, picking up the correct USR_STRING macro from each print_usr.h.
内容的提问来源于stack exchange,提问作者Christoph

