From 35faf23c6b587f34db7b8091015c45f9026edbab Mon Sep 17 00:00:00 2001 From: Simone Basso Date: Wed, 25 Jan 2023 17:55:06 +0100 Subject: [PATCH] feat: rewrite generic build rules in Go (#1051) This diff rewrites the generic build rules in Go. See https://github.com/ooni/probe/issues/2401. --- CLI/go-build-generic | 35 --------- MONOREPO/w/run-desktop-with-cli.bash | 2 +- Makefile | 8 +- internal/cmd/buildtool/generic.go | 62 +++++++++++++++ internal/cmd/buildtool/generic_test.go | 100 +++++++++++++++++++++++++ internal/cmd/buildtool/main.go | 1 + internal/cmd/buildtool/product.go | 6 -- 7 files changed, 168 insertions(+), 46 deletions(-) delete mode 100755 CLI/go-build-generic create mode 100644 internal/cmd/buildtool/generic.go create mode 100644 internal/cmd/buildtool/generic_test.go diff --git a/CLI/go-build-generic b/CLI/go-build-generic deleted file mode 100755 index 5281182190..0000000000 --- a/CLI/go-build-generic +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -if [[ $# -ne 1 ]]; then - echo "" 1>&2 - echo "Compiler for a Go PACKAGE producing GOOS/GOARCH binaries in the" 1>&2 - echo "top-level directory (should not be used for releasing)." 1>&2 - echo "" 1>&2 - echo "usage: $0 PACKAGE..." 1>&2 - echo "" 1>&2 - echo "Features:" 1>&2 - echo "" 1>&2 - echo "* automatically sets -tags=ooni_psiphon_config when possible;" 1>&2 - echo "" 1>&2 - echo "* if GOLANG_EXTRA_FLAGS is set, pass it to the Go compiler." 1>&2 - echo "" 1>&2 - echo "Example:" 1>&2 - echo "" 1>&2 - echo " ./CLI/go-build-generic ./internal/cmd/miniooni" 1>&2 - echo "" 1>&2 - exit 1 -fi - -if [[ -f ./internal/engine/psiphon-config.json.age && - -f ./internal/engine/psiphon-config.key ]]; then - OONI_PSIPHON_TAGS=ooni_psiphon_config -else - OONI_PSIPHON_TAGS="" -fi - -set -x -for pkg in "$@"; do - go build -tags=$OONI_PSIPHON_TAGS -ldflags="-s -w" ${GOLANG_EXTRA_FLAGS:-} $pkg -done diff --git a/MONOREPO/w/run-desktop-with-cli.bash b/MONOREPO/w/run-desktop-with-cli.bash index e8b06295be..6cc18572e0 100755 --- a/MONOREPO/w/run-desktop-with-cli.bash +++ b/MONOREPO/w/run-desktop-with-cli.bash @@ -30,7 +30,7 @@ arm64) ;; esac -run ./CLI/go-build-generic ./cmd/ooniprobe +run make CLI/ooniprobe run mkdir -p ./MONOREPO/repo/probe-desktop/build/probe-cli/${GOOS}_${GOARCH} run mv -v ooniprobe ./MONOREPO/repo/probe-desktop/build/probe-cli/${GOOS}_${GOARCH} ( diff --git a/Makefile b/Makefile index 4227309f90..a66900d562 100644 --- a/Makefile +++ b/Makefile @@ -130,15 +130,15 @@ CLI/linux-static-arm64: search/for/docker maybe/copypsiphon #help: The `make CLI/miniooni` command creates a build of miniooni, for the current #help: system, putting the binary in the top-level directory. .PHONY: CLI/miniooni -CLI/miniooni: maybe/copypsiphon search/for/go - ./CLI/go-build-generic ./internal/cmd/miniooni +CLI/miniooni: + go run ./internal/cmd/buildtool generic miniooni #help: #help: The `make CLI/ooniprobe` command creates a build of ooniprobe, for the current #help: system, putting the binary in the top-level directory. .PHONY: CLI/ooniprobe -CLI/ooniprobe: maybe/copypsiphon search/for/go - ./CLI/go-build-generic ./cmd/ooniprobe +CLI/ooniprobe: + go run ./internal/cmd/buildtool generic ooniprobe #help: #help: The `make CLI/windows` command builds the ooniprobe and miniooni diff --git a/internal/cmd/buildtool/generic.go b/internal/cmd/buildtool/generic.go new file mode 100644 index 0000000000..85b5c1ecba --- /dev/null +++ b/internal/cmd/buildtool/generic.go @@ -0,0 +1,62 @@ +package main + +// +// Generic builder for the current GOOS/GOARCH +// + +import ( + "runtime" + + "github.com/apex/log" + "github.com/ooni/probe-cli/v3/internal/cmd/buildtool/internal/buildtoolmodel" + "github.com/ooni/probe-cli/v3/internal/runtimex" + "github.com/ooni/probe-cli/v3/internal/shellx" + "github.com/spf13/cobra" +) + +// genericSubcommand returns the generic sucommand. +func genericSubcommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "generic", + Short: "Generic Go builder for the current GOOS and GOARCH", + } + cmd.AddCommand(&cobra.Command{ + Use: "miniooni", + Short: "Builds miniooni for the current GOOS and GOARCH", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + genericBuildPackage(&buildDeps{}, productMiniooni) + }, + }) + cmd.AddCommand(&cobra.Command{ + Use: "ooniprobe", + Short: "Builds ooniprobe for the current GOOS and GOARCH", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + genericBuildPackage(&buildDeps{}, productOoniprobe) + }, + }) + return cmd +} + +// genericBuildPackage is the generic function for building a package. +func genericBuildPackage(deps buildtoolmodel.Dependencies, product *product) { + deps.PsiphonMaybeCopyConfigFiles() + deps.GolangCheck() + + log.Infof("building %s for %s/%s", product.Pkg, runtime.GOOS, runtime.GOARCH) + + argv := runtimex.Try1(shellx.NewArgv("go", "build")) + if deps.PsiphonFilesExist() { + argv.Append("-tags", "ooni_psiphon_config") + } + argv.Append("-ldflags", "-s -w") + argv.Append(product.Pkg) + + config := &shellx.Config{ + Logger: log.Log, + Flags: shellx.FlagShowStdoutStderr, + } + + runtimex.Try0(shellx.RunEx(config, argv, &shellx.Envp{})) +} diff --git a/internal/cmd/buildtool/generic_test.go b/internal/cmd/buildtool/generic_test.go new file mode 100644 index 0000000000..b0fd16b49f --- /dev/null +++ b/internal/cmd/buildtool/generic_test.go @@ -0,0 +1,100 @@ +package main + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/ooni/probe-cli/v3/internal/cmd/buildtool/internal/buildtooltest" + "github.com/ooni/probe-cli/v3/internal/shellx/shellxtesting" +) + +func TestGenericBuildPackage(t *testing.T) { + + // testspec specifies a test case for this test + type testspec struct { + // name is the name of the test case + name string + + // product is the product to build + product *product + + // hasPsiphon indicates whether we should build with psiphon config + hasPsiphon bool + + // expectations contains the commands we expect to see + expect []buildtooltest.ExecExpectations + } + + var testcases = []testspec{{ + name: "miniooni build with psiphon", + product: productMiniooni, + hasPsiphon: true, + expect: []buildtooltest.ExecExpectations{{ + Env: []string{}, + Argv: []string{ + "go", "build", "-tags", "ooni_psiphon_config", + "-ldflags", "-s -w", "./internal/cmd/miniooni", + }, + }}, + }, { + name: "miniooni build without psiphon", + product: productMiniooni, + hasPsiphon: false, + expect: []buildtooltest.ExecExpectations{{ + Env: []string{}, + Argv: []string{ + "go", "build", "-ldflags", "-s -w", "./internal/cmd/miniooni", + }, + }}, + }, { + name: "ooniprobe build with psiphon", + product: productOoniprobe, + hasPsiphon: true, + expect: []buildtooltest.ExecExpectations{{ + Env: []string{}, + Argv: []string{ + "go", "build", "-tags", "ooni_psiphon_config", + "-ldflags", "-s -w", "./cmd/ooniprobe", + }, + }}, + }, { + name: "ooniprobe build without psiphon", + product: productOoniprobe, + hasPsiphon: false, + expect: []buildtooltest.ExecExpectations{{ + Env: []string{}, + Argv: []string{ + "go", "build", "-ldflags", "-s -w", "./cmd/ooniprobe", + }, + }}, + }} + + for _, testcase := range testcases { + t.Run(testcase.name, func(t *testing.T) { + + cc := &buildtooltest.SimpleCommandCollector{} + + deps := &buildtooltest.DependenciesCallCounter{ + HasPsiphon: testcase.hasPsiphon, + } + + shellxtesting.WithCustomLibrary(cc, func() { + genericBuildPackage(deps, testcase.product) + }) + + expectCalls := map[string]int{ + buildtooltest.TagGolangCheck: 1, + buildtooltest.TagPsiphonMaybeCopyConfigFiles: 1, + buildtooltest.TagPsiphonFilesExist: 1, + } + + if diff := cmp.Diff(expectCalls, deps.Counter); diff != "" { + t.Fatal(diff) + } + + if err := buildtooltest.CheckManyCommands(cc.Commands, testcase.expect); err != nil { + t.Fatal(err) + } + }) + } +} diff --git a/internal/cmd/buildtool/main.go b/internal/cmd/buildtool/main.go index 1871769e50..6227932f22 100644 --- a/internal/cmd/buildtool/main.go +++ b/internal/cmd/buildtool/main.go @@ -17,6 +17,7 @@ func main() { Short: "Tool for building ooniprobe, miniooni, etc.", } root.AddCommand(darwinSubcommand()) + root.AddCommand(genericSubcommand()) root.AddCommand(windowsSubcommand()) logHandler := logx.NewHandlerWithDefaultSettings() logHandler.Emoji = true diff --git a/internal/cmd/buildtool/product.go b/internal/cmd/buildtool/product.go index 8100d355dc..da8fb8a995 100644 --- a/internal/cmd/buildtool/product.go +++ b/internal/cmd/buildtool/product.go @@ -39,12 +39,6 @@ var productMiniooni = &product{ Kind: "CLI", } -// productOohelperd is the oohelperd product. -var productOohelperd = &product{ - Pkg: "./internal/cmd/oohelperd", - Kind: "CLI", -} - // productOoniprobe is the ooniprobe product. var productOoniprobe = &product{ Pkg: "./cmd/ooniprobe",