Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

构建与依赖

复习

  • 版本控制:保存与合并代码变更
  • 编译器总装:从源码到可执行文件
  • 从源代码到可执行文件:编译、汇编、链接的流水线

TL;DR

  • 构建把源文件、库和配置变成可发布的产物
  • 依赖管理记录并获取程序用到的外部库
  • 自动化构建保证结果一致、可重复
  • “在我机器上能跑”正是构建要消灭的问题

正文

  代码写好了,也通过了测试。但它还不能直接交付——它需要经过构建(build),才能变成用户能用的东西。

构建:从源码到产物

  构建,就是把源代码、库、配置等各种原料,加工成可发布产物的过程。它大致包括:

  • 编译:把源码编译成目标文件(还记得前面讲的那条流水线吗)
  • 链接:把目标文件和库连成可执行文件
  • 打包:整理成安装包、镜像等可交付形态
  • 有时还有代码生成、资源处理等步骤

  这些步骤,如果全靠人手动敲,既繁琐又容易出错。所以实践中通常用自动化构建:一条命令,把整套流程跑完。

依赖:程序也用别人的库

  现代程序很少“自给自足”,几乎都会用到第三方库。这些外部库,就是程序的依赖(dependency)。

  依赖管理要处理两个问题:

  • 记录:我用了哪些库、各自哪个版本
  • 获取:怎么把这些库下载、安装到本地

  依赖管理工具会自动完成这些,让你不必手动去找、去装。但这也带来了新的麻烦:版本兼容——库升级了,可能和你的代码不兼容;不同库之间,也可能要求同一个库的不同版本。

可重现的构建

  “构建”最重要的目标之一,是可重现同样的源代码,在任何时候、任何机器上构建,都应该得到相同的结果。

  为什么这很重要?因为如果构建结果不可重现,就会出现经典的一幕——“在我机器上能跑啊”:开发者本地一切正常,换台机器或换个环境就崩了。原因往往是构建环境的差异:缺了某个依赖、版本不对、配置不同……

  解决之道,是把构建所需的一切都明确记录下来(依赖的精确版本、构建配置等),让构建过程像一份精确的配方:照着做,无论谁来、在哪做,都得到同样的产物。 这样,问题才能被稳定地复现和解决。

  至此,“怎么把代码变成能交付的东西”就清楚了。接下来,要面对的是软件长期运行中最实际的两件事:数据往哪存、性能怎么调。

思考题 1

  “构建”大致包括哪些步骤?

思考题 2

  为什么“能重现的构建”很重要?

小结

知识点

  • 构建把源码、库与配置加工成可交付产物
  • 步骤包括编译、链接、打包等
  • 依赖管理记录并获取外部库及其版本
  • 可重现的构建消除环境差异带来的问题

参考资料

  1. Wikipedia(zh):软件构建:把源码加工为可运行产物的过程
  2. Wikipedia(zh):依赖管理:管理软件所依赖的外部组件

思考题答案(仅供参考)

思考题 1

  大致包括:编译源码、链接库与目标文件、按需进行代码生成或资源处理,最后打包成安装包或镜像等可交付产物。实践中通常由自动化构建工具一次完成。

思考题 2

  因为它保证同样的源码在任何时间、任何机器上都得到相同的结果。若构建不可重现,就会出现“在我机器上能跑”的问题:问题难以复现、难以排查。可重现的构建让环境差异不再捣乱,问题能被稳定定位。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪