V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zcion
V2EX  ›  C++

[求助] Linux 有什么好的引入 c++ 第三方库的方案

  •  1
     
  •   zcion · 4 天前 · 1919 次点击

    问题

    之前用 windows 开发,为了统一使用第三方库行为,我习惯 cmake + vcpkg 这套,直接用上 vcpkg.cmake 后在 cmake 中 find_package 就行。

    而 linux 已经有自己的包管理器了,我直接 pacman 可以很方便的下载第三方库。但问题是有哪些统一行为能够在 cmake 引入 pacman 下载的内容(头文件+库文件)?

    我的一些想法

    我能想到的是通过 pkg-config 去统一管理,在 cmake 中 find_package(PkgConfig),然后用 pkg-config 的东西去引入。

    但当我通过 pacman 下载 boost 时( boost 和 boost-libs ),用 pkg-config 找不到对应的文件(例如我想引入 asio 库,但 pkg-config --list-all | grep asio 找不到相关的内容)。通过 pacman 下载的 boost 似乎没有提供 .pc 文件,导致 pkg-config 不知道这么个东西。

    另外我能想到的是,手动的在 cmake 中 find_libraryfind_path 引入库文件和头文件,但这样太麻烦了(例如要使用 ffmpeg ,那我得分别手动搜索 libavformat 、libavcodec 、libavutil 、libswscale 的头文件和库文件),用 find_package 倒是可以很方便解决,但 pacman 下载的依赖似乎没有提供相关的 .cmake 文件?

    so ?

    似乎 pkg-config 不是终极解决方案,所以有什么方案能够统一引入依赖的行为。难道还要继续使用 vcpkg 吗?(确实好用,但看一些人的说法是 linux 上建议使用自带的包管理器)

    20 条回复    2025-11-25 10:54:07 +08:00
    w568w
        1
    w568w  
       4 天前   ❤️ 2
    (我主要写 C ,没写过 C++,所以下面一部分说法可能不准确。)

    这个问题其实有系统级和语言级的两层,一是 Linux 对 C/C++ 依赖的管理没有明确的定义,各个发行版自立山头;二是 C/C++ 的包管理本身确实很乱。

    1. 对于前者,可以认为在依赖管理这件事上,Linux 没有规定什么做法是标准的,所以「每个系的发行版都是完全独立的体系」,不应该像 Windows 7/8/10/11 那样当成同一血脉的系统来看待。

    尽管大家可以找出一些最大公约数(比如大多遵循 FHS 、使用 pkg-config 和 gcc ),但在实现上会有非常多细微的差别。大部分差别在开发过程中可以消解掉(例如使用 CMake 的 find_library/package 过程)但不是全部,而在打包和分发过程中则完全需要各个区别对待(比如 Debian 系、Gentoo 系和 Redhat 系,在分割软件包的粒度和指定依赖的方式上,做法都完全不同)。

    此外,Linux 本身又是极度依赖 source-driven 的,需要时刻考虑用户利用现有环境进行开发的可能性。这就是为什么 Linux 下很难有 vcpkg 这样一个独立的、和系统无关的 C/C++ 包管理器。或者说即使有了,也不会好用,因为你最终还是要为每个发行版、编译器和依赖组合付出额外的成本去适配。

    2. 对于后者,你的例子其实就是很好的典型。「通过 pacman 下载的 boost 似乎没有提供 .pc 文件」,是因为 boost 这个库本身只提供了 CMake 模块。你用 pacman -Ql boost 就能看到,boost 提供的是 /usr/lib/cmake/Boost-xxx/BoostConfig.cmake 配置文件,而不是 pkg-config 文件。

    这种四世同堂的局面很多,不是每个包都会提供 pkg-config 来兜底(从功能性上来说,CMake Modules 无疑是更先进的)。这其实也是生态碎片化的体现:开发中的选择一旦多起来,开源作者都会习惯性选择自己最习惯的,而不是兼容性最好的。你问「有没有办法用统一的方式导入」,其实就和前端问「有没有办法在我的 React 项目里导入其他 UI 框架的控件」是一样的。当然这边的问题至少理论上是 solvable 的。

    ----


    所以我能给的建议是什么呢?

    1. 如果你专为某个发行版开发程序:完全本土化。使用那个发行版和系统包管理器,完全遵循那个发行版的逻辑。系统提供什么就使用什么方式引入;

    2. 如果你为所有发行版开发程序:防御性编程,减少假设。同上,但是尽可能不要依赖某些假设(例如「一定有 pkg-config 」)。CMake 的 https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html 介绍了通用的建议,主要是 尽可能使用 find_package 来引入依赖、使用 FetchContent 来从源码编译依赖 及 不要使用 FindPkgConfig 。
    ysc3839
        2
    ysc3839  
       4 天前 via Android
    boost 的话直接用 cmake 的 find_package 就行了,不需要 pkg-config
    kekxv
        3
    kekxv  
       4 天前 via iPhone
    bwnjnOEI
        4
    bwnjnOEI  
       4 天前 via iPhone   ❤️ 1
    我用的 conan
    mz02005
        5
    mz02005  
       4 天前 via iPhone
    不是,你都用 vcpkg 了,还想如何?
    LindsayZhou
        6
    LindsayZhou  
       4 天前
    em... 我不了解 C 开发,不过 asio 是这东西吗?它好像和 boost 不是同一个包,它带了 .pc 文件:

    https://archlinux.org/packages/extra/any/asio/
    sir283
        7
    sir283  
       4 天前
    手动找,或者自己拉源码 rebuild 一遍,生成 pkg-config ,就这样,下一个问题。
    jsph
        8
    jsph  
       4 天前
    bazel
    bigtan
        9
    bigtan  
       4 天前
    vcpkg 在 Linux 一样可以用啊 cmake 不都跨平台吗
    tinybaby365
        10
    tinybaby365  
       3 天前
    依然使用 cmake + vcpkg ,也可以 cmake + ExternalProject_Add

    如果你想要你的程序不只是兼容特定的 Linux 发行版,你就不要使用 Linux 包管理器安装的-dev 或-devel 包。这一点上商业软件为了维护更少的包,基本上会采取这种做法,和 Linux 发行版里面自带软件的做法相反。

    想要兼容更多的 Linux 发行版,你就要考虑编译环境的 glibc 版本(想要兼容更老的版本,就意味着不能使用 C++更新的标准)
    tinybaby365
        11
    tinybaby365  
       3 天前
    @jsph bazel 是理想,小团队不现实
    shylockhg
        12
    shylockhg  
       3 天前
    把所有 lib 放一个 cmake 工程用 external project 管理,编译安装 tar 打包,根据 libc 版本,区分不同 tar 包
    shylockhg
        13
    shylockhg  
       3 天前
    @shylockhg 如何涉及到 c++98/11,libc++/libstdc++之类的还需要加上 abi 区分 tar 包
    shihira
        14
    shihira  
       3 天前
    或许比较邪教的 flake.nix ?
    pluswu1986
        15
    pluswu1986  
       3 天前
    conan
    Fenicesun
        16
    Fenicesun  
       3 天前
    我都是把所有的依赖库源码放在 third_party 和自己工程一起编译
    MrVito
        17
    MrVito  
       3 天前
    conan
    ink19
        18
    ink19  
       3 天前
    如果是自己的项目,我建议 xmake
    nno
        19
    nno  
       3 天前
    vcpkg 在 linux 下经常编译失败;但 conan 不会,而且 conan 可以生成各种各样的构建文件
    heyzenxu
        20
    heyzenxu  
       2 天前
    conda 生态的 [pixi]( https://pixi.sh) 了解下, 开发体验类似 rust + cargo
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   5201 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 05:50 · PVG 13:50 · LAX 21:50 · JFK 00:50
    ♥ Do have faith in what you're doing.