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

相关推荐
Sakura_j_h_4 小时前
STM32F103 定时器的三种用法:PWM 输出、输入捕获与编码器接口
stm32·嵌入式·输入捕获·定时器·pwm·编码器·1024程序员节
pipixia200335 小时前
C++ 面试高频:namespace 的 6 个知识点,从 using 到匿名命名空间
c语言·学习·算法·嵌入式·命名空间·c++面试·匿名命名空间
Zevalin爱灰灰7 小时前
Linux入门第一部分(Ubuntu入门篇) 第二章 浅尝Ubuntu(二)
linux·嵌入式·1024程序员节
Zevalin爱灰灰13 小时前
Linux入门第一部分(Ubuntu入门篇) 第二章 浅尝Ubuntu(一)
linux·嵌入式·1024程序员节
Zwawa1 天前
一盏 LED 不够用了:让同一盏灯说出不同的话
c语言·单片机·嵌入式
2035去旅行1 天前
U-Boot简介
嵌入式·arm·soc
嵌入式分享1 天前
驱动之路#43:一文理清 I2C 子系统架构
嵌入式
HRTOS1 天前
8051 单片机 RTOS 开发的难点在哪里?从任务切换、中断管理到资源控制
单片机·51单片机·嵌入式·8051·hrtos
Y Shy2 天前
2026.10 在受限的嵌入式机器人设备中使用LLM Agent
机器人·llm·嵌入式·agent
用户766166003112 天前
先中转、后打洞:libnpf 的 NAT 穿透与对称型 NAT 实战
嵌入式