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

如何让CMake将私有库输出到源码顶层目录而非构建目录?

问题描述

现有临时特殊源码结构:私有库privLibs与可执行文件ExeA、ExeB未通过CMake关联,但可执行文件编译时依赖这些私有库。要求避免引用build目录下的库文件,且无法修改顶层引用结构。

源码结构

topLevel
  |- privLibs
  |----CMakeLists.txt (目前仅执行add_subdirectory(libX))
  |----lib (make install的输出目录)
  |----include (make install的公共头文件输出目录)
  |----libA
  |-------CMakeLists.txt  
  |----libB
  |-------CMakeLists.txt
  |_ ExeA 
  |----CMakeLists.txt (依赖libA和libB)
  |_ ExeB
  |----CMakeLists.txt (依赖libA)

核心疑问

  1. 是否有合理方法让privLibs在编译时将libA.so和libB.so输出到privLibs/lib目录?
  2. 是否必须先执行privLibs的make install?
  3. 有没有更优方案?(已知find_library指定privLibs/build/lib并非理想方案)

关联CMake代码

privLibs/CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(liby VERSION 0.0.1 DESCRIPTION "liby library group")

add_subdirectory(libA)
add_subdirectory(libB)

libA/CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(libA VERSION 0.0.1 DESCRIPTION "libA library")

include (FindPkgConfig)
include (GNUInstallDirs)


set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)

set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH True)

#Perform Package Checks for standard system libraries.
find_library(SOMELIB NAMES somelib HINTS /path/to/lib NO_DEFAULT_PATH)
 
include_directories(../include)


#List and add Sources to compile
set (SOURCES
    libcode.c
)

add_library(${PROJECT_NAME} SHARED ${SOURCES})
set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 0.0.0 SOVERSION 0 PUBLIC_HEADER "libcode.h")

install (TARGETS ${PROJECT_NAME} DESTINATION lib PUBLIC_HEADER DESTINATION include )


##link needed libraries
target_link_libraries(${PROJECT_NAME} PUBLIC
  ${SOMELIB}
)

target_include_directories(${PROJECT_NAME}
    PUBLIC 
    ${PROJECT_SOURCE_DIR}
)

解决方案

方案1:修改库输出路径,跳过make install

无需执行make install,直接在libA和libB的CMakeLists.txt中指定库文件和头文件的输出目录,让编译产物直接生成到privLibs/lib和privLibs/include。

修改libA/CMakeLists.txt(libB同理):

# 替换原set_target_properties和install部分,或直接追加以下配置
set_target_properties(${PROJECT_NAME} PROPERTIES
    VERSION 0.0.0
    SOVERSION 0
    PUBLIC_HEADER "libcode.h"
    # 指定库文件输出到privLibs/lib
    LIBRARY_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/../lib"
)

# 同步公共头文件到privLibs/include
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:${PROJECT_NAME},PUBLIC_HEADER> "${PROJECT_SOURCE_DIR}/../include"
)
  • 编译privLibs时,libA.so会直接生成到privLibs/lib,头文件同步复制到privLibs/include,完全跳过install流程。
  • 若需区分Debug/Release等多配置构建,可改用LIBRARY_OUTPUT_DIRECTORY_DEBUG/LIBRARY_OUTPUT_DIRECTORY_RELEASE指定不同子目录。

方案2:指定本地安装前缀,简化install流程

如果必须保留install逻辑,可在编译privLibs时通过CMAKE_INSTALL_PREFIX参数指定安装根目录为privLibs,这样make install会自动将库和头文件安装到目标路径,无需修改CMake代码:

cd privLibs && mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../
make && make install

方案3:让ExeA/ExeB正确引用privLibs/lib的库

无论采用上述哪种方案,在ExeA/CMakeLists.txt中可通过以下方式配置依赖:

方式1:直接指定搜索路径

# 添加头文件搜索路径
include_directories(${CMAKE_SOURCE_DIR}/../privLibs/include)
# 添加库文件搜索路径
link_directories(${CMAKE_SOURCE_DIR}/../privLibs/lib)
# 链接目标库
target_link_libraries(ExeA PUBLIC libA libB)

方式2:用find_library更规范引用

find_library(LIBA NAMES libA.so HINTS ${CMAKE_SOURCE_DIR}/../privLibs/lib NO_DEFAULT_PATH)
find_library(LIBB NAMES libB.so HINTS ${CMAKE_SOURCE_DIR}/../privLibs/lib NO_DEFAULT_PATH)

include_directories(${CMAKE_SOURCE_DIR}/../privLibs/include)

target_link_libraries(ExeA PUBLIC ${LIBA} ${LIBB})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 17:10:35