From c761d102ea5c76bc955fdb2d0ac56c8096e86466 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 5 Oct 2023 16:43:09 -0700 Subject: [PATCH] tool/gocross: don't absorb --tags flags passed to subcommand Fixes tailscale/corp#15117 Signed-off-by: David Anderson --- tool/gocross/autoflags.go | 13 +++++++-- tool/gocross/autoflags_test.go | 48 +++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/tool/gocross/autoflags.go b/tool/gocross/autoflags.go index ee60c3155..10c977b32 100644 --- a/tool/gocross/autoflags.go +++ b/tool/gocross/autoflags.go @@ -166,7 +166,7 @@ func autoflagsForTest(argv []string, env *Environment, goroot, nativeGOOS, nativ // commandline and environment modifications. newArgv = append(newArgv, argv[:2]...) // Program name and `go` tool subcommand - filteredArgvPostSubcmd, originalTags := extractTags(argv[2:]) + filteredArgvPostSubcmd, originalTags := extractTags(argv[1], argv[2:]) newArgv = append(newArgv, buildFlags...) tags = append(tags, originalTags...) @@ -201,7 +201,7 @@ func autoflagsForTest(argv []string, env *Environment, goroot, nativeGOOS, nativ // 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) { +func extractTags(gocmd string, v []string) (filtered, tags []string) { for len(v) > 0 { e := v[0] if strings.HasPrefix(e, "--tags=") { @@ -225,6 +225,15 @@ func extractTags(v []string) (filtered, tags []string) { } continue } + if gocmd == "run" && !strings.HasPrefix(e, "-") { + // go run can include arguments to pass to the program + // being run. They all appear after the name of the + // package or Go file to run, so when we hit the first + // non-flag positional argument, stop extracting tags and + // wrap up. + filtered = append(filtered, v...) + break + } filtered = append(filtered, e) v = v[1:] } diff --git a/tool/gocross/autoflags_test.go b/tool/gocross/autoflags_test.go index 7c2838157..e5202efc9 100644 --- a/tool/gocross/autoflags_test.go +++ b/tool/gocross/autoflags_test.go @@ -416,6 +416,33 @@ TS_LINK_FAIL_REFLECT=0 (was )`, "./cmd/tailcontrol", }, }, + { + name: "linux_amd64_to_linux_amd64_go_run_tags", + + argv: []string{"go", "run", "./cmd/mkctr", "--tags=foo"}, + goroot: "/goroot", + nativeGOOS: "linux", + nativeGOARCH: "amd64", + + envDiff: `CC=cc (was ) +CGO_CFLAGS=-O3 -std=gnu11 (was ) +CGO_ENABLED=1 (was ) +CGO_LDFLAGS= (was ) +GOARCH=amd64 (was ) +GOARM=5 (was ) +GOMIPS=softfloat (was ) +GOOS=linux (was ) +GOROOT=/goroot (was ) +TS_LINK_FAIL_REFLECT=0 (was )`, + wantArgv: []string{ + "go", "run", + "-trimpath", + "-tags=tailscale_go,osusergo,netgo", + "-ldflags", "-X tailscale.com/version.longStamp=1.2.3-long -X tailscale.com/version.shortStamp=1.2.3 -X tailscale.com/version.gitCommitStamp=abcd -X tailscale.com/version.extraGitCommitStamp=defg '-extldflags=-static'", + "./cmd/mkctr", + "--tags=foo", + }, + }, } for _, test := range tests { @@ -442,61 +469,76 @@ func TestExtractTags(t *testing.T) { s := func(ss ...string) []string { return ss } tests := []struct { name string + cmd string in []string filt []string // want filtered tags []string // want tags }{ { name: "one_hyphen_tags", + cmd: "build", in: s("foo", "-tags=a,b", "bar"), filt: s("foo", "bar"), tags: s("a", "b"), }, { name: "two_hyphen_tags", + cmd: "build", in: s("foo", "--tags=a,b", "bar"), filt: s("foo", "bar"), tags: s("a", "b"), }, { name: "one_hypen_separate_arg", + cmd: "build", in: s("foo", "-tags", "a,b", "bar"), filt: s("foo", "bar"), tags: s("a", "b"), }, { name: "two_hypen_separate_arg", + cmd: "build", in: s("foo", "--tags", "a,b", "bar"), filt: s("foo", "bar"), tags: s("a", "b"), }, { name: "equal_empty", + cmd: "build", in: s("foo", "--tags=", "bar"), filt: s("foo", "bar"), tags: s(), }, { name: "arg_empty", + cmd: "build", in: s("foo", "--tags", "", "bar"), filt: s("foo", "bar"), tags: s(), }, { name: "arg_empty_truncated", + cmd: "build", in: s("foo", "--tags"), filt: s("foo"), tags: s(), }, + { + name: "go_run_with_program_tags", + cmd: "run", + in: s("--foo", "--tags", "bar", "my/package/name", "--tags", "qux"), + filt: s("--foo", "my/package/name", "--tags", "qux"), + tags: s("bar"), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - filt, tags := extractTags(tt.in) + filt, tags := extractTags(tt.cmd, tt.in) if !reflect.DeepEqual(filt, tt.filt) { - t.Errorf("extractTags(%q) filtered = %q; want %q", tt.in, filt, tt.filt) + t.Errorf("extractTags(%q, %q) filtered = %q; want %q", tt.cmd, tt.in, filt, tt.filt) } if !reflect.DeepEqual(tags, tt.tags) { - t.Errorf("extractTags(%q) tags = %q; want %q", tt.in, tags, tt.tags) + t.Errorf("extractTags(%q, %q) tags = %q; want %q", tt.cmd, tt.in, tags, tt.tags) } }) }