From efac2cb8d672670b7411dcb68e4e4357d5abdd7c Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 3 Oct 2023 12:38:40 -0700 Subject: [PATCH] tool/gocross: merge user's build tags and implicitly added build tags together Fixes tailscale/corp#15058 Change-Id: I7e539b3324153077597f30385a2cb540846e8bdc Signed-off-by: Brad Fitzpatrick --- tool/gocross/autoflags.go | 39 ++++++++++++++++++++- tool/gocross/autoflags_test.go | 64 ++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/tool/gocross/autoflags.go b/tool/gocross/autoflags.go index fc4ae6a5b..c2f15766e 100644 --- a/tool/gocross/autoflags.go +++ b/tool/gocross/autoflags.go @@ -169,14 +169,18 @@ func autoflagsForTest(argv []string, env *Environment, goroot, nativeGOOS, nativ // Finished computing the settings we want. Generate the modified // commandline and environment modifications. newArgv = append(newArgv, argv[:2]...) // Program name and `go` tool subcommand + + filteredArgvPostSubcmd, originalTags := extractTags(argv[2:]) + newArgv = append(newArgv, buildFlags...) + tags = append(tags, originalTags...) if len(tags) > 0 { newArgv = append(newArgv, fmt.Sprintf("-tags=%s", strings.Join(tags, ","))) } if len(ldflags) > 0 { newArgv = append(newArgv, "-ldflags", strings.Join(ldflags, " ")) } - newArgv = append(newArgv, argv[2:]...) + newArgv = append(newArgv, filteredArgvPostSubcmd...) env.Set("GOOS", targetOS) env.Set("GOARCH", targetArch) @@ -198,6 +202,39 @@ func autoflagsForTest(argv []string, env *Environment, goroot, nativeGOOS, nativ return newArgv, env, nil } +// extractTags parses out "-tags=foo,bar" (or double hyphen or "-tags", +// "foo,bar") in its various forms and returns v filtered to remove the 0, 1 or +// 2 build tag elements, then the tags parsed, split on commas ("foo", "bar"). +func extractTags(v []string) (filtered, tags []string) { + for len(v) > 0 { + e := v[0] + if strings.HasPrefix(e, "--tags=") { + e = e[1:] // remove one of the hyphens for the next line + } + if suf, ok := strings.CutPrefix(e, "-tags="); ok { + v = v[1:] + if suf != "" { + tags = strings.Split(suf, ",") + } + continue + } + if e == "-tags" || e == "--tags" { + v = v[1:] + if len(v) > 0 { + tagStr := v[0] + v = v[1:] + if tagStr != "" { + tags = strings.Split(tagStr, ",") + } + } + continue + } + filtered = append(filtered, e) + v = v[1:] + } + return filtered, tags +} + // boolStr formats v as a string 0 or 1. // Used because CGO_ENABLED doesn't strconv.ParseBool, so // strconv.FormatBool breaks. diff --git a/tool/gocross/autoflags_test.go b/tool/gocross/autoflags_test.go index c8007c40d..7c2838157 100644 --- a/tool/gocross/autoflags_test.go +++ b/tool/gocross/autoflags_test.go @@ -437,3 +437,67 @@ TS_LINK_FAIL_REFLECT=0 (was )`, }) } } + +func TestExtractTags(t *testing.T) { + s := func(ss ...string) []string { return ss } + tests := []struct { + name string + in []string + filt []string // want filtered + tags []string // want tags + }{ + { + name: "one_hyphen_tags", + in: s("foo", "-tags=a,b", "bar"), + filt: s("foo", "bar"), + tags: s("a", "b"), + }, + { + name: "two_hyphen_tags", + in: s("foo", "--tags=a,b", "bar"), + filt: s("foo", "bar"), + tags: s("a", "b"), + }, + { + name: "one_hypen_separate_arg", + in: s("foo", "-tags", "a,b", "bar"), + filt: s("foo", "bar"), + tags: s("a", "b"), + }, + { + name: "two_hypen_separate_arg", + in: s("foo", "--tags", "a,b", "bar"), + filt: s("foo", "bar"), + tags: s("a", "b"), + }, + { + name: "equal_empty", + in: s("foo", "--tags=", "bar"), + filt: s("foo", "bar"), + tags: s(), + }, + { + name: "arg_empty", + in: s("foo", "--tags", "", "bar"), + filt: s("foo", "bar"), + tags: s(), + }, + { + name: "arg_empty_truncated", + in: s("foo", "--tags"), + filt: s("foo"), + tags: s(), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + filt, tags := extractTags(tt.in) + if !reflect.DeepEqual(filt, tt.filt) { + t.Errorf("extractTags(%q) filtered = %q; want %q", tt.in, filt, tt.filt) + } + if !reflect.DeepEqual(tags, tt.tags) { + t.Errorf("extractTags(%q) tags = %q; want %q", tt.in, tags, tt.tags) + } + }) + } +}