头图

bgo

One sentence to understand: bgo pipe exe regardless of lib

foreword

Preface before :

The preface this time is very long and can be skipped directly.

bgo is a build aid that is not much different from the known tools for building services for go applications, and supports cross-compiling the executable to build the go application in your working environment. <!--MORE-->


Although this capability is originally built into go build, the auxiliary build tools that are packaged once can save you a lot of effort, whether it's those hard-to-remember go build command-line parameters, or those we have to use Pre-prep, post-processing steps such as go generate, copy to a public location, etc.

So that's what tools like bgo are for, save effort.

origin

Of course, why should I develop yet another helper tool?

The reasons are not complicated, there are several:

I often make a lot of small projects in a big directory, maybe just to test a certain function, do a certain thing, maybe because I need to list a lot of examples for users to see, in short, there are many. But in a small cycle, I usually focus on one or two or three of them. For this reason, switching directories and building are very tired. Goland is very considerate and allows me to save the work in these command line environments, but its running result window cannot support full-featured keyboard interaction, so I can only open a terminal to run for some behaviors. Of course, there are many other things that Goland must not be able to do, so I won't list them. In short, this is a specific problem. For this, why not vscode? Have you used it? You need to know that vscode only has the ability to debug and run a certain main program when running goapp. If you want to debug or not, or want to have multiple apps, you need to type the command line in its embedded terminal. Also, vscode has a lot of problems if you don't open the workspace in go.mod - in other words, vscode supports at most modules represented by a single go.mod.

Another reason is that as a more formal release, I may need to use -X or go generate frequently. For this, I originally had a complex Makefile that would solve these problems automatically. But they are not very useful for me in large scale projects, because I may have many different directories corresponding to different submodules.

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

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

You can notice that the main reason is again that I am maintaining a large project structure. Why not split into many, many repos? This brings up another problem: go modules do not support multiple nested go.mods. That is to say, if your upper level directory has go.mod, then the lower level cannot have it anymore. This is a very complicated situation, but in the end, this restriction is very hard for you, so this structure will not work:

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

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

Likewise, there are still people who say that every go.mod is just a repo. Well, it is like this, it is indeed possible to do this, and it can only be done in this way.

After that, you need to find a way to resolve the dependencies.

go 1.18's go.work doesn't help, or even makes it hard to use.

git submodules? Very troublesome, difficult to use, will forget the state, and then the cup.

Then some people will say, the top-level go.mod, don't use the others, just separate the directory structure. Yeah, that's what I did when I was working on a similar large scale project a few years ago, but the api's protobuf reference, the common's etcd reference, etc. were all mixed up, and they were all kind of cumbersome to solve, and in the end Makes the whole mega project bloated and needlessly cluttered.

In fact, there was a time when multiple go.mod nested existences could work sloppily, but that stage was very short, I forgot whether it was in 1.13 or which period, in short, this is a distant memory. I was satisfied with the configuration of the project during that time, but then it was more painful to re-conform to a single go.mod.

so

There are a lot of reasons, but bgo only solves part of the problem, that is, the build problem when many small apps are distributed in a bunch 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, go.mod cannot be created in the top-level directory (to avoid problems with go.mod in subdirectories) , it only plays the role of aggregation, and we use Goland or vscode to open this structure will be OK.

Current configuration:

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

You can notice that there is a .bgo.yml file in the top-level directory. This is the bgo configuration file. It can be bgo init after scanning subdirectories, and then you can further adjust it on this basis.

The only problem is that it only collects the directory where the main package is located, that is, those directories that can produce executables. As for your directory with go.mod, it is not really included in the management scope.

This is a limitation of bgo, but that's what bgo was designed for: we scan and manage a set of CLI apps and build accordingly in a lighter way. We don't provide the management of multiple modules marked by go.mod. Either we design a separate tool for this function, or we don't do it, lest google get a nerve and come up with a set of go.zone one day.

Of course, you can have a main.go for each go.mod and let bgo take care of it. But in general, bgo pipe exe regardless of lib

Disappointing go evolution

Saying go.mod go.work have it all, but not all effective programs to do large-scale projects to solve, but merely confined I in one module of.

In project management in Go, there are always many questions:

  • Solution for private repos
  • Problem repo or solution for missing repo
  • Complex multi-module construction and organization
  • Poor generics, might as well not have
  • etc

To be honest, I had high expectations. But my mood is probably similar to those of yaml, wow, generics are here, oh, generics go well. In this area (automatic type resolution, unknown type resolution), golang's generics are pretty much useless. According to the current evolution situation, it is impossible to expect it to solve the unknown type of free pre-judgment.

How to get started?

Install

The first thing to do is, of course, to install bgo.

Releases

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

go get

Alternatively, you can pass the go get system:

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

image-20220130101919648

Homebrew

homebrew is ok:

brew install hedzr/brew/bgo

Package management of other platforms is not supported yet, because this is just a small tool.

Docker

It can also be run using docker, but it is a little more complicated because it needs to mount the native volume:

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

This is the same as executing native bgo.

docker containers can be obtained from these places:

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

run

In the directory you want to build, run bgo.

For example we run it in the source code of ini-op

image-20220128104835837

This is the easiest way to start.

Features

But if that's the case, what's the value? Command line shortener?

What bgo can do, especially in and :

  • tags etc. go build command line is too long and hard to edit
  • Want to orchestrate build instructions and their pre- and post-processing behavior. For example adding post processors, etc.
  • There are a whole bunch of subdirectories that have CLIs, but don't want to build them one by one, or have different build parameters that can't be dealt with all at once.
  • There is a series of go modules, but want to organize them uniformly.

These goals can be solved through configuration files.

Create a build profile

Based on the current directory, bgo will look for the .bgo.yml file in the current directory, load the projects configuration information in it, and then build it in a specific order.

Since we emphasize orderliness, bgo does not support parallel compilation of multiple projects.

In fact, this feature is worthless because it just slows down the overall compilation speed.

So the first question is, .bgo.yml prepared?

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.

You can then optionally rename the configuration file (this is recommended to prevent possible side effects of --save But if you want, you can keep the filename as it is.

synonym

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

If you need an annotated example, see:

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.

Take a different build range

bgo supports three scopes, which differ in how projects in the configuration file are handled and whether or not projects in the current folder are scanned:

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

Usually bgo is in automatic mode ( --auto ), at this time only projects in the configuration file are considered for inclusion in the build sequence. If no configuration file is found, bgo will try to scan the current folder for the first main app.

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

The short mode ( --short ) will only extract the first project from the config file, however, if you don't have a config file in your root directory, it will scan to the first project to build. What makes it special is that only the current GOOS+GOARCH of the worker will be built.

In addition to that, 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 individually.

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

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

group projects

Multiple projects can be divided into a group, the advantage is that the build 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

The example defines a default-group group, and then defines two projects bgo and jsonx

Their name prefixes (like the 001- fragment) are used for sorting purposes, are ignored in build behavior, and are not considered part of the name.

A project group's build configuration settings (such as cgo parameters) will be dropped and applied to each project unless you specify it explicitly; similarly, cgo, for, os, arch, etc. parameters can also be defined app.bgo.build They have a higher priority.

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

Project configuration parameters

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

name, dir, package

Every project needs dir as a basic definition, which is required:

---
app:
  bgo:
    build:

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

You can use ../ to escape the limitation of the current directory. In theory, you can include everything.

bgo will detect go.mod in this directory to decide whether it should start go modules compilation.

Whenever go build is specifically executed, it will always switch to the location pointed to by dir, based on this, unless you specify keep-workdir , which tells bgo to keep the current working directory. You can also use use-workdir to specify a go build base working directory for a project.

name can be used to explicitly specify the app name of the project. If not specified, the value will be taken from the project name. The project name is the developer's project management name, and the app name is what the end user sees (and, the base name of the executable that will be output as output).

package is optional, usually you don't have to specify it manually. This field is automatically filled in the results scanned by bgo init , but it is always re-extracted when actually building.

disabled

This field causes the corresponding item to be skipped

disable-result

After bgo has completed the build, it will automatically make the result executable. This field can disable this behavior of bgo.

keep-workdir, use-workdir

Under normal circumstances, bgo jumps to the directory where the project is located and starts go build . , and then returns to the current directory.

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

If you want a project to use a specific base directory (most likely because that base directory has go.mod), you can specify one use-workdir

    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 executable file into $GOPATH/bin , as go install does.

debug will produce a larger executable, and by default will use the typical configuration of -trimpath -s -w to reduce the size of the executable.

gocmd when you want to perform builds with different go versions, just set it to point to your specific version of go executable. Most of the time you will probably keep it empty. But gocmd can be useful if you've compiled a piece of experimental code in a folder that requires generics.

cgo determines the value of the environment variable CGO_ENABLED and whether to enable the gcc link during build. Note that the CGO feature is only available for current GOOS/GOARCH, it is not well supported for cross-compilation.

race indicates whether to enable race condition detection.

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

Target platforms: for , os , arch

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

---
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 keys 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, where each entry is an os/arch pair.

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

post-action,pre-action

A shell script can be specified to be 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 feature. The corresponding data source comes from our build.Context variable. The definition of this variable will be described at the end of the article.

Specifically, { {.Info.GOARCH}} represents the running go runtime value, which is runtime.GOARCH , while { {.OS}} and { {.ARCH}} are the corresponding values for the target being built.

Due to jekyll template expansion, all { { spaces are inserted to prevent the article from failing.
post-action-file,pre-action-file

You can use a script file if you want.

Notice

These settings are per-project only and do not support being applied to the project-group level. The reason is that the group level is removed in the final stage of our code implementation.

ldflags, asmflags, gcflags, tags

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

But in our case, you should specify them as arrays, for example:

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

The global ldflags parameter specified will be used when all projects are built, unless you explicitly specify a specific version of ldflags in a project.

extends

Writing variable values to specific packages of code being built is accomplished with go build -ldflags -X ... . There are also configuration file entries to simplify the 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}}"

Template expansion can be used, or small shell scripts can be embedded.

But writing a lot of scripts here is discouraged.

The examples are given as hedzr/cmdr CLI app, but in reality they are redundant: as a family we automatically try to identify if your go.mod contains a reference to cmdr, so Decided whether we want to automatically fill in this set of parameters.

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

Top-level specific configuration parameters

In the configuration file, app.bgo.build is the top level of the configuration item, where exclusion directories and output filename templates can be specified:

---
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 block, you can specify named-as as the template for outputting the executable file name. By default, bgo will use { {.AppName}}-{ {.OS}}-{ {.ARCH}} .

dir specifies the output folder, where the executable is pointed.

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

excludes is an array of strings that provide a set of filename wildcard templates, and folders matching these templates will not be scanned.

Build Context

In some fields we allow you to embed dynamic variable values, which will change based on the build 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 the declaration of build.Context

The corresponding code snippet from the bgo source code is given below, so I don't have to explain it any further.

This is not the latest version, it is still iterating
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 or check it out at go.dev.

Use of the command line

bgo is a hedzr/cmdr , with basic features supported by cmdr, such as free multi-level subcommand parameter input and recognition, and so on.

image-20220128180556300

In general, you should use bgo in two steps:

  1. Use bgo init generate a bgo.yml template, which organizes the scanned cli apps into this configuration template, please rename it to .bgo.yml facilitate automatic loading of bgo.

    bgo looks for the existence of a .bgo.yml file from several automatic locations. In fact it will also look at bgo.yml, and will automatically expand to the corresponding conf.d folder for autoloading and merging, so you can write a separate yaml fragment for each project in conf.d, which It's great for continuous integration.

  2. Once the .bgo.yml is ready (you can manually edit it to add custom properties), just use bgo one-time build.

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

  1. If bgo doesn't find a configuration file, we try to scan the current folder to try to build.
  2. If you don't want unexpected build behavior, take the --dry-run parameter.

Some potentially useful command lines are listed below, and none of them require a configuration file to be present - but as mentioned, a configuration file can give you a lot of control in an easily tweakable format, and the command line is no matter what Optimization, nor can it hide -ldflags is so complex and difficult to edit.

To shorten command line typing, running bgo is implicitly equivalent to executing the bgo build subcommand. That is, bgo -s essentially executes bgo build -s , which will start a short build mode.

So to see possible command line arguments you should use bgo build --help .

Build against current GOOS/GOARCH

bgo -s
bgo -s -pn project-one

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

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

full scan mode

bgo -f

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

Specify the build target platform

For example, only compile the linux/386 executable file for 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, an array can be specified by specifying it multiple times:

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

And feel free to use the comma delimiter ( , ) to tell bgo to recognize a list of arrays, for example the above example actually gives an array of three [ "386", "amd64", "arm64"] as arguments: 061f60d4f9ae45 .

In addition, for , os and arch are applicable to both long and short parameter forms, --for or -for no problem, the purpose is to reduce the memory burden.

Similarly, this is also valid:

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

Specify the build project name

bgo -pn bgo
bgo used as the build abbreviation and is a shortened way bgo build

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

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

Enable Shell Autocomplete

Currently bgo can provide Shell auto-completion function. After entering bgo, type TAB .

image-20220130092618399

as well as

image-20220130092701837

and

image-20220130092728651

If you are running bgo by downloading the binary executable, a few steps are required to enable shell autocompletion.

zsh

For the zsh environment, the autocomplete script is generated like this:

$ 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 a place to put the _bgo completion script, it will output the script to the console, you need to save it _bgo as 061f60d4f9b185 and put it 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. bgo cannot be successfully written due to write permissions or other issues, then you need to do it manually.

You can also generate the script to a specified location:

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

bash autocomplete script

postscript

bgo may seem useful, but it probably won't work for you either.

bgo is like a modules manager and build aid, but it is not actually a modules manager, at most it can only be regarded as an automatic builder for main packages.

So the important thing is said three times: bgo pipe exe regardless of lib.

At last

In the end, I have to say that what bgo did is very rude, because the initial idea was just to have a Disabled flag to kill certain projects, and then I wanted to have a --project-name to filter, then -os, -arch , and then found it necessary to have --for.

And then it was almost out of control.

But anyway it can run now.

title map

image-20220130110150772

Off topic

Anyone else remember Newegg?

Suddenly I saw some news about newegg. It turns out that its American parent company is alive and well, far from being closed down and declining, and it went public last year.

At this age change, looking back on the changes on the Internet in the past 20 years, my heart is filled with emotion but it is difficult to evaporate.

REFs

🔚


hedzr
95 声望19 粉丝