RevyOS上的工程软件生态观测 (5): 构建之旅:从入门到放弃 (中):pkg-config 小时候借书 not found in the pkg-config search path 了

大家好,我是 PLCT 丁丑小队的一名实习生。这是我们工程软件测试系列帖的第五篇,接续上篇

在上期,我们处理了那些构建流程相对标准的软件。而本期,我们将进入更具挑战性的领域:这些软件不仅需要从源码编译,还可能伴随着以下一种或多种情况:

  • 关键依赖缺失: 软件依赖的某个特定版本的库在 RevyOS 源中不存在,需要我们手动编译和安装这个依赖。
  • 构建系统魔改: 软件的构建脚本存在问题,例如硬编码了不适用于 RISC-V 的编译器标志、或者无法正确找到已安装的依赖,需要我们手动修改构建脚本。
  • 源码级 Patch: 软件的源代码中包含了一些与现代编译器或库不兼容的写法,需要我们直接修改源码。

这些操作无疑增加了在 RISC-V 平台上使用这些软件的门槛,但成功克服这些障碍的过程,也正是开源社区 porting 工作乐趣的一部分。

1. CalculiX - 需要手动编译依赖的三维结构 FEA 程序

CalculiX 是一款功能强大的三维结构有限元分析软件。它的特殊之处在于,它依赖一个特定且较旧版本的稀疏矩阵求解库 SPOOLES 2.2,这个库在现代发行版中早已不见踪影。因此,我们必须先手动编译这个“古董”依赖。

构建步骤:

  1. 安装基础依赖

    sudo apt update
    sudo apt install build-essential gfortran make libarpack2-dev libopenblas-dev
    
  2. 编译并安装 SPOOLES 2.2

    • 获取并解压源码:
      cd /usr/local
      sudo mkdir spooles && cd spooles
      sudo wget http://netlib.org/linalg/spooles/spooles.2.2.tgz
      sudo tar -xvzf spooles.2.2.tgz
      
    • 魔改时刻SPOOLES 2.2 的源码过于古老,无法直接通过现代 GCC 编译。我们需要打两个 Patch:
      # 修复 Makefile 中的一个文件名错误
      sudo sed -i 's/drawTree\.c/draw.c/' Tree/src/makeGlobalLib
      # 修复 C 源码中一个不再被支持的 NULL 指针用法
      sudo find . -type f -name '*.c' -exec sed -i -E 's/IVinit\(([^,]+),[[:space:]]*NULL\)/IVinit(\1, 0)/g' {} +
      
    • 编译 SPOOLES
      sudo make global
      
      这会在 /usr/local/spooles/spooles.a 生成我们需要的静态库。
  3. 编译 CalculiX

    • 获取源码并解压。
    • 魔改时刻:修改 CalculiX/ccx_2.22/src/Makefile,手动指定 SPOOLES 库的路径以及其他链接库:
      ...
      DIR=/usr/local/spooles.2.2
      
      LIBS = \
             $(DIR)/spooles.a \
              -larpack -lopenblas \
              -lpthread -lm -lc
      ...
      
    • 编译 CalculiX 主程序:
      make
      

运行验证:
编译成功后,我们使用官方提供的一个名为 achtel 的测试用例进行验证。

# 假设 acht.inp 文件在当前目录
./ccx_2.22 achtel

程序正常执行计算,并将结果输出到 achtel.dat 文件中,证明整个编译流程成功。

...
 Factoring the system of equations using the symmetric spooles solver
 Using 1 cpu for spooles.
...
 Job finished

详细的测试报告请见:CalculiX 测试报告

2. OpenCASCADE & NETGEN - 互相依赖的 CAD 内核与网格生成器

OpenCASCADE (OCCT) 是一个强大的开源 CAD 内核,而 NETGEN 则是一款优秀的网格生成器,并且可以选择使用 OCCT 作为其几何内核。在 RevyOS 上,我们需要先从源码编译 OCCT,然后再编译 NETGEN 并链接到我们自己编译的 OCCT。

构建 OpenCASCADE (OCCT):

  1. 安装依赖
    sudo apt install cmake-curses-gui tcl-dev tk-dev libfreetype6-dev libgl1-mesa-dev libx11-dev
    
  2. 配置与编译
    OCCT 使用标准的 CMake 流程,过程比较顺利。
    # 获取源码并进入
    mkdir build && cd build
    cmake ..
    make -j$(nproc)
    sudo make install
    
    sudo make install 会将 OCCT 的头文件和库安装到系统目录,方便后续其他程序(如 NETGEN)找到它。

构建 NETGEN:

  1. 安装依赖
    sudo apt install python3-dev python3-tk tk-dev tcl-dev libxmu-dev liblapacke-dev
    
  2. 获取源码并初始化子模块
    git clone https://github.com/NGSolve/netgen.git
    cd netgen
    git checkout v6.2.2505 # 锁定到一个稳定版本
    git submodule update --init --recursive
    
  3. 魔改时刻:NETGEN 的 CMake 脚本默认会启用 -march=native 编译器优化选项,但这在我们的 RISC-V 测试平台上会导致编译错误。因此需要手动修改根目录的 CMakeLists.txt 文件,禁用该选项:
    # 将 ON 修改为 OFF
    option(ENABLE_NATIVE_ARCH "Enable native architecture optimizations" OFF)
    
  4. 配置与编译
    在配置阶段,CMake 会自动找到我们上一步安装好的 OCCT。
    mkdir build && cd build
    cmake ..
    make -j$(nproc)
    make install
    

运行验证:
安装后,配置好环境变量,即可启动 NETGEN 的 GUI。

export NETGENDIR="/path/to/your/netgen/install/bin"
export PATH="$NETGENDIR:$PATH"
export PYTHONPATH="/path/to/your/netgen/install/lib/python3.11/dist-packages:$PYTHONPATH"
netgen

GUI 成功启动,证明 OCCT 和 NETGEN 均已正确构建和链接。

详细的测试报告请见:

3. MayaVi - 依赖系统库的 Python 可视化工具

MayaVi 是一款基于 VTK 的科学数据可视化 Python 库。在 RISC-V 平台上,其关键依赖 VTK 和 wxPython 都没有预编译的 wheel 包,直接 pip install 会失败。我们的策略是:使用 apt 安装最复杂的原生依赖 VTK,然后利用 pip 在一个特殊的虚拟环境中安装 MayaVi 及其余 Python 依赖

构建步骤:

  1. 安装系统依赖

    sudo apt install git uv build-essential python3-vtk9 libgtk-3-dev
    

    这里的 python3-vtk9 是关键,它为我们提供了系统级的 VTK Python 绑定。

  2. 创建可访问系统包的虚拟环境
    这是本次操作的核心技巧。

    git clone https://github.com/enthought/mayavi.git
    cd mayavi
    # --system-site-packages 标志是关键
    uv venv --system-site-packages
    source .venv/bin/activate
    
  3. 分步安装

    • 首先,在不处理依赖的情况下,强制在当前环境中编译安装 MayaVi:
      uv pip install --no-build-isolation --no-deps .
      
    • 然后,再使用 uv 安装剩下的纯 Python 依赖和需要编译的 wxPython:
      uv pip install "numpy>=2.0" traits traitsui pyface envisage apptools wxPython
      

运行验证:
执行一段测试代码,如果能成功显示三维图像窗口,则证明安装成功。

python -c "from mayavi import mlab; mlab.test_points3d(); mlab.show()"

在我们的测试平台上,成功弹出了交互式 3D 窗口。

详细的测试报告请见:MayaVi 测试报告

总结

本期我们通过三个案例,展示了在 RISC-V 平台上构建复杂工程软件时可能遇到的一些典型问题及其解决方案,包括手动编译古老依赖、修改构建脚本以及利用混合包管理策略等。这些操作虽然比简单的 apt install 要复杂得多,但它们是打通软件生态“最后一公里”的关键步骤。

下一期,我们将直面那些最顽固的挑战——即使我们使出浑身解数,最终仍然构建失败的软件。我们将详细分析失败的原因,为社区的未来工作提供参考。

欢迎各位复现/吐槽丁丑小队的所有测试结果。
如果有对我们的测试方法/结果有任何建议/问题,欢迎直接在 GitHub 开 issue,或者在论坛 @ 我们、回帖询问。

7 个赞

goooooooooooooood job! 期待下一篇

2 个赞

goooooooooooooood job!

1 个赞

那啥,CMake 其实可以传环境变量的

是的…