From 8b4491fc937a9f8adaf000aa3482f37108f37a38 Mon Sep 17 00:00:00 2001 From: Chris Koch <chrisko@google.com> Date: Sat, 24 Feb 2024 01:12:45 +0000 Subject: [PATCH 1/3] Rename mkuimage -> uimage make Signed-off-by: Chris Koch <chrisko@google.com> --- .github/workflows/go.yml | 2 +- cmd/mkuimage/main.go | 99 ------------------- cmd/{mkuimage => uimage}/.gitignore | 1 + cmd/uimage/main.go | 62 ++++++++++++ cmd/{mkuimage => uimage}/main_test.go | 82 ++++++++------- .../testdata/test-config.yaml | 0 go.mod | 2 +- go.sum | 2 + uimage/builder/binary_test.go | 4 +- uimage/builder/gbb_test.go | 18 ++-- uimage/mkuimage/cmd.go | 10 +- 11 files changed, 127 insertions(+), 155 deletions(-) delete mode 100644 cmd/mkuimage/main.go rename cmd/{mkuimage => uimage}/.gitignore (68%) create mode 100644 cmd/uimage/main.go rename cmd/{mkuimage => uimage}/main_test.go (82%) rename cmd/{mkuimage => uimage}/testdata/test-config.yaml (100%) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 8304f63..bee02d9 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -53,7 +53,7 @@ jobs: run: go test -v -covermode atomic -coverpkg ./... -coverprofile cover.out ./... - name: Convert GOCOVERDIR coverage data - run: go tool covdata textfmt -i=cmd/mkuimage/cover -o cmdcover.out + run: go tool covdata textfmt -i=cmd/uimage/cover -o cmdcover.out - uses: codecov/codecov-action@v4-beta env: diff --git a/cmd/mkuimage/main.go b/cmd/mkuimage/main.go deleted file mode 100644 index 58947f5..0000000 --- a/cmd/mkuimage/main.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2015-2018 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. - -// Command mkuimage builds CPIO archives with the given files and Go commands. -package main - -import ( - "errors" - "flag" - "fmt" - "log" - "log/slog" - "os" - - "github.com/dustin/go-humanize" - "github.com/u-root/gobusybox/src/pkg/golang" - "github.com/u-root/mkuimage/uimage" - "github.com/u-root/mkuimage/uimage/mkuimage" - "github.com/u-root/uio/llog" -) - -var ( - errEmptyFilesArg = errors.New("empty argument to -files") -) - -// checkArgs checks for common mistakes that cause confusion. -// 1. -files as the last argument -// 2. -files followed by any switch, indicating a shell expansion problem -// This is usually caused by Makfiles structured as follows -// u-root -files `which ethtool` -files `which bash` -// if ethtool is not installed, the expansion yields -// u-root -files -files `which bash` -// and the rather confusing error message -// 16:14:51 Skipping /usr/bin/bash because it is not a directory -// which, in practice, nobody understands -func checkArgs(args ...string) error { - if len(args) == 0 { - return nil - } - - if args[len(args)-1] == "-files" { - return fmt.Errorf("last argument is -files:%w", errEmptyFilesArg) - } - - // We know the last arg is not -files; scan the arguments for -files - // followed by a switch. - for i := 0; i < len(args)-1; i++ { - if args[i] == "-files" && args[i+1][0] == '-' { - return fmt.Errorf("-files argument %d is followed by a switch: %w", i, errEmptyFilesArg) - } - } - - return nil -} - -func main() { - log.SetFlags(log.Ltime) - if err := checkArgs(os.Args...); err != nil { - log.Fatal(err) - } - - env := golang.Default(golang.DisableCGO()) - f := &mkuimage.Flags{ - Commands: mkuimage.CommandFlags{Builder: "bb"}, - ArchiveFormat: "cpio", - OutputFile: defaultFile(env), - } - f.RegisterFlags(flag.CommandLine) - - l := llog.Default() - l.RegisterVerboseFlag(flag.CommandLine, "v", slog.LevelDebug) - - tf := &mkuimage.TemplateFlags{} - tf.RegisterFlags(flag.CommandLine) - flag.Parse() - - // Set defaults. - m := []uimage.Modifier{ - uimage.WithReplaceEnv(env), - uimage.WithBaseArchive(uimage.DefaultRamfs()), - uimage.WithCPIOOutput(defaultFile(env)), - } - if err := mkuimage.CreateUimage(l, m, tf, f, flag.Args()); err != nil { - l.Errorf("mkuimage error: %v", err) - os.Exit(1) - } - - if stat, err := os.Stat(f.OutputFile); err == nil && f.ArchiveFormat == "cpio" { - l.Infof("Successfully built %q (size %d bytes -- %s).", f.OutputFile, stat.Size(), humanize.IBytes(uint64(stat.Size()))) - } -} - -func defaultFile(env *golang.Environ) string { - if len(env.GOOS) == 0 || len(env.GOARCH) == 0 { - return "/tmp/initramfs.cpio" - } - return fmt.Sprintf("/tmp/initramfs.%s_%s.cpio", env.GOOS, env.GOARCH) -} diff --git a/cmd/mkuimage/.gitignore b/cmd/uimage/.gitignore similarity index 68% rename from cmd/mkuimage/.gitignore rename to cmd/uimage/.gitignore index 56fc4cf..41e6ef7 100644 --- a/cmd/mkuimage/.gitignore +++ b/cmd/uimage/.gitignore @@ -1,2 +1,3 @@ mkuimage +uimage cover diff --git a/cmd/uimage/main.go b/cmd/uimage/main.go new file mode 100644 index 0000000..54831f7 --- /dev/null +++ b/cmd/uimage/main.go @@ -0,0 +1,62 @@ +// Copyright 2015-2024 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. + +// Command uimage builds CPIO archives with the given files and Go commands. +package main + +import ( + "fmt" + "log" + "log/slog" + "os" + + "github.com/u-root/gobusybox/src/pkg/golang" + "github.com/u-root/mkuimage/uimage" + "github.com/u-root/mkuimage/uimage/mkuimage" + "github.com/u-root/uio/cli" + "github.com/u-root/uio/llog" +) + +func main() { + log.SetFlags(log.Ltime) + l := llog.Default() + + env := golang.Default(golang.DisableCGO()) + f := &mkuimage.Flags{ + Commands: mkuimage.CommandFlags{Builder: "bb"}, + ArchiveFormat: "cpio", + OutputFile: defaultFile(env), + } + tf := &mkuimage.TemplateFlags{} + + makeCmd := cli.Command{ + Name: "make", + Short: "create uimage from specified flags", + Run: func(args []string) { + // Set defaults. + m := []uimage.Modifier{ + uimage.WithReplaceEnv(env), + uimage.WithBaseArchive(uimage.DefaultRamfs()), + uimage.WithCPIOOutput(defaultFile(env)), + } + if err := mkuimage.CreateUimage(l, m, tf, f, args); err != nil { + l.Errorf("mkuimage error: %v", err) + os.Exit(1) + } + }, + } + l.RegisterVerboseFlag(makeCmd.Flags(), "v", slog.LevelDebug) + f.RegisterFlags(makeCmd.Flags()) + tf.RegisterFlags(makeCmd.Flags()) + + app := cli.App{makeCmd} + app.Run(os.Args) +} + +func defaultFile(env *golang.Environ) string { + if len(env.GOOS) == 0 || len(env.GOARCH) == 0 { + return "/tmp/initramfs.cpio" + } + return fmt.Sprintf("/tmp/initramfs.%s_%s.cpio", env.GOOS, env.GOARCH) +} diff --git a/cmd/mkuimage/main_test.go b/cmd/uimage/main_test.go similarity index 82% rename from cmd/mkuimage/main_test.go rename to cmd/uimage/main_test.go index 7aca4bc..f3020c1 100644 --- a/cmd/mkuimage/main_test.go +++ b/cmd/uimage/main_test.go @@ -93,10 +93,10 @@ func TestUrootCmdline(t *testing.T) { wantOutput func(*testing.T, string) } - noCmdTests := []testCase{ + tests := []testCase{ { name: "include one extra file", - args: []string{"-nocmd", "-files=/bin/bash"}, + args: []string{"make", "-nocmd", "-files=/bin/bash"}, env: []string{"GO111MODULE=off"}, validators: []itest.ArchiveValidator{ itest.HasFile{Path: "bin/bash"}, @@ -104,7 +104,7 @@ func TestUrootCmdline(t *testing.T) { }, { name: "fix usage of an absolute path", - args: []string{"-nocmd", fmt.Sprintf("-files=%s:/bin", sampledir)}, + args: []string{"make", "-nocmd", fmt.Sprintf("-files=%s:/bin", sampledir)}, env: []string{"GO111MODULE=off"}, validators: []itest.ArchiveValidator{ itest.HasFile{Path: "/bin/foo"}, @@ -113,7 +113,7 @@ func TestUrootCmdline(t *testing.T) { }, { name: "include multiple extra files", - args: []string{"-nocmd", "-files=/bin/bash", "-files=/bin/ls", fmt.Sprintf("-files=%s", samplef.Name())}, + args: []string{"make", "-nocmd", "-files=/bin/bash", "-files=/bin/ls", fmt.Sprintf("-files=%s", samplef.Name())}, env: []string{"GO111MODULE=off"}, validators: []itest.ArchiveValidator{ itest.HasFile{Path: "bin/bash"}, @@ -123,7 +123,7 @@ func TestUrootCmdline(t *testing.T) { }, { name: "include one extra file with rename", - args: []string{"-nocmd", "-files=/bin/bash:bin/bush"}, + args: []string{"make", "-nocmd", "-files=/bin/bash:bin/bush"}, env: []string{"GO111MODULE=off"}, validators: []itest.ArchiveValidator{ itest.HasFile{Path: "bin/bush"}, @@ -131,19 +131,16 @@ func TestUrootCmdline(t *testing.T) { }, { name: "supplied file can be uinit", - args: []string{"-nocmd", "-files=/bin/bash:bin/bash", "-uinitcmd=/bin/bash"}, + args: []string{"make", "-nocmd", "-files=/bin/bash:bin/bash", "-uinitcmd=/bin/bash"}, env: []string{"GO111MODULE=off"}, validators: []itest.ArchiveValidator{ itest.HasFile{Path: "bin/bash"}, itest.HasRecord{R: cpio.Symlink("bin/uinit", "bash")}, }, }, - } - - bareTests := []testCase{ { name: "uinitcmd", - args: []string{"-uinitcmd=echo foobar fuzz", "-defaultsh=", "github.com/u-root/u-root/cmds/core/init", "github.com/u-root/u-root/cmds/core/echo"}, + args: []string{"make", "-uinitcmd=echo foobar fuzz", "-defaultsh=", "github.com/u-root/u-root/cmds/core/init", "github.com/u-root/u-root/cmds/core/echo"}, validators: []itest.ArchiveValidator{ itest.HasRecord{R: cpio.Symlink("bin/uinit", "../bbin/echo")}, itest.HasContent{ @@ -155,6 +152,7 @@ func TestUrootCmdline(t *testing.T) { { name: "binary build", args: []string{ + "make", "-build=binary", "-defaultsh=", "github.com/u-root/u-root/cmds/core/init", @@ -169,6 +167,7 @@ func TestUrootCmdline(t *testing.T) { { name: "hosted mode", args: []string{ + "make", "-base=/dev/null", "-defaultsh=", "-initcmd=", @@ -180,6 +179,7 @@ func TestUrootCmdline(t *testing.T) { name: "AMD64 build", env: []string{"GOARCH=amd64"}, args: []string{ + "make", "-defaultsh=echo", "github.com/u-root/u-root/cmds/core/echo", "github.com/u-root/u-root/cmds/core/init", @@ -189,6 +189,7 @@ func TestUrootCmdline(t *testing.T) { name: "AMD64 build with temp dir", env: []string{"GOARCH=amd64"}, args: []string{ + "make", "--keep-tmp-dir", "--defaultsh=echo", "github.com/u-root/u-root/cmds/core/echo", @@ -201,6 +202,7 @@ func TestUrootCmdline(t *testing.T) { name: "ARM7 build", env: []string{"GOARCH=arm", "GOARM=7"}, args: []string{ + "make", "-defaultsh=", "github.com/u-root/u-root/cmds/core/init", "github.com/u-root/u-root/cmds/core/echo", @@ -210,6 +212,7 @@ func TestUrootCmdline(t *testing.T) { name: "ARM64 build", env: []string{"GOARCH=arm64"}, args: []string{ + "make", "-defaultsh=", "github.com/u-root/u-root/cmds/core/init", "github.com/u-root/u-root/cmds/core/echo", @@ -219,6 +222,7 @@ func TestUrootCmdline(t *testing.T) { name: "RISCV 64bit build", env: []string{"GOARCH=riscv64"}, args: []string{ + "make", "-defaultsh=", "github.com/u-root/u-root/cmds/core/init", "github.com/u-root/u-root/cmds/core/echo", @@ -227,6 +231,7 @@ func TestUrootCmdline(t *testing.T) { { name: "build invalid", args: []string{ + "make", "-build=source", "github.com/u-root/u-root/cmds/core/init", "github.com/u-root/u-root/cmds/core/echo", @@ -237,6 +242,7 @@ func TestUrootCmdline(t *testing.T) { name: "arch invalid preserves temp dir", env: []string{"GOARCH=doesnotexist"}, args: []string{ + "make", "--defaultsh=echo", "github.com/u-root/u-root/cmds/core/echo", "github.com/u-root/u-root/cmds/core/init", @@ -247,6 +253,7 @@ func TestUrootCmdline(t *testing.T) { { name: "specify temp dir", args: []string{ + "make", "--tmp-dir=" + tempDir, "github.com/u-root/u-root/cmds/core/echo", "github.com/u-root/u-root/cmds/core/init", @@ -256,7 +263,12 @@ func TestUrootCmdline(t *testing.T) { }, { name: "template config", - args: []string{"-config-file=./testdata/test-config.yaml", "-v", "-config=coreconf"}, + args: []string{ + "make", + "-config-file=./testdata/test-config.yaml", + "-v", + "-config=coreconf", + }, validators: []itest.ArchiveValidator{ itest.HasRecord{R: cpio.CharDev("dev/tty", 0o666, 5, 0)}, itest.HasFile{Path: "bbin/bb"}, @@ -275,7 +287,12 @@ func TestUrootCmdline(t *testing.T) { }, { name: "template command", - args: []string{"-config-file=./testdata/test-config.yaml", "-v", "core"}, + args: []string{ + "make", + "-config-file=./testdata/test-config.yaml", + "-v", + "core", + }, validators: []itest.ArchiveValidator{ itest.HasRecord{R: cpio.CharDev("dev/tty", 0o666, 5, 0)}, itest.HasFile{Path: "bbin/bb"}, @@ -286,27 +303,27 @@ func TestUrootCmdline(t *testing.T) { }, { name: "template config not found", - args: []string{"-config-file=./testdata/test-config.yaml", "-v", "-config=foobar"}, + args: []string{"make", "-config-file=./testdata/test-config.yaml", "-v", "-config=foobar"}, exitCode: 1, }, { name: "builder not found", - args: []string{"-v", "build=source"}, + args: []string{"make", "-v", "build=source"}, exitCode: 1, }, { name: "template file not found", - args: []string{"-v", "-config-file=./testdata/doesnotexist"}, + args: []string{"make", "-v", "-config-file=./testdata/doesnotexist"}, exitCode: 1, }, { name: "config not found with no default template", - args: []string{"-v", "-config=foo"}, + args: []string{"make", "-v", "-config=foo"}, exitCode: 1, }, } - for _, tt := range append(noCmdTests, bareTests...) { + for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { var g errgroup.Group @@ -334,11 +351,11 @@ func TestUrootCmdline(t *testing.T) { var exitErr *exec.ExitError if errors.As(err, &exitErr) { if ec := exitErr.Sys().(syscall.WaitStatus).ExitStatus(); ec != tt.exitCode { - t.Errorf("mkuimage exit code = %d, want %d", ec, tt.exitCode) + t.Errorf("uimage exit code = %d, want %d", ec, tt.exitCode) } return } else if err != nil { - t.Errorf("mkuimage failed: %v", err) + t.Errorf("uimage failed: %v", err) return } @@ -370,8 +387,10 @@ func buildIt(t *testing.T, execPath string, args, env []string, gocoverdir strin // Use the u-root command outside of the $GOPATH tree to make sure it // still works. - args = append([]string{"-o", initramfs.Name()}, args...) - t.Logf("Commandline: %v mkuimage %v", strings.Join(env, " "), strings.Join(args, " ")) + if len(args) > 0 { + args = append(append([]string{args[0]}, "-o", initramfs.Name()), args[1:]...) + } + t.Logf("Commandline: %v uimage %v", strings.Join(env, " "), strings.Join(args, " ")) c := exec.Command(execPath, args...) c.Env = append(os.Environ(), env...) @@ -388,24 +407,3 @@ func buildIt(t *testing.T, execPath string, args, env []string, gocoverdir strin } return initramfs, string(out), h1.Sum(nil), nil } - -func TestCheckArgs(t *testing.T) { - for _, tt := range []struct { - name string - args []string - err error - }{ - {"-files is only arg", []string{"-files"}, errEmptyFilesArg}, - {"-files followed by -files", []string{"-files", "-files"}, errEmptyFilesArg}, - {"-files followed by any other switch", []string{"-files", "-abc"}, errEmptyFilesArg}, - {"no args", []string{}, nil}, - {"u-root alone", []string{"u-root"}, nil}, - {"u-root with -files and other args", []string{"u-root", "-files", "/bin/bash", "core"}, nil}, - } { - t.Run(tt.name, func(t *testing.T) { - if err := checkArgs(tt.args...); !errors.Is(err, tt.err) { - t.Errorf("%q: got %v, want %v", tt.args, err, tt.err) - } - }) - } -} diff --git a/cmd/mkuimage/testdata/test-config.yaml b/cmd/uimage/testdata/test-config.yaml similarity index 100% rename from cmd/mkuimage/testdata/test-config.yaml rename to cmd/uimage/testdata/test-config.yaml diff --git a/go.mod b/go.mod index 084726a..f457b51 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/hugelgupf/go-shlex v0.0.0-20200702092117-c80c9d0918fa github.com/u-root/gobusybox/src v0.0.0-20240218001334-a32c1883bffa github.com/u-root/u-root v0.12.0 - github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a + github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 golang.org/x/sync v0.6.0 golang.org/x/sys v0.16.0 golang.org/x/tools v0.17.0 diff --git a/go.sum b/go.sum index 9eab4a4..e5279cf 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/u-root/u-root v0.12.0 h1:K0AuBFriwr0w/PGS3HawiAw89e3+MU7ks80GpghAsNs= github.com/u-root/u-root v0.12.0/go.mod h1:FYjTOh4IkIZHhjsd17lb8nYW6udgXdJhG1c0r6u0arI= github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a h1:BH1SOPEvehD2kVrndDnGJiUF0TrBpNs+iyYocu6h0og= github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= +github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM= +github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= diff --git a/uimage/builder/binary_test.go b/uimage/builder/binary_test.go index 2697684..5f8d933 100644 --- a/uimage/builder/binary_test.go +++ b/uimage/builder/binary_test.go @@ -17,7 +17,7 @@ func TestBinaryBuild(t *testing.T) { opts := Opts{ Env: golang.Default(golang.DisableCGO()), Packages: []string{ - "../../cmd/mkuimage", + "../../cmd/uimage", "github.com/u-root/u-root/cmds/core/init", "cmd/test2json", }, @@ -30,7 +30,7 @@ func TestBinaryBuild(t *testing.T) { } mustContain := []string{ - "bin/mkuimage", + "bin/uimage", "bin/test2json", "bin/init", } diff --git a/uimage/builder/gbb_test.go b/uimage/builder/gbb_test.go index b7bee6a..f4fdfa4 100644 --- a/uimage/builder/gbb_test.go +++ b/uimage/builder/gbb_test.go @@ -21,7 +21,7 @@ func TestGBBBuild(t *testing.T) { opts := Opts{ Env: golang.Default(golang.DisableCGO()), Packages: []string{ - "../../cmd/mkuimage", + "../../cmd/uimage", }, TempDir: dir, } @@ -32,7 +32,7 @@ func TestGBBBuild(t *testing.T) { } mustContain := []string{ - "bbin/mkuimage", + "bbin/uimage", "bbin/bb", } for _, name := range mustContain { @@ -53,7 +53,7 @@ func TestGBBBuildError(t *testing.T) { opts: Opts{ Env: golang.Default(golang.DisableCGO()), Packages: []string{ - "../../cmd/mkuimage", + "../../cmd/uimage", }, BinaryDir: "bbin", }, @@ -63,7 +63,7 @@ func TestGBBBuildError(t *testing.T) { opts: Opts{ TempDir: t.TempDir(), Packages: []string{ - "../../cmd/mkuimage", + "../../cmd/uimage", }, BinaryDir: "bbin", }, @@ -74,7 +74,7 @@ func TestGBBBuildError(t *testing.T) { Env: golang.Default(golang.DisableCGO()), TempDir: t.TempDir(), Packages: []string{ - "../../cmd/mkuimage", + "../../cmd/uimage", }, BinaryDir: "bbin", }, @@ -88,12 +88,12 @@ func TestGBBBuildError(t *testing.T) { Env: golang.Default(golang.DisableCGO()), TempDir: t.TempDir(), Packages: []string{ - "../../cmd/mkuimage", + "../../cmd/uimage", }, BinaryDir: "bbin", }, files: []cpio.Record{ - cpio.StaticFile("bbin/mkuimage", "", 0o777), + cpio.StaticFile("bbin/uimage", "", 0o777), }, want: os.ErrExist, }, @@ -102,12 +102,12 @@ func TestGBBBuildError(t *testing.T) { Env: golang.Default(golang.DisableCGO()), TempDir: t.TempDir(), Packages: []string{ - "../../cmd/mkuimage", + "../../cmd/uimage", }, BinaryDir: "bbin", }, files: []cpio.Record{ - cpio.StaticFile("bbin/mkuimage", "", 0o777), + cpio.StaticFile("bbin/uimage", "", 0o777), }, gbb: GBBBuilder{ShellBang: true}, want: os.ErrExist, diff --git a/uimage/mkuimage/cmd.go b/uimage/mkuimage/cmd.go index 1f4dc88..421e7a8 100644 --- a/uimage/mkuimage/cmd.go +++ b/uimage/mkuimage/cmd.go @@ -11,6 +11,7 @@ import ( "runtime" "strings" + "github.com/dustin/go-humanize" "github.com/u-root/mkuimage/uimage" "github.com/u-root/mkuimage/uimage/builder" "github.com/u-root/mkuimage/uimage/templates" @@ -113,5 +114,12 @@ func CreateUimage(l *llog.Logger, base []uimage.Modifier, tf *TemplateFlags, f * l.Errorf("Preserving temp dir due to busybox build error") keepTempDir = true } - return err + if err != nil { + return err + } + + if stat, err := os.Stat(f.OutputFile); err == nil && f.ArchiveFormat == "cpio" { + l.Infof("Successfully built %q (size %d bytes -- %s).", f.OutputFile, stat.Size(), humanize.IBytes(uint64(stat.Size()))) + } + return nil } From 440ed193394b696d2b31a1011a43b8efced81734 Mon Sep 17 00:00:00 2001 From: Chris Koch <chrisko@google.com> Date: Sat, 24 Feb 2024 01:15:12 +0000 Subject: [PATCH 2/3] Update README for mkuimage->uimage make Signed-off-by: Chris Koch <chrisko@google.com> --- README.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 35933c4..ce0db9c 100644 --- a/README.md +++ b/README.md @@ -27,27 +27,27 @@ $ go1.21.5 version # Now use go1.21.5 in place of go ``` -Download and install mkuimage either via git: +Download and install uimage either via git: ```shell git clone https://github.com/u-root/mkuimage -cd mkuimage/cmd/mkuimage +cd mkuimage/cmd/uimage go install ``` Or install directly with go: ```shell -go install github.com/u-root/mkuimage/cmd/mkuimage@latest +go install github.com/u-root/mkuimage/cmd/uimage@latest ``` > [!NOTE] -> The `mkuimage` command will end up in `$GOPATH/bin/mkuimage`, so you may +> The `uimage` command will end up in `$GOPATH/bin/uimage`, so you may > need to add `$GOPATH/bin` to your `$PATH`. ## Examples -Here are some examples of using the `mkuimage` command to build an initramfs. +Here are some examples of using the `uimage` command to build an initramfs. ```shell git clone https://github.com/u-root/u-root @@ -57,7 +57,7 @@ git clone https://github.com/u-root/cpu Build gobusybox binaries of these two commands and add to initramfs: ```shell -$ mkuimage ./u-root/cmds/core/{init,gosh} +$ uimage make ./u-root/cmds/core/{init,gosh} $ cpio -ivt < /tmp/initramfs.linux_amd64.cpio ... @@ -70,7 +70,7 @@ lrwxrwxrwx 0 root root 2 Jan 1 1970 bbin/init -> bb Add symlinks for shell and init: ```shell -$ mkuimage -initcmd=init -defaultsh=gosh ./u-root/cmds/core/{init,gosh} +$ uimage make -initcmd=init -defaultsh=gosh ./u-root/cmds/core/{init,gosh} $ cpio -ivt < /tmp/initramfs.linux_amd64.cpio ... @@ -84,7 +84,7 @@ lrwxrwxrwx 0 root root 9 Jan 1 1970 init -> bbin/init Build everything from core without ls and losetup: ```shell -$ mkuimage ./u-root/cmds/core/* -./u-root/cmds/core/{ls,losetup} +$ uimage make ./u-root/cmds/core/* -./u-root/cmds/core/{ls,losetup} ``` Build an initramfs with init, gosh and cpud in a gobusybox binary: @@ -99,7 +99,7 @@ Build an initramfs with init, gosh and cpud in a gobusybox binary: > To properly resolve these dependencies, head down to the [multi-module uimages section](#multi-module-uimages). ```shell -$ mkuimage ./u-root/cmds/core/{init,gosh} ./cpu/cmds/cpud +$ uimage make ./u-root/cmds/core/{init,gosh} ./cpu/cmds/cpud ... 01:24:15 INFO GBB_STRICT is not set. 01:24:15 INFO [WARNING] github.com/u-root/cpu/cmds/cpud depends on github.com/u-root/u-root @ version v0.11.1-0.20230913033713-004977728a9d @@ -115,12 +115,12 @@ lrwxrwxrwx 0 root root 2 Jan 1 1970 bbin/init -> bb ... ``` -`GBB_PATH` is a place that mkuimage will look for commands. Each colon-separated +`GBB_PATH` is a place that uimage will look for commands. Each colon-separated `GBB_PATH` element is concatenated with patterns from the command-line and checked for existence. For example: ```shell -GBB_PATH=$(pwd)/u-root:$(pwd)/cpu mkuimage \ +GBB_PATH=$(pwd)/u-root:$(pwd)/cpu uimage make \ cmds/core/{init,gosh} \ cmds/cpud @@ -137,7 +137,7 @@ If you add binaries with `-files` are listed, their ldd dependencies will be included as well. ```shell -$ mkuimage -files /bin/bash +$ uimage make -files /bin/bash $ cpio -ivt < /tmp/initramfs.linux_amd64.cpio ... @@ -156,7 +156,7 @@ lrwxrwxrwx 0 root root 42 Jan 1 1970 lib64/ld-linux-x86-64.so. You can determine placement with colons: ```shell -$ mkuimage -files "/bin/bash:sbin/sh" +$ uimage make -files "/bin/bash:sbin/sh" $ cpio -ivt < /tmp/initramfs.linux_amd64.cpio ... @@ -168,7 +168,7 @@ For example on Debian, if you want to add two kernel modules for testing, executing your currently booted kernel: ```shell -$ mkuimage -files "$HOME/hello.ko:etc/hello.ko" -files "$HOME/hello2.ko:etc/hello2.ko" ./u-root/cmds/core/* +$ uimage make -files "$HOME/hello.ko:etc/hello.ko" -files "$HOME/hello2.ko:etc/hello2.ko" ./u-root/cmds/core/* $ qemu-system-x86_64 -kernel /boot/vmlinuz-$(uname -r) -initrd /tmp/initramfs.linux_amd64.cpio ``` @@ -177,7 +177,7 @@ $ qemu-system-x86_64 -kernel /boot/vmlinuz-$(uname -r) -initrd /tmp/initramfs.li To cross compile for an ARM, on Linux: ```shell -GOARCH=arm mkuimage ./u-root/cmds/core/* +GOARCH=arm uimage make ./u-root/cmds/core/* ``` If you are on OSX, and wish to build for Linux on AMD64: @@ -213,7 +213,7 @@ has native uimage support. ## Multi-module uimages -Rather than having mkuimage decide how to resolve dependencies across +Rather than having uimage decide how to resolve dependencies across multi-module repositories, you may also create a go.mod with all commands you intend to use in them. @@ -247,7 +247,7 @@ mod tidy` to add these dependencies to `go.mod`: ```sh go mod tidy -mkuimage \ +uimage make \ github.com/u-root/u-root/cmds/core/ip \ github.com/u-root/u-root/cmds/core/init \ github.com/hugelgupf/p9/cmd/p9ufs @@ -255,12 +255,12 @@ mkuimage \ ## Build Modes -mkuimage can create an initramfs in two different modes, specified by `-build`: +uimage can create an initramfs in two different modes, specified by `-build`: * `bb` mode: One busybox-like binary comprising all the Go tools you ask to include. See [the gobusybox README for how it works](https://github.com/u-root/gobusybox). - In this mode, mkuimage copies and rewrites the source of the tools you asked + In this mode, uimage copies and rewrites the source of the tools you asked to include to be able to compile everything into one busybox-like binary. * `binary` mode: each specified binary is compiled separately and all binaries From 1d7d9b00b3120d483ab814edb9fb3f78ff59c866 Mon Sep 17 00:00:00 2001 From: Chris Koch <chrisko@google.com> Date: Sat, 24 Feb 2024 01:40:26 +0000 Subject: [PATCH 3/3] list and listconfigs commands Signed-off-by: Chris Koch <chrisko@google.com> --- cmd/uimage/main.go | 75 +++++++++++++++++++++++++++++++++++++++++++++- go.mod | 1 + go.sum | 2 -- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/cmd/uimage/main.go b/cmd/uimage/main.go index 54831f7..f61531e 100644 --- a/cmd/uimage/main.go +++ b/cmd/uimage/main.go @@ -10,12 +10,15 @@ import ( "log" "log/slog" "os" + "slices" + "github.com/u-root/gobusybox/src/pkg/bb/findpkg" "github.com/u-root/gobusybox/src/pkg/golang" "github.com/u-root/mkuimage/uimage" "github.com/u-root/mkuimage/uimage/mkuimage" "github.com/u-root/uio/cli" "github.com/u-root/uio/llog" + "golang.org/x/exp/maps" ) func main() { @@ -50,7 +53,77 @@ func main() { f.RegisterFlags(makeCmd.Flags()) tf.RegisterFlags(makeCmd.Flags()) - app := cli.App{makeCmd} + listconfigsCmd := cli.Command{ + Name: "listconfigs", + Short: "list template configs", + Run: func(args []string) { + tpl, err := tf.Get() + if err != nil { + l.Errorf("Failed to get template: %w", err) + os.Exit(1) + } + configs := maps.Keys(tpl.Configs) + slices.Sort(configs) + for _, name := range configs { + fmt.Println(name) + } + }, + } + l.RegisterVerboseFlag(listconfigsCmd.Flags(), "v", slog.LevelDebug) + tf.RegisterFlags(listconfigsCmd.Flags()) + + listCmd := cli.Command{ + Name: "list", + Short: "list commands from template (no args: lists all cmds in template)", + Run: func(args []string) { + tpl, err := tf.Get() + if err != nil { + l.Errorf("Failed to get template: %w", err) + os.Exit(1) + } + var cmds []string + if tf.Config == "" && len(args) == 0 { + for _, conf := range tpl.Configs { + for _, c := range conf.Commands { + cmds = append(cmds, tpl.CommandsFor(c.Commands...)...) + } + } + for _, c := range tpl.Commands { + cmds = append(cmds, c...) + } + } + if tf.Config != "" { + if _, ok := tpl.Configs[tf.Config]; !ok { + l.Errorf("Config %s not found", tf.Config) + os.Exit(1) + } + for _, c := range tpl.Configs[tf.Config].Commands { + cmds = append(cmds, tpl.CommandsFor(c.Commands...)...) + } + } + cmds = append(cmds, tpl.CommandsFor(args...)...) + + lookupEnv := findpkg.DefaultEnv() + paths, err := findpkg.ResolveGlobs(l.AtLevel(slog.LevelInfo), env, lookupEnv, cmds) + if err != nil { + l.Errorf("Failed to resolve commands: %v", err) + os.Exit(1) + } + uniquePaths := map[string]struct{}{} + for _, p := range paths { + uniquePaths[p] = struct{}{} + } + ps := maps.Keys(uniquePaths) + slices.Sort(ps) + for _, p := range ps { + fmt.Println(p) + } + }, + } + l.RegisterVerboseFlag(listCmd.Flags(), "v", slog.LevelDebug) + tf.RegisterFlags(listCmd.Flags()) + + app := cli.App{makeCmd, listconfigsCmd, listCmd} app.Run(os.Args) } diff --git a/go.mod b/go.mod index f457b51..89e0fa7 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/u-root/gobusybox/src v0.0.0-20240218001334-a32c1883bffa github.com/u-root/u-root v0.12.0 github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 + golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 golang.org/x/sync v0.6.0 golang.org/x/sys v0.16.0 golang.org/x/tools v0.17.0 diff --git a/go.sum b/go.sum index e5279cf..be86361 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,6 @@ github.com/u-root/gobusybox/src v0.0.0-20240218001334-a32c1883bffa h1:NNmn/fsvgA github.com/u-root/gobusybox/src v0.0.0-20240218001334-a32c1883bffa/go.mod h1:vN1IwhlCo7gTDTJDUs6WCKM4/C2uiq5w0XvZCqLtb5s= github.com/u-root/u-root v0.12.0 h1:K0AuBFriwr0w/PGS3HawiAw89e3+MU7ks80GpghAsNs= github.com/u-root/u-root v0.12.0/go.mod h1:FYjTOh4IkIZHhjsd17lb8nYW6udgXdJhG1c0r6u0arI= -github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a h1:BH1SOPEvehD2kVrndDnGJiUF0TrBpNs+iyYocu6h0og= -github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM= github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=