不一样的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集成。
显然go的构建系统还不够强大,开发人员还无法定制构建过程与结果。只有go build命令而没有辅助go build命令的工具,在这一方面go依然任得道远。
常见构建系统列表
| 语言 | 构建系统 | 说明 |
|---|---|---|
| c/c++ | gnu make, automake, nmake, cmake, qmake | 各个make对应于不同时期,不同架构体系下的构建工具 |
| java | ant, maven, gradle | 目前maven与gradle是主流, ant已经退出历史舞台 |
| python | distribute, setuptools, easy_install, eggs, pip | python的构建系统百家齐放,世界大战般。不过pip最终赢得王座 |
| nodejs | npm | - |
| javasript | grunt, gulp, webpack | 谁是王者? |
| go | go build | 嫡系 |
| rust | cargo | 号称最强大的构建系统, 超级大杀器。 |
| ruby | rubygem | - |
| .net | visual studio之nuget | 最牛逼的IDE, 包罗万有 |
| swift&object-c | xcode | 最霸道的IDE |
除了上述列表的构建系统,现在已经有不少云构建系统存在。比如google的Bazel,滴滴的建木。
上面提到的大杀器cargo,它与其他语言的构建系统不同,其既是构建系统又是构件系统。cargo口号叫得那么响,除了其是官方出品之外,恐怕也只是为了与go一较高下。rust可能为程序 员考虑得更多,极力地想讨好程序员。而在构建系统方面,对比一下go module与cargo,只怕go也是借鉴了不少cargo的东西。但与当代成熟的构建系统,比如gradle,并没有高下立判之感。不同之处在于cargo在配置中使用rust语言本身来做扩展,而gradle则是使用自身的DSL语言来实现。相比这下,go在这一方面还需要快马加鞭,总比在屁颠屁颠地跟在别人后面追好。
构件系统
go语言的构件系统,官方默认是github。此外也可以是支持vgo下载协议的仓库(如athens, goproxy.io),然后通过设置GOPROXY环境变量来设置构件系统代理,此举可以完美解决国内下载依赖不畅的问题。而对于私库,目前免费开源的只有athens,但是仍不够完善。除此之外,jfrog的artifactory也支持go私库,只不过要收费。
私库对于一个成熟、专业的开发团队来说,是极其重要的一个工具。团队内部会产生大量的公共程序包,对于go语言来说,如果没有一个类似于maven的nexus仓库,那么项目如何构建?如何持续集成?虽然必然会有各种巧妙地方案来解决或避开这些问题,但无疑是不得已而为之。现代编程体系发展至今天,没有理由让历史倒退,走回批处理或者基础设施(网络)的老路来解决问题。有时候我真觉得王垠大侠对go的批判有道理,不吸取前人在编程语言设计上的经验教训,而一意孤行到底。尽管我不否认,写go确实会比java舒服很多,java严谨地啰嗦,所以它只适合用来做大项目。
鉴于此,go的官方团队应该鼓励社区去达成构件系统这事。而不应该像go module那样,将社区招之即来,挥之即去,利用完了,就没社区什么事了。
那么构件系统,应该具有以下特征。
- 构件存储:包括二进制包、源码包、文档
- 版本:支持release、snapshot,
- 元数据:设计良好的元数据的存储机制
- 缓存:支持本地缓存
- 安全&权限:支持用户、角色、权限模型;支持常用的用户体系集成,如LDAP
- 仓库管理:多语言,多仓库,支持代理仓库,远程仓库。
常见构件系统列表
| 构件系统 | 支持语言/系统 | 支持构建系统 | 说明 |
|---|---|---|---|
| nexus | java | maven, gradle, npm | 历史悠久,流行的构件系统 |
| jfrog | java, go | maven, gradle, go | 后起之秀,有选择的收费 |
| proget | .net | vistual studio | - |
| cargo | rust | cargo | - |
| Cocoapods | swift&object-c | xcode | - |
| Carthage | swift&object-c | xcode | - |
| dpkg&apt | Debian, Ubuntu | - | - |
| yum | CentOS | - | - |
| homebrew | Mac OS | - | - |
请关注公众号

不一样的go语言-构建系统与构件系统的更多相关文章
- 从零构建JavaScript的对象系统
一.正统的类与继承 类是对象的定义,而对象是类的实例(Instance).类不可直接使用,要想使用就必须在内存上生成该类的副本,这个副本就是对象. 以Java为例: public class Grou ...
- 语言模拟ATM自动取款机系统
C语言实验报告 题目名称:C语言模拟ATM自动取款机系统 C语言模拟实现ATM自动取款机功能:输入密码,余额查询,取款,存款,转账,修改密码,退出功能: 代码实现的功能: 账号及密码输入: ...
- go语言打造个人博客系统(二)
go语言打造个人博客系统(二) 在上篇文章go语言打造个人博客系统(一)中,我们了解了go语言的优点和go语言的数据库操作,本次我们会完成博客系统的后端开发. 博客系统后端接口开发 路由测试 ht ...
- C语言课设——电影院选票系统
C语言课设--电影院选票系统 1.课题介绍 大家都爱看电影,现请参考一个熟悉电影票预订系统,实现C语言版的订票系统.了解订票如何实现的.系统主要有2类用户:管理员用户和顾客用户. 管理员用户 1.电影 ...
- go语言打造个人博客系统(一)
go语言打造个人博客系统(一) 为什么选择go语言? 听说go语言是在几年前,但真正深入了解他却是在2017年,因为当时作为讲师 ,需要准备go语言的课程,结果稍一接触立刻就喜欢上这门语言了,作为 ...
- python为什么叫胶水语言?python为什么是系统脚本?
python为什么叫胶水语言?python为什么是系统脚本? 特点是什么? python现在最广为闻名的形容大概有这些: 他是很好的胶水语言.什么是胶水语言?反正当时的我不知道. 他是新一代的系统 ...
- 构建嵌入式小型Linux系统
构建嵌入式小型Linux系统 摘要:用buildroot构建x86的交叉编译工具链:裁减linux内核,尽可能做到最小:手工构建根文件系统:安装qemu虚拟机,仿真新配置的Linux系统:为新配置的L ...
- R语言构建蛋白质网络并实现GN算法
目录 R语言构建蛋白质网络并实现GN算法 1.蛋白质网络的构建 2.生物网络的模块发现方法 3.模块发现方法实现和图形展示 4.附录:igraph中常用函数 参考链接 R语言构建蛋白质网络并实现GN算 ...
- C语言构建小型Web服务器
#include <stdio.h> #include <sys/socket.h> #include <stdlib.h> #include <string ...
随机推荐
- centos6 python 安装 sqlite 解决 No module named ‘_sqlite3′
原文连接: http://blog.csdn.net/jaket5219999/article/details/53512071 系统red hat6.7 也即centos6.7 python3.5. ...
- [转]bus error与segment error
在c程序中,经常会遇到段错误(segment error)和总线错误(bus error),这两种问题出现的原因可能如下 段错误: 对一个NULL指针解引用. 访问程序进程以外的内存空间. 实际上,第 ...
- swift计算 switch case
var year = var month = var day = ; let daysOfFeb = year % == && year% != || year % == ?: var ...
- SpringMVC参数绑定(四)
1.默认支持的参数类型 处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值. HttpServletRequest 通过request对象获取请求信息 HttpServletResponse ...
- hadoop学习笔记之一步一步部署hadoop分布式集群
一.准备工作 同一个局域网中的三台linux虚拟机,我用的是redhat6.4,如果主机是windows操作系统,可以先安装vmware workstation, 然后在workstation中装上3 ...
- ARMV8 datasheet学习笔记3:AArch64应用级体系结构之Memory Type and Attributes
1.前言 2. Memory类型和属性 memory分为normal memory和device memory,两种类型的Memory有各自的属性,除了下面介绍的几种属性外,还有其他一些杂项属性 2. ...
- TERMIOS详解【转】
转自:https://blog.csdn.net/guo_wangwei/article/details/1102931# TERMIOS NAME termios, tcgetattr, tcset ...
- ES系列二、CentOS7安装ES head6.3.1
1.Head插件简介 ElasticSearch-head是一个H5编写的ElasticSearch集群操作和管理工具,可以对集群进行傻瓜式操作. 显示集群的拓扑,并且能够执行索引和节点级别操作 搜索 ...
- Ex 6_14 布料剪裁问题_第八次作业
子问题定义: 定义p[i][j]为布料宽为i,高为j的最优产出,每次剪下一块布料,剩余布料最多形成三块矩阵面料.每次剪裁会有两种情况,水平切割布料,其次是将布料旋转90度后在切割布料. 递归关系: 初 ...
- PHP中的一些常用函数
<?php //===============================时间日期=============================== //y返回年最后两位,Y年四位数,m月份数字 ...