多机部署practice

@vrqq  January 6, 2024

Prerequisition

  • 开发环境: GLIBC_2.34 + GLIBCXX_3.4.29
  • 目标主机: GLIBC_2.16 未提供libstdc++
  • 我们需要发行一个 libxxx.so, 以及基于它的小工具 mine.exe
  • libxxx.so 在编译时依赖了不可或缺的 libdrv1.so (闭源 外部提供) 这个so依赖了 GLIBC_2.34 + GLIBCXX_3.4.29
  • 最终需要打包基于x86_64和arm两个arch
  • glibc 位于kernel中,一般生产机不升级,但 libstdc++ 可以随程序发布

综上所述

  • 不能在编译 libxxx.so 时用 -static_libstdc++,因为libdrv1.so有强制依赖 libstdc++.so
  • 同样的原因 也不用 LLVM libc++

Solution

以目标主机arch=arm,Linux系统自带 GLIBC 2.16 举例(目标主机自带的 libstdc++.so 即使有也不用)

  1. 下载一套目标主机kernel (内含glibc 2.16)
  2. 基于以上glibc 在开发机编译 目标主机 libstdc++.so (ELF,ARM, GLIBCXX_3.4.32 + GLIBC_2.16) 和 arm_linux_gcc_15 (cross compile)
  3. 使用 arm_linux_gcc_15 编译目标主机 libxxx.so,编译出的so依赖 上一步"的libstdc++.so.32"和 第一步的 "glibc.so.16",部署用
  4. 若本地gcc版本过低,编译一套基于本地 GLIBC_2.34 的 libstdc++.32 和 gcc15,本机调试时用

编译本地和 cross GCC
BTW:g++编译器和libstdc++是同时产生的
网上相关文章很多了,这里引入几个,大概介绍一下概念:

和"目标主机"的绑定太深了, 是为了解决个什么问题呢?

  • 基于-march=... 做指令集优化
  • 使用最新的代码,获得最佳性能

目标主机的glibc在kernel里 无法升级,c++编译出来的程序同时依赖libstdc++和glibc,对他俩分别有最小版本要求。
开发机:libstdc++.so.29 依赖的glibc.so.34
目标主机:glibc 2.16

case1. 目标主机有了 libstdc++.so.29
我主机的libstdc++.29会带出glibc.34的函数 在目标主机运行不了

case2. 我的主机编译了一套极度保守的libstdc++.1 glibc.1
在所有机器上都能运行,但代码不是最新,性能可能不佳(例如调用了旧的为兼容保留下来的函数)
有的函数用不了,C++ standard, C standard, 都随着这些库在升级

Bazel方案

buck 2 看起来简单又规矩,可惜bazel生态好,有protobuf,grpc等开箱即用,希望fb多多努力多搞点周边,bazel历史包袱太大了,现在又走npm路线,为了讨好消费者吧


添加新评论