软件开发里的 prebuilt 是什么

做项目的时候经常撞见 prebuilt 这个词:AOSP 有个巨大的 prebuilts/ 目录,CMake 里有 IMPORTED 库,Android.bp 里有 cc_prebuilt_library_shared。看着都认识,但一直没真正搞明白它想表达什么。

这篇把它讲清楚。

一句话解释

prebuilt = 预先编译好的二进制产物,直接以二进制形式引入项目,而不是在本地从源码编译。

关键对立面是:

  • build from source ------ 仓库里放源码,构建时用你自己的编译器、你自己的编译选项编出来
  • prebuilt ------ 仓库里(或外部制品库)直接放 .so / .a / .jar / .aar / 可执行文件 / 工具链,构建时只做链接或拷贝

所以 prebuilt 的本质特征是:

它已经被别人、用别人的编译器、别人的编译选项、针对别人的目标平台编好了,你无法改变。

你项目里绝大多数 prebuilt 相关的坑,都来自这一句。

从一个真实例子看起

先看这句话:

fluoride depends on android prebuilt, llvm compiler may not support some special compilation options

Fluoride 是 AOSP 的蓝牙协议栈(bluedroid 的后继)。它"依赖 android prebuilt",指的是依赖 AOSP 的 prebuilts/ 目录树。这里面主要有两类东西:

1. 预编译的依赖库

libchrome、libbase、protobuf、libcutils 等等。Fluoride 的代码直接 include 它们的头文件、链接它们的二进制。这些库只在 AOSP 构建环境里存在,离开 AOSP 就拿不到。

2. 预编译的工具链本身

prebuilts/clang/host/linux-x86/... ------ AOSP 自带一套定版的 clang。Android.bp 里会写一堆只有这个特定 clang 版本才认的 flag:某些 -Xclang 参数、特定的 sanitizer 选项、-fno-c++-static-destructors 之类。

所以那句话实际在说:Fluoride 这套代码绑死在 AOSP 的 prebuilt 生态上。 如果你换成自己的 LLVM(比如移植到 NuttX / Vela、或者只是用系统 clang 编),这些特殊编译选项它不认,直接编不过。

这是移植 AOSP 组件的典型阻塞点 ------ 不是代码本身有问题,而是它假设了一整套 prebuilt 环境的存在。

prebuilt 出现的其他场景

工具链

arm-none-eabi-gcc 官方发布的压缩包、Android NDK、rustup 下载的 Rust toolchain。没人会为了编一个固件先自己 build 一遍 GCC。

构建系统里的"导入"语法

各家都有对应写法,看到这些就是在引入 prebuilt:

构建系统 写法
Soong / Android.bp cc_prebuilt_library_shared、android_app_import、prebuilt_etc
CMake add_library(foo SHARED IMPORTED)
Make / NuttX 直接把 .a 丢进 EXTRA_LIBS
Gradle implementation files('libs/xxx.aar')

包管理器的二进制分发

Python 的 wheel(相对于 sdist 源码包)、npm 原生模块的 node-pre-gyp 预编译包。pip install numpy 不用等编译半小时,就是因为有现成的 manylinux prebuilt wheel。

闭源 blob

WiFi / BT / GPU 固件、厂商 SDK 里的 .a。

这类是根本没有源码的 prebuilt。它和"有源码但图省事先编好"是两种不同情况 ------ 排查问题时,这个区别决定了你有没有退路。

CI 加速

把编译耗时长、又不常变的部分做成 prebuilt 制品缓存:Docker base image、第三方库、预编译 sysroot。

为什么要关心 prebuilt 还是 from source

维度 prebuilt from source
构建速度 快 慢
可调试性 差,常无符号 / 无源码 好
改编译选项 不行 行
换 ABI / 工具链 容易炸 重编即可
换目标架构 需要对应架构的 prebuilt 重编即可
打安全补丁 等上游出新二进制 自己打 patch

嵌入式场景下最常踩的两个坑:

ABI 不匹配。 prebuilt 是用 GCC 编的、你用 clang;或者两边 C++ 标准库版本不同。结果是链接期符号对不上,报一堆 undefined reference,而函数名明明就在那儿(只是 mangling 不一样)。

缺符号。 prebuilt 假设 libc 里有某个函数,但你的目标平台(比如 NuttX)没实现。链接到最后一步才暴雷。

一个容易混的词

precompiled header(PCH / 预编译头) 和 prebuilt 没关系。

PCH 只是把常用头文件预先解析成中间格式,用来加快编译速度,纯粹是编译期优化。中文里两个都带"预编译"三个字,但指的东西完全不同。

相关推荐
7yewh14 小时前
SLAM 三维空间刚体运动(2)
数据结构·人工智能·机器人·嵌入式·slam
LCG元15 小时前
树莓派 Pico RP2040 PIO 逻辑分析仪实战:SM 指令周期拆解、DREQ 触发 DMA 环形缓冲与采样率参数实测
嵌入式·树莓派·rp2040
7yewh1 天前
SLAM 从视觉里程计到建图(6)
数据结构·人工智能·机器人·自动驾驶·嵌入式
Zwawa1 天前
蜂鸣器为什么会响:有源、无源和低电平触发
单片机·嵌入式
LCG元1 天前
STM32L431 QSPI驱动W25Q256实战:内存映射模式配置、4字节地址模式陷阱与读写吞吐实测
stm32·单片机·嵌入式·flash
fanged2 天前
嵌入式架构学习1--前言
嵌入式
feasibility.2 天前
把城市压缩成 2067 个盒子:CosFly 无人机跟踪数据管线论文解剖
人工智能·大模型·嵌入式·无人机·vla
susplus3 天前
【ARM 裸机开发 (IMX6ULL-mini)】I2C协议详解
嵌入式·arm·i2c
番茄灭世神3 天前
PN学堂GD32教程第11篇——I2C与EEPROM
c语言·stm32·单片机·嵌入式·gd32