forked from u-root/u-root
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
u-root: add the new go builder the right way
Previously, we added the gobusybox builder as a test. Add it the way it should be added: - make a new builder, gbb, and type GBBBBuilder that implements builder.Builder This new type uses the u-root/gobusybox package - extend the string handling for the build option to include gbb - add a test for the gbb builder Remaining is the question of whether to pull gobusybox into u-root. Is this separation the right thing in the long term? gobusybox and u-root are very tightly connected. Signed-off-by: Ronald G. Minnich <[email protected]>
- Loading branch information
1 parent
b8c06a0
commit 73262e9
Showing
4 changed files
with
157 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Copyright 2015-2021 the u-root Authors. All rights reserved | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package builder | ||
|
||
import ( | ||
"errors" | ||
"flag" | ||
"fmt" | ||
"os" | ||
"path" | ||
"path/filepath" | ||
|
||
"github.com/u-root/gobusybox/src/pkg/bb" | ||
"github.com/u-root/gobusybox/src/pkg/golang" | ||
"github.com/u-root/u-root/pkg/cpio" | ||
"github.com/u-root/u-root/pkg/uroot/initramfs" | ||
) | ||
|
||
// GBBBuilder is an implementation of Builder that compiles many Go commands | ||
// into one busybox-style binary. | ||
// | ||
// GBBBuilder will also include symlinks for each command to the busybox binary. | ||
// | ||
// GBBBuilder does all this by rewriting the source files of the packages given | ||
// to create one busybox-like binary containing all commands. | ||
// | ||
// The compiled binary uses argv[0] to decide which Go command to run. | ||
// | ||
// See bb/README.md for a detailed explanation of the implementation of busybox | ||
// mode. | ||
type GBBBuilder struct { | ||
// ShellBang means generate #! files instead of symlinks. | ||
// ShellBang are more portable and just as efficient. | ||
ShellBang bool | ||
} | ||
|
||
// DefaultBinaryDir implements Builder.DefaultBinaryDir. | ||
// | ||
// The default initramfs binary dir is bbin for busybox binaries. | ||
func (GBBBuilder) DefaultBinaryDir() string { | ||
return "bbin" | ||
} | ||
|
||
// Build is an implementation of Builder.Build for a busybox-like initramfs. | ||
func (b GBBBuilder) Build(af *initramfs.Files, opts Opts) error { | ||
// Build the busybox binary. | ||
if len(opts.TempDir) == 0 { | ||
return fmt.Errorf("opts.TempDir is empty") | ||
} | ||
bbPath := filepath.Join(opts.TempDir, "bb") | ||
env := golang.Default() | ||
if env.CgoEnabled { | ||
env.CgoEnabled = false | ||
} | ||
|
||
remove := false | ||
|
||
if len(opts.BinaryDir) == 0 { | ||
return fmt.Errorf("must specify binary directory") | ||
} | ||
|
||
bopts := &bb.Opts{ | ||
Env: env, | ||
GenSrcDir: opts.TempDir, | ||
CommandPaths: opts.Packages, | ||
BinaryPath: bbPath, | ||
GoBuildOpts: &golang.BuildOpts{}, | ||
} | ||
bopts.GoBuildOpts.RegisterFlags(flag.CommandLine) | ||
|
||
if err := bb.BuildBusybox(bopts); err != nil { | ||
var errGopath *bb.ErrGopathBuild | ||
var errGomod *bb.ErrModuleBuild | ||
if errors.As(err, &errGopath) { | ||
return fmt.Errorf("preserving bb generated source directory at %s due to error. To reproduce build, `cd %s` and `GO111MODULE=off GOPATH=%s go build`", opts.TempDir, errGopath.CmdDir, errGopath.GOPATH) | ||
} else if errors.As(err, &errGomod) { | ||
return fmt.Errorf("preserving bb generated source directory at %s due to error. To debug build, `cd %s` and use `go build` to build, or `go mod [why|tidy|graph]` to debug dependencies, or `go list -m all` to list all dependency versions", opts.TempDir, errGomod.CmdDir) | ||
} else { | ||
return fmt.Errorf("preserving bb generated source directory at %s due to error", opts.TempDir) | ||
} | ||
} | ||
// Only remove temp dir if there was no error. | ||
if remove { | ||
os.RemoveAll(opts.TempDir) | ||
} | ||
|
||
if err := af.AddFile(bbPath, "/bbin/bb"); err != nil { | ||
return err | ||
} | ||
|
||
// Add symlinks for included commands to initramfs. | ||
for _, pkg := range opts.Packages { | ||
if _, ok := skip[path.Base(pkg)]; ok { | ||
continue | ||
} | ||
|
||
// Add a symlink /bbin/{cmd} -> /bbin/bb to our initramfs. | ||
// Or add a #! file if b.ShellBang is set ... | ||
if b.ShellBang { | ||
b := path.Base(pkg) | ||
if err := af.AddRecord(cpio.StaticFile(filepath.Join(opts.BinaryDir, b), "#!/bbin/bb #!"+b+"\n", 0o755)); err != nil { | ||
return err | ||
} | ||
} else if err := af.AddRecord(cpio.Symlink(filepath.Join(opts.BinaryDir, path.Base(pkg)), "bb")); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright 2021 the u-root Authors. All rights reserved | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package builder | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/u-root/u-root/pkg/golang" | ||
"github.com/u-root/u-root/pkg/uroot/initramfs" | ||
) | ||
|
||
func TestGBBBuild(t *testing.T) { | ||
dir := t.TempDir() | ||
|
||
opts := Opts{ | ||
Env: golang.Default(), | ||
Packages: []string{ | ||
"../test/foo", | ||
"../../../cmds/core/elvish", | ||
}, | ||
TempDir: dir, | ||
BinaryDir: "bbin", | ||
} | ||
af := initramfs.NewFiles() | ||
var gbb GBBBuilder | ||
if err := gbb.Build(af, opts); err != nil { | ||
t.Fatalf("Build(%v, %v); %v != nil", af, opts, err) | ||
} | ||
|
||
mustContain := []string{ | ||
"bbin/elvish", | ||
"bbin/foo", | ||
} | ||
for _, name := range mustContain { | ||
if !af.Contains(name) { | ||
t.Errorf("expected files to include %q; archive: %v", name, af) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters