bgo: make it easier to build go programs

Posted by SGTWhitelaw on Mon, 31 Jan 2022 10:42:18 +0100

bgo

In a word: bgo manages exe regardless of lib

preface

Before the preface:

The preface is very long and can be skipped directly.

bgo It is a build assistant tool. It is not much different from the known tools for building go applications. It can support cross compiling and building go application executable files in your working environment. <-- MORE-->

Although this capability was originally provided by go build, the auxiliary construction tool after such packaging can save you a lot of energy, whether it is the go build command-line parameters that are difficult to remember, or the pre-processing and post-processing steps we have to use, such as go generate, copy to a public place, and so on.

So this is the purpose of bgo, which is labor-saving.

origin

Of course, why should I develop another auxiliary tool?

The reasons are not complicated. There are several:

Now I often make a lot of small projects in a large directory. Maybe I just try a function and do something. Maybe it's because I need to list a lot of examples for users to see. In short, there are a lot of them. But in a small cycle, I usually focus on one or two or three of them. Therefore, switching directories and building are very tired. Goland is very considerate, which can save me the work in the command-line environment, but its operation result window can not support full-featured keyboard interaction, so I can only open a terminal for some behaviors. Of course, there are many other things Golan can't do, so I won't list them. In short, this is a specific problem. Why not use vscode? Have you ever used it? You should know that vscode running goapp only has the ability to debug and run a main program. If you want to run multiple apps without debugging, you need to go to its embedded terminal and click the command line. Besides, if you're not in go If you open the workspace in mod, vscode will have many problems -- in other words, vscode supports a single go at most Module represented by mod.

Another reason is that as a more formal release, I may frequently need to use - X or go generate. In this regard, I originally had a complex Makefile that can automatically solve these problems. However, they are not very easy for me to use in large-scale projects, because I may have many different directories corresponding to different sub modules.

Another reason is the order of construction. Sometimes I need to do a series of construction orderly, and sometimes I need to quickly build a single target to run and view the results in exeutable mode.

Of course, there are other reasons, but I won't say anything about it.

You can notice that the main reason is that I am maintaining the structure of large projects. Why not cut into many, many repos? This brings up another problem: go modules does not support multiple nested go mod. That is, if your parent directory has go Mod, then subordinates can't have any more. This is a very complicated situation, but in the end, this restriction is very hard for you, so this structure won't work:

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

Only part of the directory structure is listed here, and it is only a schematic.

Similarly, some people will say that every go Just one repo for mod. Well, it's true. It's OK and can only be done.

After that, we need to find a way to solve the dependency.

go 1.18 Work doesn't help, even hard to use.

git submodules? It's very troublesome and difficult to use. You will forget the state and then use the cup.

Then someone will say, let's go to the top Mod, don't use anything else. Just separate the directory structure. Yes, I did this when I did similar large-scale projects a few years ago, but the protobuf reference of api and etcd reference of common are mixed together, and they are all very troublesome to solve. In the end, the whole huge project is bloated and needlessly chaotic.

In fact, there was a time when there were multiple go Mod nesting can operate carelessly, but that stage is very short. I forget whether it was 1.13 or which period. In short, this is a distant memory. At that time, I was satisfied with the configuration of the project, but later I adapted to the single go Mod is also more painful.

therefore

There are a lot of reasons, but bgo only solves part of the problem, that is, the construction problem when many small apps are distributed in a pile of complex subdirectories.

With bgo, we can use a large top-level directory to manage several sub projects. Of course, due to the limitation of go modules, we can't establish go in the top-level directory Mod (to avoid problems with go.mod in the subdirectory). It only plays the role of aggregation, and it will be OK when we open this structure with Goland or vscode.

Current configuration:

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

You can notice that there is one in the top-level directory bgo.yml file, which is the configuration file of BGO. It can be automatically generated after scanning subdirectories through bgo init, and then you can further adjust it on this basis.

The only problem is that it only collects the directories where the main package is located, that is, those directories that can produce executable. As for your package with go The mod directory is not really managed.

This is the limitation of bgo, but this is also the design goal of bgo: we scan and manage a series of CLI apps and complete the corresponding construction in a lighter way. We do not offer to go For the management of multiple modules marked by mod, we either design another tool or don't do it, so that google won't have a set of go one day Zone out.

Of course, you can go for each Mod is equipped with a main Go to let bgo take care of it. But in general, bgo doesn't care about lib

Disappointing go evolution

Say go mod go. Work is available, but it is not an effective solution for large-scale projects, but only limited to one of my module s.

In the engineering management of Go, there are always many problems:

  • Solution of private repos
  • Solution of problem repo or missing repo
  • Complex multi module construction and organization
  • Poor generics, it's better not to have them
  • wait

Seriously, I had high expectations. But the mood of yaml and I are similar. Wow, generics are coming. Oh, generics go well. In this field (automatic type resolution, unknown type resolution), golang's generics are good for nothing. According to the current evolution trend, it is impossible to expect it to solve the unknown types of free prediction.

How to start?

install

The first step, of course, is to install bgo.

Releases

bgo is designed to work with a single executable, so please Releases Download the precompiled version and put it in your search path.

go get

Alternatively, you can use the go get system:

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

Homebrew

homebrew is OK:

brew install hedzr/brew/bgo

Package management of other platforms is not supported temporarily because it is just a small tool.

Docker

You can also use docker mode to run, but it is a little complicated, because you need to carry the local volume:

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

This is consistent with the implementation of native bgo.

docker containers can be obtained from these places:

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

function

In the directory you want to build, run bgo.

For example, we are ini-op Run it in your source code:

This is the easiest start.

characteristic

But if so, what is the value? Command line shortener?

bgo can do two things in particular:

  • tags, etc. go build command line is too long and difficult to edit
  • You want to orchestrate build instructions and their pre - and post-processing behavior. For example, add a post processor, and so on.
  • There are a lot of subdirectories with CLIs, but we don't want to build them one by one, or the construction parameters are different, so we can't deal with them at one time.
  • There are a series of go modules, but you want to arrange them uniformly.

These goals can be solved through configuration files.

Create build profile

BGO takes the current directory as the benchmark, and it will look for the current directory bgo.yml file, load the projects configuration information in it, and then build it in a specific order.

Because we emphasize ordering, bgo does not support parallel compilation of multiple projects.

In fact, this feature is worthless because it only reduces the overall compilation speed.

So the first question is bgo.yml how to prepare?

To do this, select your root directory to run bgo for the first time.

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

This command will scan all subdirectories, then compile a build configuration table and save it as BGO YML file.

Then you can choose to rename the configuration file (this is recommended to prevent possible side effects after running -- save incorrectly). But you can also leave the file name unchanged if you want.

synonym

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

If you need a annotated example, please refer to:

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

Start building

Once the configuration file is ready, you can run:

bgo

This will build all the projects in the configuration file.

In fact, if there is no configuration file, bgo will automatically scan out the first main cli and build it.

Use different build ranges

bgo supports three ranges. The difference between them is how to deal with the projects in the configuration file and whether to scan the projects in the current folder:

  [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)

Normally, bgo is in automatic mode (- - auto). At this time, only the projects in the configuration file are considered to be included in the construction sequence. If the configuration file is not found, bgo will try to scan the current folder to find the first main app.

Full scan mode (- - full) scans all possible projects in the current folder.

Short mode (- - short) will only extract the first project from the configuration file, but if there is no configuration file in your root directory, it will scan to the first project to build. Its special feature is that only the current GOOS+GOARCH of the working machine will be built.

In addition, you can explicitly specify a name to run bgo. bgo will retrieve the project with the same name in the configuration table and run the build sequence on it separately.

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

In the configuration file, you can set disabled: true to disable a project or a project group.

Group projects

Multiple projects can be divided into one group. The advantage is that the construction parameters can be specified uniformly. For example:

---
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

In the example, a default group group is defined, and then bgo and jsonx projects are defined.

Their name prefixes (e.g. 001 fragments) are used for sorting purposes and are ignored in the construction behavior and are not considered part of the name.

The build configuration settings of the project group (such as cgo parameters) will be applied to each project by drop-down unless you explicitly specify it; Similarly, in app bgo. The build level can also define cgo, for, os, arch and other parameters, which have a higher priority.

In the sample fragment, the parameter cgo is defined at all levels, and the project level cgo has the highest priority.

Configuration parameters of Project

Except for the name, dir and package fields, other parameters are public. That is, other parameters can be used at the top level or project group level.

name, dir, package

Each project needs dir as the basic definition, which is necessary:

---
app:
  bgo:
    build:

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

Can be used/ The syntax of the relative path to jump out of the limit of the current directory. In theory, you can include everything.

bgo will detect the go. In this directory Mod to determine whether go modules compilation should be started.

Whenever go build is executed, it will always switch to the location pointed by dir. This is the benchmark. Unless you specify keep workdir, this parameter tells bgo to keep the current working directory. You can also use use workdir to specify a benchmark working directory of go build for a project.

Name can be used to explicitly specify the app name of the project. If it is not specified, it will be taken from the project name. The name of the project and the name of the user to be managed are used as the name of the project, and the name of the project is used as the name of the executable.

package is optional. Usually you don't have to specify it manually. This field in the result scanned by bgo init will be filled in automatically, but it will always be re extracted during actual construction.

disabled

This field causes the corresponding item to be skipped

disable-result

bgo automatically ll the executable of the result after the build is completed. This field can prohibit this behavior of bgo.

keep-workdir, use-workdir

Generally, bgo starts go build after jumping to the directory where the project is located, Then return to the current directory.

But keep workdir allows you to stay in the current directory (that is, the directory where bgo was started) and use go build/ Tools / bgo. At this point, you can set keep workdir to true.

If you want a project to use a specific benchmark directory (mostly because that benchmark directory has go.mod), you can use the use workdir field to specify one.

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

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

gen determines whether to run go generate before go build

Install determines whether to copy the execution file to $GOPATH/bin, as go install does.

debug will produce a larger executable, and by default - trimpath -s -w, these typical configurations are used to reduce the size of the executable.

Gocmd is very useful when you want to use different versions of go to perform construction. Just set it to point to your specific version of go execution file. In most cases, you may keep it empty. But gocmd can be useful if you've written a piece of experimental code that needs generics in a folder.

CGO determines the environment variable CGO_ The value of enabled and whether the gcc link is enabled during construction. Note that the CGO feature can only be used for the current GOOS/GOARCH, and it cannot be well supported for cross compilation.

Race indicates whether to open race condition detection.

msan is passed to go build as is to produce memory diagnosis and audit code.

Target platform: for, os, arch

In the configuration file, you can specify which target platforms to build.

---
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 ]

Note that these key values can also be used for project group or project, for example:

      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 specifies an array of target platforms, and each entry is an os/arch pair.

But if you specify the os and arch arrays, they will do Cartesian product to produce the final target platform martrix.

post-action,pre-action

You can specify that the shell script is executed before or after go build.

A post action might look like this:

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

It uses the template expansion function. The corresponding data source comes from our build Context variable. The definition of this variable will be described at the end of the text.

Specifically, {. Info.GOARCH}} represents the running go runtime value, i.e. runtime Goarch, and {{. OS}} and {. ARCH}} are the corresponding values of the target being built.

Due to the expansion of the jekyll template, all {{are inserted with spaces to prevent the article from publishing failure.

post-action-file,pre-action-file

You can use script files if you want.

be careful

These settings are only used for each project and cannot be applied to the project group level. The reason is that the group level is deleted in the final stage of our code implementation.

ldflags, asmflags, gcflags, tags

These optional parameters will be passed to the corresponding command line parameters of go build.

But here, you should specify them as an array, for example:

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

Specifies the global ldflags parameter, which will be used in the construction of all projects, unless you explicitly specify the exclusive ldflags version in a project.

extends

Write variable values to the specific package of the code being built through go build -ldflags -X To achieve it. Similarly, there are configuration file entries to simplify this problem:

            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}}"

Templates can be used to expand or small shell scripts can be embedded.

But it is not encouraged to write a lot of scripts here.

The example is given for hedzr/cmdr CLI app build parameters, but they are actually redundant: as a family, we will automatically try to identify your go Whether mod contains a reference to cmdr determines whether we should automatically fill in this set of parameters.

Obviously, writing package variables at build time is not something exclusive to cmdr, so you can use it for your exclusive configuration.

Top level unique configuration parameters

In the configuration file, app bgo. Build is the top level of the configuration item. In this layer, you can specify the exclusion directory and output file name template:

---
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*"

In the output block, named as can be specified as the template for outputting the executable file name. By default, bgo will adopt {{. AppName}} - {. OS} - {. Arch}}.

dir indicates the output folder where the executable file is pointed.

You can also specify split to set additional sub file levels for each project, such as {{. ProjecName}}, and so on.

excludes is a string array that provides a set of file name wildcard templates. Folders matching these templates will not be scanned.

Build Context

In some fields, we allow you to embed dynamic variable values, which will change according to the construction time of each project. For example, {. AppName}} can be expanded to the app name of the project currently being built.

These values are included in build In the declaration of context.

The corresponding code snippets of bgo source code are given below, so I don't need to explain any more.

This is not the latest version and is still in iteration

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
    }
)

For the latest version, please go directly to or go Dev.

Use of command line

bgo is based on hedzr/cmdr Command line program with basic features supported by cmdr, such as free multi-level subcommand parameter input and identification, and so on.

In general, you should use bgo in two steps:

  1. Use bgo init to generate a BGO YML template, which organizes the scanned cli apps into this configuration template. Please change its name to bgo.yml facilitates BGO automatic loading.

    BGO will search from several automatic locations bgo. The existence of the YML file. In fact, it will also check BGO YML, and it will automatically expand to the corresponding conf.d folder for automatic loading and merging, so you can separately write a yaml fragment for each project in conf.d, which is very good for continuous integration.

  2. .bgo. Once the YML is ready (you can edit it manually to add custom attributes), it can be built at one time directly using BGO.

In addition to the above automatic mode, there are also some ways to leave the automatic mode for temporary specific operation.

  1. If bgo does not find the configuration file, we will try to scan the current folder to try to build it.
  2. If you don't want unexpected build behavior, bring the -- dry run parameter.

Some command lines that may be useful are listed below. They don't have to force the presence of the configuration file - but as mentioned earlier, the configuration file can fill you with control in an easy to adjust format, and no matter how optimized the command line is, it can't hide that the content of control parameters such as - ldflags is so complex and difficult to edit.

In order to shorten the command line input, running bgo implies that it is equivalent to executing the bgo build subcommand. That is, bgo -s actually executes bgo build -s, which will start a short build mode.

So to see the possible command line parameters, you should use bgo build --help.

Build for current GOOS/GOARCH

bgo -s
bgo -s -pn project-one

The purpose of the latter form is to compile the project one only for the current GOOS/GOARCH and ignore other projects in the configuration file.

If there is no configuration file, it will automatically find the first main cli and build it.

Full scan mode

bgo -f

At this time, bgo will scan all cli apps under the folder again except the projects defined in the configuration file.

Specify build target platform

For example, only compile the linux/386 executable file of the specified target platform, ignoring other target platform definitions that may exist in the configuration file:

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

Both commands serve the same purpose.

At the same time, you can specify an array by specifying multiple times:

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

And you can use the comma separator (,) to tell bgo to recognize the array list. For example, the above example actually gives an array containing three arch as parameters: ["386", "amd64", "arm64"].

In addition, for, os and arch are applicable to both long and short parameter forms, - for or - for is OK, in order to reduce the burden of memory.

Similarly, this is also effective:

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

Specify the build project name

bgo -pn bgo

bgo is used as the abbreviation of build, which is the shortening method of bgo build.

You can limit both the project name and the target platform:

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

Enable Shell autocomplete

At present, bgo can provide Shell automatic completion function. Enter bgo and click TAB.

as well as

and

If you run bgo by downloading binary executables, you need a few steps to enable Shell autocomplete.

zsh

For zsh environment, the auto completion script is generated as follows:

$ bgo gen sh --zsh

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

If bgo can't find the place_ bgo completes the script location. It will output the script to the console. You need to save it as_ bgo is then placed in your zsh autocomplete script search location.

zsh uses the environment variable fpath to indicate where the autocomplete script should be placed. For example:

❯ 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 will automatically interpret these path locations and find the best placement path. However, if bgo cannot write successfully due to write permission or other problems, you need to do it manually.

You can also generate the script to the specified location:

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

bash autocomplete script

Postscript

bgo may seem useful, but it may not be useful to you.

bgo is like a modules manager and a construction assistant, but it is not a modules manager. At most, it can only be regarded as an automatic builder of main packages.

So the important thing to say three times: bgo tube exe regardless of lib.

last

Finally, I have to say that what bgo did was very rude, because the original idea was to have a Disabled flag to kill some projects, and then want to have a -- project name for screening, then - os, -arch, and then find it necessary to have -- for.

Then it was almost out of control.

But anyway, it can run now.

Title Map

Digression

Does anyone else remember Newegg?

Suddenly I saw some news about newegg. It turned out that its American parent company was living well, far from going bankrupt and declining. It was listed last year.

At this time of changing years, looking back on the changes on the Internet in the past 20 years, my heart is filled with emotion, but it is difficult to volatilize.

REFs

🔚

Topics: Go compiler build