乐趣区

关于golang:bgo-让构建-go-程序更容易

bgo

一句话理解:bgo 管 exe 不论 lib

前言

前言之前:

这次的前言很长,能够间接跳过。

bgo 是一个构建辅助工具,它和已知的那些为 go 应用程序构建服务的工具没有多大的不同,都能反对在你的工作环境中穿插编译构建出 go 应用程序的执行文件。<!–MORE–>


只管这个能力原本是 go build 自带所有,但这样外包装一次后的辅助性的构建工具能够让你节俭大量的精力,无论是那些难以记忆的 go build 命令行参数也好,还是那些咱们不得不用到的前筹备,后处理步骤,例如 go generate,复制到某个公共地点,等等。

所以这就是 bgo 这样的工具的用处,省力。

缘起

当然,为什么我要开发又一个辅助工具呢?

起因也不简单,有这么几个:

我当初经常在一个大目录中弄一大堆小我的项目,兴许只是试验一下某个性能,做某件事情,兴许是因为我须要列举一大堆 examples 给用户睇,总之很多就是了。但一个小的周期里,我通常聚焦在其中的某一个或者某两三个,为此,切换目录,构建就很疲乏了。Goland 倒是很贴心能让我省去这些命令行环境里的工作,但它的运行后果窗口不能反对全功能的键盘交互,所以有的行为我就只能开出一个终端来跑。当然还有很多别的是 Goland 肯定做不了的,就不列举了,总之这是一个具体的问题。对此,为什么不 vscode 呢?你用过吗?你要晓得 vscode 跑 goapp 只有调试跑某一个主程序的能力,想要不调试,或者想多个 apps,须要去它的嵌入终端里敲命令行的。另外,如果你不在 go.mod 那里关上工作区的话,vscode 会有很多问题——换句话说,vscode 顶多反对单个 go.mod 代表的模块。

另一个起因,是作为较为正式的公布,我可能频繁须要用到 -X 或者 go generate。对此,我本来有一个简单的 Makefile 能够主动解决这些问题。不过他们对于我在大规模我的项目中也不怎么好用,因为我可能会有很多不同的目录对应不同的子模块。

再一个起因是构建时的程序问题,我有时候须要有序地做一系列构建,而有时候我须要很快地构建单个 target 在 exeutable 模式下运行和检视后果。

当然还有其它起因,不过拉拉杂杂的就不说了。

你能够留神到次要的理由还是在于我在保护大型项目构造。为什么不切分成很多很多的 repos 呢?这又波及到另一个问题:go modules 不反对多个嵌套的 go.mod。也就是说,如果你的下级目录有 go.mod,那么上级就不能够再有,这是个很简单的状况,但终归对于你来说,这个限度是很硬的,所以这样的构造行不通:

/complex-system
  go.mod
  /api
    /v1
      go.mod
  /common
    go.mod
  /account
    go.mod
  /backends
    /order
      go.mod
    /ticket
      go.mod

这里只列举了局部目录构造,而且仅仅是个示意。

同样地,还是会有人说,每个 go.mod 都一个 repo 就好了丫。恩,是这样的,的确这样是能够的,也只能这样做。

完了之后就须要想方法解决依赖关系了。

go 1.18 的 go.work 对此没有什么帮忙,甚至于很难用。

git submodules?很麻烦,很难用,会遗记状态,而后就杯具。

再来有人就会说,那就顶级一个 go.mod,其它的都不要用,只分出目录构造就好了。对的,在我几年前做相似的大规模我的项目时就是这么做的,但 api 的 protobuf 参考,common 的 etcd 参考,等等,混淆在一起,而且都是解决起来很麻烦的那种,最初弄得整个巨型我的项目臃肿不堪,而且毫无必要地凌乱。

其实,已经有一段时间,多个 go.mod 嵌套存在是能够随随便便运作的,但那个阶段很短,我遗记是在 1.13 还是哪个期间了,总之这是一个边远的思念了。那段时光里我的项目的构型我就称心,但起初从新适应单 go.mod 也更苦楚。

所以

理由说了一堆,然而 bgo 只解决了一部分问题,也就是很多小 apps 散布在一堆简单的子目录中时的构建问题。

采纳 bgo 的话,咱们就能够用一个大的顶级目录来治理若干的子项目了,当然,因为 go modules 的限度在顶级目录是不能建设 go.mod 的(免得子目录中的 go.mod 呈现问题),它只是起到汇集的作用,而咱们利用 Goland 或者 vscode 关上这种构造时也都会很 OK。

当初的构型:

/atonal
  .bgo.yml
  /api
    /v1
      go.mod
  /common
    go.mod
  ...

你能够留神到,在顶级目录中蕴含一个 .bgo.yml 文件,这就是 bgo 的配置文件了,它能够通过 bgo init 通过扫描子目录之后主动生成,而后在这个根底上你能够进一步地调整。

惟一的问题是,它只收集 main 包所在的目录,也就是可能产出 executable 的那些目录,至于说你的带有 go.mod 的目录并不真的被纳入治理范畴。

这是 bgo 的限度,但本也就是 bgo 的设计指标:咱们是扫描和治理一系列的 CLI apps 并以一种较轻便的形式实现相应的构建。咱们并不提供以 go.mod 为标记的多个 modules 的治理,这种性能要么咱们另行设计一款工具来说,要么不做,省得哪天 google 发神经有搞一套 go.zone 进去。

当然,你能够为每个 go.mod 配一个 main.go 来让 bgo 兼管它。但总的来说,bgo 管 exe 不论 lib

令人悲观的 go 演进

话说 go.mod go.work 都有了,却全都不是对大型项目做解决的无效计划,而是仅仅局限在 的某一个 module 之中。

在 Go 的工程治理中,总是有很多问题:

  • 公有 repos 的解决
  • 问题 repo 或者遗失的 repo 的解决
  • 简单的多模块建设与组织
  • 可怜的泛型,还不如没有呢
  • 等等

讲真,我曾抱有很高的期待。但我和 yaml 那些人的情绪预计是类似的,哇,泛型来了,哦,泛型走好。在这个畛域里(主动类型解决,未知类型解决),golang 的泛型算得上是一无是处。依照目前的演进态势,也不可能冀望它解决自在预判未知类型。

如何开始?

装置

首先当然是要装置 bgo。

Releases

bgo 被设计为只需单个可执行文件即可开始工作,所以请在 Releases 下载预编译版本并放到你的搜素门路中。

go get

或者,你能够通过 go get 零碎:

go get -u -v github.com/hedzr/bgo
From source code

Homebrew

homebrew 是能够的:

brew install hedzr/brew/bgo

其它平台的包治理暂不反对,因为这就是个小工具而已。

Docker

也能够应用 docker 形式运行,但略微有点简单,因为须要搭载本机卷下来:

docker run -it --rm -v $PWD:/app -v /tmp:/tmp -v /tmp/go-pkg:/go/pkg hedzr/bgo

这样就和执行原生 bgo 作用统一。

docker 容器能够从这些中央获取:

docker pull hedzr/bgo:latest
docker push ghcr.io/hedzr/bgo:latest

运行

在你想要构建的目录,运行 bgo。

例如咱们在 ini-op 的源代码中运行它:

这就是最简便的开始。

特点

不过如果就是这样,有什么价值呢?命令行缩短器?

bgo 所能做的,特地在于 几处:

  • tags 等等 go build 命令行太长太难于编辑
  • 想要编排构建指令及其前后解决行为。例如退出后处理器,等等。
  • 有一大堆子目录中都有 CLIs,但不想一一构建、或者构建参数各有区别而不能一次性解决。
  • 有一系列的 go modules,但想要对立编排。

这些指标,都能够通过配置文件来解决。

创立构建配置文件

bgo 以当前目录为基准,它会寻找当前目录下的 .bgo.yml 文件,载入其中的 projects 配置信息,而后依照特定的程序顺次构建。

因为咱们强调有序性,因而 bgo 并不反对多个我的项目并行编译。

事实上,这种性能是无价值的,因为它只会升高整体的编译速度。

所以问题的第一个是,.bgo.yml 如何筹备?

办法是,抉择你的根目录来首次运行 bgo。

bgo -f --save          # Or: bgo init
mv bgo.yml .bgo.yml

这个命令会扫描全副子目录,而后编制一个构建配置表并保留为 bgo.yml 文件。

而后你能够抉择重命名配置文件(这是被举荐的,避免谬误运行了 --save 后带来的可能的副作用)。但如果你想,也能够放弃文件名原样不变。

同义词

bgo init
bgo init --output=.bgo.yml

如果你须要一份带正文的示例,请查阅:

https://github.com/hedzr/bgo/blob/master/.bgo.yaml

开始构建

配置文件筹备好之后,就能够跑了:

bgo

这就会将配置文件中的全副 projects 都给构建了。

事实上,如果没有配置文件,bgo 会主动扫描出第一个 main cli 并构建它。

采纳不同的构建范畴

bgo 反对三种范畴,它们的区别在于如何解决配置文件中的 projects 以及是否扫描以后文件夹中的 projects:

  [Scope?]
  -a, --auto      ⬢ Build all modules defined in .bgo.yaml recursively (auto mode) [env: AUTO] (default=true)
  -f, --full      ⬡ Build all CLIs under work directory recursively [env: FULL](default=false)
  -s, --short     ⬡ Build for current CPU and OS Arch ONLY [env: SHORT] (default=false)

平时 bgo 在主动模式(--auto),此时仅配置文件中的 projects 被思考纳入构建序列中。如果没有找到配置文件的话,bgo 会尝试扫描以后文件夹找出第一个 main app。

残缺扫描模式(--full)会扫描以后文件夹中的全副可能的 projects。

而简短模式(--short)只会从配置文件中提取第一个我的项目,不过,如果你的根目录中没有配置文件的话,它会扫描到首个 project 来构建。它的特别之处在于只有工作机的以后 GOOS+GOARCH 才会被构建。

除此之外,你能够显式指定一个名字来运行 bgo。bgo 会在配置表中检索同名的 project 并独自对其运行构建序列。

bgo -pn whoami   # Or `--project-name`

在配置文件中,你能够设置 disabled: true 来禁止一个我的项目,或者禁止一个项目组。

对 projects 分组

多个 projects 能够划分为一个分组,益处是构建参数能够对立指定。例如:

---
app:
  bgo:
    build:
      cgo: false

      projects:
        000-default-group:
          # leading-text:
          cgo: false
          items:
            001-bgo:   # <- project name
              name:    # <- app name
              dir: .
              gen: false
              install: true
              cgo: false
            010-jsonx: # <- project name
              name:    # <- app name
              dir: ../../tools/jsonx

例子中定义了一个 default-group 组,而后定义了 bgojsonx 两个 projects。

它们的名字前缀(如 001- 片段)被用于排序目标,在构建行为中会被疏忽,不会被当作是名称的一部分。

项目组的构建配置设定(例如 cgo 参数)会被下拉利用到每个我的项目,除非你显式指定它;相似地,在 app.bgo.build 这一级也能够定义 cgo, for, os, arch 等等参数,它们具备更高一级的优先性。

示例片段中,cgo 这个参数在各级都有定义,我的项目级的 cgo 优先级最高。

Project 的配置参数

除了 name, dir, package 字段之外,其它的参数都是公共的。也就是说,其它参数都能够被用于顶级或者项目组一级。

name, dir, package

每个 project 须要 dir 作为根本的定义,这是必须的:

---
app:
  bgo:
    build:

      projects:
        000-default-group:
          # leading-text:
          items:
            001-bgo:   # <- project name
              name:    # <- app name
              dir: .
              package: # optional

能够采纳 ../ 的相对路径的语法,跳出当前目录的限度。实践上说,你能够纳入所有我的项目。

bgo 会检测该目录中的 go.mod 以决定应否启动 go modules 编译。

每当具体执行 go build 时,总是会切换到 dir 所指向的地位,以此为基准,除非你指定了 keep-workdir,这个参数通知 bgo 放弃当前工作目录。你也能够应用 use-workdir 来为某个 project 特地指明一个 go build 时的基准工作目录。

name 能够被用于显式地指定我的项目的 app name,如果不指定,那么会从 project name 取值。project name 是开发者的工程治理用名,而 app name 是用给 end user 看的(以及,将被作为输入的 executable 的根本名字)。

package 是可选的,通常你不用手工指定它。通过 bgo init 扫描得来的后果里这个字段会被主动填写,但理论构建时它总是会被从新提取。

disabled

这个字段使得相应我的项目被跳过

disable-result

bgo 在实现了构建之后,主动 ll 后果的 executable。这个字段能够禁止 bgo 的这一行为。

keep-workdir, use-workdir

个别状况下,bgo 跳转到我的项目所在目录之后开始 go build .,而后再返回当前目录。

keep-workdir 容许你停留在当前目录(也即启动 bgo 时所在的目录),应用 go build ./tools/bgo 这样的句法进行构建。此时你能够设置 keep-workdir 为 true。

如果你想某个我的项目应用特定的一个基准目录(多半是因为那个基准目录才有 go.mod)的话,能够应用 use-workdir 字段指定一个。

    use-workdir: ./api/v1
    keep-workdir: false

gen, install, debug, gocmd, cgo, race, msan,

gen 决定了是否在 go build 前运行 go generate ./…

install 决定了是否将执行文件复制到 $GOPATH/bin 中,如同 go install 做的那样。

debug 会产出更大的可执行文件,而默认时会应用 -trimpath -s -w 这些典型配置来削减执行文件的尺寸。

gocmd 在你要应用不同的 go 版本执行构建时很有用,把它设置为指向你的特定版本的 go 执行文件即可。当大多数状况下你可能都会放弃它为空。但如果你在哦某个文件夹中编制了一段须要泛型的试验代码时 gocmd 可能很有用。

cgo 决定了环境变量 CGO_ENABLED 的取值以及构建时是否使能 gcc 环节。留神 CGO 个性仅可用于以后 GOOS/GOARCH,对于穿插编译它不能被很好地反对。

race 示意是否关上竞态条件检测。

msan 被原样传递给 go build,以便产出内存诊断和审计代码。

指标平台:for, os, arch

在配置文件中,能够指定要对哪些指标平台进行构建。

---
app:
  bgo:
    build:
      # the predefined limitations
      # for guiding which os and arch will be building in auto scope.
      #
      # If 'bgo.build.for' is empty slice, the whole available 'go tool dist list'
      # will be used.
      #
      #for:
      #  - "linux/amd64"
      #  - "windows/amd64"
      #  - "darwin/amd64"
      #  - "darwin/arm64"

      # the predefined limitations
      os: [linux]

      # the predefined limitations
      #
      arch: [amd64,"386",arm64]

留神这些键值也能够被用于 project-group 或者 project,例如这样:

      projects:
        000-default-group:
          # leading-text:
          items:
            001-bgo:   # <- project name
              name:    # <- app name
              dir: .
              gen: true
              install: true
              # os: ["linux","darwin","windows"]
              # arch: ["amd64"]
              # for: ["linux/riscv64"]

for 会指定一个指标平台数组,每一个条目都是 os/arch 对。

但如果你指明了 os 和 arch 数组的话,它们俩会做笛卡尔积来产生最终的指标平台 martrix。

post-action,pre-action

能够指定 shell 脚本在 go build 之前或者之后执行。

一个 post-action 可能是像这样的:

post-action: |
  if [["$OSTYPE" == *{ {.OS}}* && "{{.Info.GOARCH}}" == {{.ARCH}} ]]; then
    cp {{.Output.Path}} $HOME/go/bin/
  fi
  echo "OS: $OSTYPE, Arch: {{.Info.GOARCH}}"

它应用了模板开展性能。相应的数据源来自于 咱们的 build.Context 变量,这个变量的定义在文末会有一个形容。

具体而言,{{.Info.GOARCH}} 代表着正在运行的 go runtime 值,即 runtime.GOARCH,而 {{.OS}}{{.ARCH}} 是正在构建的指标的相应值。

因为 jekyll 模板开展的起因,所以所有的 {{ 都被插入了空格以避免文章公布失败。

post-action-file,pre-action-file

如果你想要,能够应用脚本文件。

留神

这些设定仅用于每个 project,不反对被利用到 project-group 这一级。起因在于咱们的代码实现中在最初阶段删除了 group 这个层级。

ldflags, asmflags, gcflags, tags

这些选填的参数将被传递给 go build 的相应命令行参数。

然而在咱们这里,你应该将它们指定为数组模式,例如:

---
app:
  bgo:
    build:
      ldflags: ["-s", "-w"]

指定了全局的 ldflags 参数,将被用到所有的 projects 构建时,除非你在某个 project 明确地指定了专属的 ldflags 版本。

extends

向正在构建的代码的特定包写入变量值,是通过 go build -ldflags -X ... 来达成的。同样的也有配置文件条目来简化这个问题:

            001-bgo: # <- project name
              name:    # <- app name
              dir: tools/bgo
              gen: false
              install: true
              cgo: true
              extends:
                - pkg: "github.com/hedzr/cmdr/conf"
                  values:
                    AppName: "{{.AppName}}"
                    Version: "{{.Version}}"
                    Buildstamp: "{{.BuildTime}}" # or shell it
                    Githash: "`git describe --tags --abbrev=16`"
                    # Githash: "{{.GitRevision}}"  # or shell it: "`git describe --tags --abbrev=9`"
                    GoVersion: "{{.GoVersion}}"  # or shell it
                    ServerID: "{{.randomString}}"

能够采纳模板开展,也能够嵌入小的 shell 脚本。

但不激励写很多的脚本在这里。

示例中给出的是针对 hedzr/cmdr CLI app 的构建参数,但实际上它们是多余的:作为一家人,咱们会主动尝试辨认你的 go.mod 是不是蕴含了到 cmdr 的援用,从而决定了咱们要不要主动填写这组参数。

很显然,在构建时写入包变量并不是 cmdr 专属的货色,所以你能够用它来做你的专属配置。

顶级的特有配置参数

在配置文件中,app.bgo.build 是配置项的顶层,在这一层能够指定排除目录和输入文件名模板:

---
app:
  bgo:
    build:
      output:
        dir: ./bin
        # split-to sample: "{{.GroupKey}}/{{.ProjectName}}"
        #
        # named-as sample: "{{.AppName}}-{{.Version}}-{{.OS}}-{{.ARCH}}"

      # wild matches with '*' and '?'
      # excludes patterns will be performed to project directories.
      # but projects specified in .bgo.yml are always enabled.
      excludes:
        - "study*"
        - "test*"

output 块中能够指定 named-as 作为输入可执行文件名的模板,默认时 bgo 会采纳 {{.AppName}}-{{.OS}}-{{.ARCH}}

dir 指明输入文件夹,可执行文件被指向这里。

当你还能够指明 split-to 为每个 project 设定额定的子文件档次,例如能够是 {{ .ProjecName}},等等。

excludes 是一个字符串数组,提供一组文件名通配符模板,和这些模板匹配的文件夹将不会被扫描。

Build Context

在一些字段中咱们容许你嵌入动静变量值,它们会依据每个我的项目的构建时而因应变动。例如 {{.AppName}} 能够被开展为以后正在被构建的我的项目的 app name。

这些值被蕴含在 build.Context 的申明中。

上面给出 bgo 源代码的相应代码片段,因而我就不用再做解释了。

这里并非最新版本,目前仍在迭代中

type (
    Context struct {
        WorkDir    string
        TempDir    string
        PackageDir string

        // Output collects the target binary executable path pieces in building
        Output PathPieces

        *Common
        *Info
        *DynBuildInfo
    }
)

type PathPieces struct {
    Path    string
    Dir     string
    Base    string
    Ext     string
    AbsPath string
}

type (
    Info struct {
        GoVersion   string // the result from 'go version'
        GitVersion  string // the result from 'git describe --tags --abbrev=0'
        GitRevision string // revision, git hash code, from 'git rev-parse --short HEAD'
        BuildTime   string //
        GOOS        string // a copy from runtime.GOOS
        GOARCH      string // a copy from runtime.GOARCH
        GOVERSION   string // a copy from runtime.Version()

        RandomString string
        RandomInt    int
        Serial       int
    }
  
    DynBuildInfo struct {
        ProjectName         string
        AppName             string
        Version             string
        BgoGroupKey         string // project-group key in .bgo.yml
        BgoGroupLeadingText string // same above,
        HasGoMod            bool   //
        GoModFile           string //
        GOROOT              string // force using a special GOROOT
        Dir                 string
    }
)

type (
    CommonBase struct {
        OS   string `yaml:"-"` // just for string template expansion
        ARCH string `yaml:"-"` // just for string template expansion

        Ldflags    []string `yaml:"ldflags,omitempty,flow"`    // default ldflags is to get the smaller build for releasing
        Asmflags   []string `yaml:"asmflags,omitempty,flow"`   //
        Gcflags    []string `yaml:"gcflags,omitempty,flow"`    //
        Gccgoflags []string `yaml:"gccgoflags,omitempty,flow"` //
        Tags       []string `yaml:"tags,omitempty,flow"`       //
        // Cgo option
        Cgo bool `yaml:",omitempty"` //
        // Race option enables data race detection.
        //        Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64,
        //        linux/ppc64le and linux/arm64 (only for 48-bit VMA).
        Race bool `yaml:",omitempty"` //
        // Msan option enables interoperation with memory sanitizer.
        //        Supported only on linux/amd64, linux/arm64
        //        and only with Clang/LLVM as the host C compiler.
        //        On linux/arm64, pie build mode will be used.
        Msan          bool   `yaml:",omitempty"`               //
        Gocmd         string `yaml:",omitempty"`               // -gocmd go
        Gen           bool   `yaml:",omitempty"`               // go generate at first?
        Install       bool   `yaml:",omitempty"`               // install binary to $GOPATH/bin like 'go install' ?
        Debug         bool   `yaml:",omitempty"`               // true to produce a larger build with debug info
        DisableResult bool   `yaml:"disable-result,omitempty"` // no ll (Shell list) building result

        // -X for -ldflags,
        // -X importpath.name=value
        //    Set the value of the string variable in importpath named name to value.
        //    Note that before Go 1.5 this option took two separate arguments.
        //    Now it takes one argument split on the first = sign.
        Extends      []PackageNameValues `yaml:"extends,omitempty"` //
        CmdrSpecials bool                `yaml:"cmdr,omitempty"`
    }

    PackageNameValues struct {
        Package string            `yaml:"pkg,omitempty"`
        Values  map[string]string `yaml:"values,omitempty"`
    }

    Common struct {
        CommonBase     `yaml:"base,omitempty,inline,flow"`
        Disabled       bool     `yaml:"disabled,omitempty"`
        KeepWorkdir    bool     `yaml:"keep-workdir,omitempty"`
        For            []string `yaml:"for,omitempty,flow"`
        Os             []string `yaml:"os,omitempty,flow"`
        Arch           []string `yaml:"arch,omitempty,flow"`
        Goroot         string   `yaml:"goroot,omitempty,flow"`
        PreAction      string   `yaml:"pre-action,omitempty"`       // bash script
        PostAction     string   `yaml:"post-action,omitempty"`      // bash script
        PreActionFile  string   `yaml:"pre-action-file,omitempty"`  // bash script
        PostActionFile string   `yaml:"post-action-file,omitempty"` // bash script
    }
)

最新版本请间接返回 或者 go.dev 处查阅。

命令行的应用

bgo 是一个基于 hedzr/cmdr 的命令行程序,带有 cmdr 所反对的根本个性,例如自在的多级子命令参数输出与辨认,等等。

总的来说,你应该以两个步骤来应用 bgo:

  1. 利用 bgo init 生成一个 bgo.yml 模板,它组织了扫描到的 cli apps 到这个配置模板中,请将其改名为 .bgo.yml 便于 bgo 主动装载。

    bgo 会从若干主动地位查找 .bgo.yml 文件的存在。实际上它也会查看 bgo.yml,并且还会主动拓展到相应的 conf.d 文件夹中做主动装载与合并,所以你能够在 conf.d 中拆散地为每个 project 编写一个 yaml 片段,这对于继续集成是很有益处的。

  2. .bgo.yml 就绪之后(你能够手工编辑它以削减定制属性),间接应用 bgo 就能一次性构建。

在上述主动模式之外,也有一些来到主动模式长期特定操作的形式。

  1. 如果 bgo 没有发现配置文件,咱们会试着扫描以后文件夹来尝试构建。
  2. 如果不想产生预期之外的构建行为,请带上 --dry-run 参数。

一些可能有用的命令行在上面列举进去,它们都是不用强求配置文件在场的——然而如前所述,配置文件可能以一种易于调整的格局让你充斥了控制力,而命令行无论如何优化,也不能覆盖像 -ldflags 这样的控制参数的内容如此简单与难以编辑。

为了缩短命令行输出,运行 bgo 时隐含着等价于执行 bgo build 子命令。也就是说,bgo -s 本质上切实执行 bgo build -s,将启动一个简短构建模式。

所以为了查看可能的命令行参数,你应该应用 bgo build --help

针对以后 GOOS/GOARCH 构建

bgo -s
bgo -s -pn project-one

其中后一种模式的目标是只针对以后 GOOS/GOARCH 编译 project-one 这个我的项目,疏忽配置文件中的其它 projects。

如果没有配置文件,它会主动查找首个 main cli 而后进行构建。

残缺扫描模式

bgo -f

这时除了配置文件中定义的 projects 之外,bgo 会再次扫描文件夹下的所有 cli apps。

指定构建指标平台

例如仅编译指定指标平台 linux/386 执行文件,疏忽配置文件中可能存在的其它指标平台定义:

bgo build --for linux/386
bgo -os linux -arch 386

两条命令的用处雷同。

同时,能够通过屡次指定来指明一个数组:

bgo -os linux --arch 386 --arch amd64,arm64

并且能够随便应用逗号分隔符(,)来通知 bgo 辨认数组列表,例如上例中实际上给出了一个蕴含三个 arch 的数组作为参数:["386", "amd64", "arm64"]

此外,foros 以及 arch 同时实用于长短参数模式,--for 或者 -for 都没问题,目标是为了升高记忆负担。

相似的,这样也是无效的:

bgo --for linux/386 --for darwin/am64
bgo --for linux/386,darwin/amd64

指定构建我的项目名

bgo -pn bgo

bgo 用作构建简称,是 bgo build 的缩短形式。

你能够同时限定我的项目名以及指标平台:

bgo -os linux,windows -arch 386,amd64 -pn project-one

启用 Shell 主动实现

以后 bgo 可能提供 Shell 主动实现性能,输出 bgo 之后键击 TAB 即可。

以及

如果你是通过下载二进制执行文件的形式运行 bgo 的,须要一点步骤来启用 Shell 主动实现性能。

zsh

对于 zsh 环境,这样生成主动实现脚本:

$ bgo gen sh --zsh

# "/usr/local/share/zsh/site-functions/_bgo" generated.
# Re-login to enable the new zsh completion script.

如果 bgo 没有能找到搁置 _bgo 实现脚本的地位,它会将脚本输入到控制台,你须要自行保留为 _bgo 而后放入你的 zsh 主动实现脚本搜寻地位中。

zsh 应用环境变量 fpath 来批示主动实现脚本应该放在什么中央。例如:

❯ print -l $fpath
/Users/hz/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting
/Users/hz/.oh-my-zsh/custom/plugins/zsh-autosuggestions
/Users/hz/.oh-my-zsh/plugins/z
/Users/hz/.oh-my-zsh/plugins/docker
/Users/hz/.oh-my-zsh/plugins/git
/Users/hz/.oh-my-zsh/functions
/Users/hz/.oh-my-zsh/completions
/Users/hz/.oh-my-zsh/cache/completions
/usr/local/share/zsh/site-functions
/usr/share/zsh/site-functions
/usr/share/zsh/5.7.1/functions

bgo 将会主动解释这些门路地位并寻找最佳搁置门路。然而如果因为写入权限或其它问题导致 bgo 无奈胜利写入的话,那么你须要手工操作。

你也能够生成该脚本到指定地位:

bgo gen sh --zsh -o /some/where/for/_bgo
bash

bash 主动实现脚本

后记

bgo 看起来仿佛有点用,然而它对你可能也并没有用途。

bgo 如像是个 modules 管理器和构建辅助工具,但实际上它并不是 modules 管理器,顶多只能算是 main packages 主动构建器吧。

所以重要的事说三遍:bgo 管 exe 不论 lib。

最初

最初不得不说,bgo 做的是很粗犷的,因为最后的念头只是想有一个 Disabled 标记能够毙掉某些 projects,而后就想有个 –project-name 做筛选,而后是 -os, -arch,而后又察觉有必要有 –for。

而后其实简直曾经失控了。

但总之它当初能够跑了。

题图

题外话

还有谁记得新蛋网吗?

忽然看到些 news 是对于 newegg 的,原来它的美国母公司活得好好的,远不至于说是开张没落,去年还上市了。

在这个年纪交替的时候,回首二十年来互联网上的变迁,心生感叹却难以挥发。

REFs

  • GOOS/GOARCH combos on macOS – Marcelo Cantos
  • 我的项目:https://github.com/hedzr/bgo
  • 配置文件示例:https://github.com/hedzr/bgo/blob/master/.bgo.yaml
  • Docker Hub:hedzr/bgo – Docker Image | Docker Hub

🔚

退出移动版