Merge branch 'feat/r4g-fallback' into feat/r4g
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
// mesh-pack builds a Go bundle by hand with the recipe of the mesh-build-go module and packs it with mesh-sdk's own
|
||||
// buildstep.Pack, printing the digest, so a hand build has the form of a built artifact and, with the same Go version,
|
||||
// its digest (novox/hq ADR 0526; fallback record F1; issue 1499 for the Go version).
|
||||
//
|
||||
// mesh-pack -dir <module dir> -from <package> -binary <name> [-system arch] [-out <archive file>]
|
||||
// mesh-pack -pack <directory> [-out <archive file>] (a `files` archive: pack a tree as it is)
|
||||
//
|
||||
// The recipe is mesh-catalog modules/mesh-build-go cmd/mesh-build-go/build.go (recipeFlags, recipeLinkerFlags,
|
||||
// recipeSystemStamp, buildEnv): CGO_ENABLED=0, GOFLAGS "-trimpath -buildvcs=false -mod=mod" (-mod=vendor when the
|
||||
// directory vendors), GOTOOLCHAIN=local, GOPROXY=off, and -ldflags "-s -w -X main.builtFor=<system>".
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/buildstep"
|
||||
)
|
||||
|
||||
const (
|
||||
recipeFlags = "-trimpath -buildvcs=false"
|
||||
recipeLinkerFlags = "-s -w"
|
||||
recipeSystemStamp = "main.builtFor"
|
||||
)
|
||||
|
||||
// Env is the build module's environment for the compile of dir, added to the caller's own.
|
||||
func Env(dir string) []string {
|
||||
mod := "-mod=mod"
|
||||
if _, err := os.Stat(filepath.Join(dir, "vendor", "modules.txt")); err == nil {
|
||||
mod = "-mod=vendor"
|
||||
}
|
||||
return append(os.Environ(),
|
||||
"CGO_ENABLED=0",
|
||||
"GOFLAGS="+recipeFlags+" "+mod,
|
||||
"GOTOOLCHAIN=local",
|
||||
"GOPROXY=off",
|
||||
)
|
||||
}
|
||||
|
||||
// Args is the arguments of the go command of the recipe.
|
||||
func Args(dir, from, out, binary, system string) []string {
|
||||
linker := recipeLinkerFlags
|
||||
if s := strings.TrimSpace(system); s != "" {
|
||||
linker += " -X " + recipeSystemStamp + "=" + s
|
||||
}
|
||||
return []string{"-C", dir, "build", "-ldflags", linker, "-o", filepath.Join(out, binary), "./" + strings.Trim(from, "./")}
|
||||
}
|
||||
|
||||
// Build compiles the package into a fresh directory and answers it.
|
||||
func Build(dir, from, binary, system string) (string, error) {
|
||||
out, err := os.MkdirTemp("", "mesh-pack-")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cmd := exec.Command("go", Args(dir, from, out, binary, system)...)
|
||||
cmd.Env = Env(dir)
|
||||
cmd.Stdout, cmd.Stderr = os.Stderr, os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
os.RemoveAll(out)
|
||||
return "", fmt.Errorf("go build of %s: %w", from, err)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func run(args []string) (string, error) {
|
||||
fs := flag.NewFlagSet("mesh-pack", flag.ContinueOnError)
|
||||
dir := fs.String("dir", ".", "the Go module's directory")
|
||||
from := fs.String("from", "", "the package to build, relative to -dir (the artifact's from)")
|
||||
binary := fs.String("binary", "", "the binary's name in the archive")
|
||||
system := fs.String("system", "", "the system stamped into main.builtFor (an artifact's system, e.g. arch)")
|
||||
pack := fs.String("pack", "", "pack this directory as it is (a files archive) instead of building")
|
||||
outFile := fs.String("out", "", "write the archive here")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return "", err
|
||||
}
|
||||
root := *pack
|
||||
if root == "" {
|
||||
if *from == "" || *binary == "" {
|
||||
return "", fmt.Errorf("-from and -binary are needed (or -pack <directory>)")
|
||||
}
|
||||
out, err := Build(*dir, *from, *binary, *system)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer os.RemoveAll(out)
|
||||
root = out
|
||||
}
|
||||
archive, digest, err := buildstep.Pack(root)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if *outFile != "" {
|
||||
if err := os.WriteFile(*outFile, archive, 0o644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return digest, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
digest, err := run(os.Args[1:])
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "mesh-pack:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(digest)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/buildstep"
|
||||
)
|
||||
|
||||
func fixture(t *testing.T) string {
|
||||
t.Helper()
|
||||
d := t.TempDir()
|
||||
os.MkdirAll(filepath.Join(d, "sub"), 0o755)
|
||||
os.WriteFile(filepath.Join(d, "a.txt"), []byte("alpha"), 0o644)
|
||||
os.WriteFile(filepath.Join(d, "sub", "run"), []byte("#!/bin/sh\n"), 0o755)
|
||||
return d
|
||||
}
|
||||
|
||||
func TestPackFixtureTwiceGivesBuildstepsDigest(t *testing.T) {
|
||||
d := fixture(t)
|
||||
_, want, err := buildstep.Pack(d)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := 0; i < 2; i++ {
|
||||
got, err := run([]string{"-pack", d, "-out", filepath.Join(t.TempDir(), "x.tgz")})
|
||||
if err != nil || got != want {
|
||||
t.Fatalf("run %d: %q, %v; want %q", i, got, err, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildTwiceGivesOneDigestAndRecipeArgs(t *testing.T) {
|
||||
m := t.TempDir()
|
||||
os.WriteFile(filepath.Join(m, "go.mod"), []byte("module x\n\ngo 1.21\n"), 0o644)
|
||||
os.MkdirAll(filepath.Join(m, "cmd", "p"), 0o755)
|
||||
os.WriteFile(filepath.Join(m, "cmd", "p", "main.go"), []byte("package main\n\nvar builtFor string\n\nfunc main() { println(builtFor) }\n"), 0o644)
|
||||
args := []string{"-dir", m, "-from", "cmd/p", "-binary", "p", "-system", "arch"}
|
||||
a, err := run(args)
|
||||
if err != nil {
|
||||
t.Skipf("no go toolchain that builds offline: %v", err)
|
||||
}
|
||||
b, err := run(args)
|
||||
if err != nil || a != b {
|
||||
t.Fatalf("two builds: %q, %q, %v", a, b, err)
|
||||
}
|
||||
got := Args("/d", "./cmd/p/", "/o", "p", "arch")
|
||||
if got[len(got)-1] != "./cmd/p" || got[4] != "-s -w -X main.builtFor=arch" {
|
||||
t.Fatalf("args %v", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user