不一样的go语言-构建系统与构件系统

  代码的最后一步是构建成计算机可识别的二进制数据,然后才得以在计算机上运行。如果你曾经写过有点规模(至少数十个以上独立的源文件,且需要依赖第三方包)C语言项目,必定对C语言项目的构建过程印象深刻。或者当你曾经在linux系统中使用rpm命令安装程序 时,系统一遍又一遍不厌其烦地提醒你缺少依赖时,不知那时的心情如何?前一个问题可归属于构建系统(Build Systems, Build Automation),后一个问题则属于构件系统(artifact repository manager or binary repository manager)的范畴。而平常我们所说的“构建系统”往往代指构建系统与构件系统。也可以简略地认为,构建系统是由程序与配置组成的,而构件系统是由软件包与软件元数据组成。

构建系统

  go语言的程序构建,基于go build命令,内置于官方发行版中。其天生正统,而不像java有ant、maven、gradle,python有pip。它的构建体系经历过几个阶段,最早是依赖于GOPATH,其次是vendor(dep),再到后来就是go module(早期也叫vgo)。在具体介绍构建系统之前,按惯例先上示例代码。

  示例代码是一个mini的java项目结构(非maven、gradle结构),主要演示如果完全依赖于javac,如何做java项目构建。

├── com | └── eventer | ├── a | └── Person.java | └── Test.java └── build | ├── com | └── eventer | ├── a | └── Person.class | └── Test.class package com.eventer; import com.eventer.a.Person; public class Test { public static void main(String[] args) { System.out.println(new Person()); } } package com.eventer.a; public clss Person() { }

  以下是构建过程。

[eventer@localhost]# ls -a total 0 drwxr-xr-x 4 eventer eventer 128 Mar 26 22:34 . drwxr-xr-x 38 eventer eventer 1216 Mar 26 22:22 .. drwxr-xr-x 3 eventer eventer 96 Mar 26 22:34 build drwxr-xr-x 3 eventer eventer 96 Mar 26 22:23 com [eventer@localhost]# javac -d build com/rfchina/test/*.java com/rfchina/test/a/*.java [eventer@localhost]# cd build [eventer@localhost]# java com/rfchina/test/Test

  从上述代码可以看出,这仅仅是构建一个只有两个类,且没有第三方依赖的微型项目,javac命令的参数已经挺长。可想而知,当项目中有成千上百个类,几十个依赖,再加上编译选项、注解处理等等,javac的参数长度会有多长。而构建是随时发生的,这样的任务毫无疑问应该有一个工具来完成。我相信最早的时候这样的工具非批处理脚本莫属。在后来的日子里,随着越来越多的需求加入到构建的各个阶段,如编译前、编译时、构建前、构建后、测试阶段、打包、发布等,甚至在开发阶段也有很多需求产生,如代码生成。所有这些后来都被构建系统所实现,从最早的ant,到后来一统天下的maven,到现在的gradle,越来越强大。

  再比如GNU构建系统经典的configure, make, make install三部曲,已经成为linux系统构建软件的标准与习惯(即使不是GNU构建系统,很多软件的构建也使用这三个过程)。

  现代的编程语言大多给出了自己专用的构建系统与构件系统,它们两者已成为软件开发团队必不可少的工具。go语言自然也不能例外。

wikipedia对构建的定义

Build automation is the process of automating the creation of a software build and the associated processes including: compiling computer source code into binary code, packaging binary code, and running automated tests.

  在《不一样的go语言-gopher》一文中,“依赖管理”与“构建方式”两节中已经讲述过go语言关于构建的种种,在此不再赘述。也曾提到了当前go的构建系统在国内的种种不便及对策。正所谓合久必分,分久必合,在官方的支持下,go的构建系统日趋成熟,但目前独独一个好的构件系统,一个可以在本地搭建的构件系统。关于这一点,将在下一节中详述。

  一个好的构建系统,应该具有以下特征。

自动解决依赖关系:包括直接依赖与间接依赖,如A依赖B,B依赖D,C依赖D,构建系统应自动引入A、B、C、D依赖,并去重。

增量&并行构建:增量构建是只对变更构建而跳过没有变更的文件或任务;并行构建指各自独立的任务可以并行执行。

测试:如单元测试、并行测试、性能测试、测试报告等。

错误提示:友好详细的构建错误提示,丰富的调试或错误输出参数控制。

自定义构建目标:比如自定义打包格式, exe, zip, etc。

基于配置&约定:约定优于配置,构建输入输出易配置。

可扩展:可自定义扩展,如maven与gradle的plugin机制

跨平台:构建系统本身需要具备跨平台的特性,或者能在交叉构建(在某个目标系统构建另一个目标系统的程序)

发布:支持发布程序包至私库及各类不同协议的第三方仓库。

IDE集成:支持与各大主流IDE集成。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfjpf.html