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

CMake含公共库的两个独立项目打包方案问询

解决方法:生成两个独立CPack包,无需系统级安装libcommon

首先得澄清一下:你之前觉得CPack只能生成一个包,这个说法是针对单个CMake项目而言的——确实,一个CMake构建树(对应一个顶级CMakeLists.txt)只能通过CPack生成一套打包产物(哪怕用组件,那也是同一个包的不同部分,不是独立包)。但咱们完全可以绕开这个限制,不用把libcommon装到系统级,就能生成projA和projB两个独立的包。

下面给你两种实用的方案,适配不同的场景:

方案一:libcommon本地独立构建+projA/B引用本地安装包

适合需要单独维护libcommon(比如单独更新、单独打包)的场景,libcommon会被安装到项目目录下的本地文件夹,不会碰系统路径。

步骤1:给libcommon配置CMakeLists.txt

在libcommon/目录下创建CMakeLists.txt,配置成可安装的CMake项目:

cmake_minimum_required(VERSION 3.15)
project(libcommon VERSION 1.0.0)

# 编译共享库
add_library(common SHARED src/utils.c)
# 配置头文件路径:构建时用源码目录,安装后用安装目录
target_include_directories(common PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)

# 安装规则:指定安装到项目根目录下的install/libcommon文件夹
install(TARGETS common
    EXPORT commonTargets
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
    INCLUDES DESTINATION include
)
install(DIRECTORY include/ DESTINATION include)

# 生成CMake配置文件,方便其他项目查找libcommon
install(EXPORT commonTargets
    FILE commonTargets.cmake
    NAMESPACE common::
    DESTINATION lib/cmake/common
)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/commonConfigVersion.cmake"
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY SameMajorVersion
)
configure_package_config_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in"
    "${CMAKE_CURRENT_BINARY_DIR}/commonConfig.cmake"
    INSTALL_DESTINATION lib/cmake/common
)
install(FILES
    "${CMAKE_CURRENT_BINARY_DIR}/commonConfig.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/commonConfigVersion.cmake"
    DESTINATION lib/cmake/common
)

同时在libcommon/目录下创建Config.cmake.in模板文件:

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/commonTargets.cmake")
check_required_components(common)

步骤2:构建并本地安装libcommon

在终端执行:

cd libcommon
mkdir build && cd build
# 指定安装到根目录下的install/libcommon,绝对路径也行
cmake .. -DCMAKE_INSTALL_PREFIX=../../install/libcommon
cmake --build . --target install

步骤3:给projA配置CMakeLists.txt(projB同理)

在projA/目录下创建CMakeLists.txt,引用本地安装的libcommon并配置CPack:

cmake_minimum_required(VERSION 3.15)
project(projA VERSION 1.0.0)

# 告诉CMake去哪里找本地安装的libcommon
set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../install/libcommon")
find_package(common REQUIRED)

# 编译projA的可执行文件
add_executable(projA src/mainA.c)
target_link_libraries(projA PRIVATE common::common)

# 安装projA
install(TARGETS projA
    RUNTIME DESTINATION bin
)

# 配置CPack生成独立包
set(CPACK_PACKAGE_NAME "projA")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "独立打包的Project A,依赖本地libcommon")
# 可选:指定打包格式,比如DEB、RPM、ZIP等
set(CPACK_GENERATOR "ZIP;DEB")
include(CPack)

步骤4:分别构建并打包projA和projB

对projA执行:

cd projA
mkdir build && cd build
cmake ..
cmake --build .
cpack

projB重复同样的操作,就能得到两个完全独立的包文件。


方案二:用FetchContent让projA/B自动拉取libcommon源码构建

适合不需要单独维护libcommon包的场景,projA和projB在构建时会自动拉取libcommon的源码并编译,打包时可以选择把libcommon的库一起打包进去,让projA/B的包完全独立。

步骤1:给projA配置CMakeLists.txt(projB同理)

cmake_minimum_required(VERSION 3.15)
project(projA VERSION 1.0.0)

# 引入FetchContent模块,拉取本地的libcommon源码
include(FetchContent)
FetchContent_Declare(
    libcommon
    SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../libcommon
)
FetchContent_MakeAvailable(libcommon)

# 编译projA可执行文件
add_executable(projA src/mainA.c)
target_link_libraries(projA PRIVATE common::common)

# 安装projA和libcommon的库(让打包后的projA包含依赖)
install(TARGETS projA
    RUNTIME DESTINATION bin
)
install(TARGETS common
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
)
install(DIRECTORY ${libcommon_SOURCE_DIR}/include/ DESTINATION include)

# 配置CPack生成独立包
set(CPACK_PACKAGE_NAME "projA")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "包含libcommon的独立Project A包")
set(CPACK_GENERATOR "ZIP;RPM")
include(CPack)

步骤2:直接构建并打包projA/B

对projA执行:

cd projA
mkdir build && cd build
cmake ..
cmake --build .
cpack

这种方式下,projA的包会包含自己的可执行文件和libcommon的库,完全独立,不需要提前安装任何依赖。


额外说明

如果你的场景需要把libcommon也做成独立包,让projA/B的包声明依赖它,那也可以给libcommon配置自己的CPack,然后在projA/B的CPack配置里添加依赖声明(比如DEB包的CPACK_DEBIAN_PACKAGE_DEPENDS,RPM包的CPACK_RPM_PACKAGE_REQUIRES),这种情况下libcommon可以安装到系统级,也可以用本地包仓库来管理,不用全局安装。

内容的提问来源于stack exchange,提问作者P. Dmitry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:01:26