如何让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)
核心疑问
- 是否有合理方法让
privLibs在编译时将libA.so和libB.so输出到privLibs/lib目录? - 是否必须先执行
privLibs的make install? - 有没有更优方案?(已知
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
相关产品推荐
相关产品推荐

