From f9caa129089da265ce761e9c26a9dd5548f682c9 Mon Sep 17 00:00:00 2001 From: Roger Standridge <9526806+archie2x@users.noreply.github.com> Date: Tue, 20 Aug 2024 09:06:11 -0700 Subject: [PATCH 1/4] Fix #4421: Add `-C DIR` flag Signed-off-by: Roger Standridge <9526806+archie2x@users.noreply.github.com> --- main.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/main.go b/main.go index 51e62aaaee..74db8785bd 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "regexp" "runtime" "runtime/pprof" + "slices" "sort" "strconv" "strings" @@ -1461,6 +1462,7 @@ func main() { // Early command processing, before commands are interpreted by the Go flag // library. + handleChdirFlag() switch command { case "clang", "ld.lld", "wasm-ld": err := builder.RunTool(command, os.Args[2:]...) @@ -1946,3 +1948,44 @@ type outputEntry struct { stderr bool data []byte } + +// handleChdirFlag handles the -C flag before doing anything else. +// The -C flag must be the first flag on the command line, to make it easy to find +// even with commands that have custom flag parsing. +// handleChdirFlag handles the flag by chdir'ing to the directory +// and then removing that flag from the command line entirely. +// +// We have to handle the -C flag this way for two reasons: +// +// 1. Toolchain selection needs to be in the right directory to look for go.mod and go.work. +// +// 2. A toolchain switch later on reinvokes the new go command with the same arguments. +// The parent toolchain has already done the chdir; the child must not try to do it again. +func handleChdirFlag() { + used := 2 // b.c. command at os.Args[1] + if used >= len(os.Args) { + return + } + + var dir string + switch a := os.Args[used]; { + default: + return + + case a == "-C", a == "--C": + if used+1 >= len(os.Args) { + return + } + dir = os.Args[used+1] + os.Args = slices.Delete(os.Args, used, used+2) + + case strings.HasPrefix(a, "-C="), strings.HasPrefix(a, "--C="): + _, dir, _ = strings.Cut(a, "=") + os.Args = slices.Delete(os.Args, used, used+1) + } + + if err := os.Chdir(dir); err != nil { + fmt.Fprintln(os.Stderr, "cannot chdir:", err) + os.Exit(1) + } +} From 628e10770588ebac872221ad2af214e3755ce911 Mon Sep 17 00:00:00 2001 From: Roger Standridge <9526806+archie2x@users.noreply.github.com> Date: Tue, 20 Aug 2024 10:19:23 -0700 Subject: [PATCH 2/4] Fix #4421 `-C DIR` support go1.19 Signed-off-by: Roger Standridge <9526806+archie2x@users.noreply.github.com> --- main.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 74db8785bd..227c869c94 100644 --- a/main.go +++ b/main.go @@ -16,7 +16,6 @@ import ( "regexp" "runtime" "runtime/pprof" - "slices" "sort" "strconv" "strings" @@ -1961,6 +1960,7 @@ type outputEntry struct { // // 2. A toolchain switch later on reinvokes the new go command with the same arguments. // The parent toolchain has already done the chdir; the child must not try to do it again. + func handleChdirFlag() { used := 2 // b.c. command at os.Args[1] if used >= len(os.Args) { @@ -1977,11 +1977,11 @@ func handleChdirFlag() { return } dir = os.Args[used+1] - os.Args = slices.Delete(os.Args, used, used+2) + os.Args = slicesDelete(os.Args, used, used+2) case strings.HasPrefix(a, "-C="), strings.HasPrefix(a, "--C="): _, dir, _ = strings.Cut(a, "=") - os.Args = slices.Delete(os.Args, used, used+1) + os.Args = slicesDelete(os.Args, used, used+1) } if err := os.Chdir(dir); err != nil { @@ -1989,3 +1989,14 @@ func handleChdirFlag() { os.Exit(1) } } + +// go1.19 compatibility: lacks slices package +func slicesDelete[S ~[]E, E any](s S, i, j int) S { + _ = s[i:j:len(s)] // bounds check + + if i == j { + return s + } + + return append(s[:i], s[j:]...) +} From 9c88472d326b2d9e01a897bf48489c17f19b1af7 Mon Sep 17 00:00:00 2001 From: Roger Standridge <9526806+archie2x@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:27:55 -0700 Subject: [PATCH 3/4] Fix #4421 add tests for 'build' and 'run' ('test' already changes directory) Signed-off-by: Roger Standridge <9526806+archie2x@users.noreply.github.com> --- GNUmakefile | 11 ++++++++++- tests/testing/chdir/chdir.go | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/testing/chdir/chdir.go diff --git a/GNUmakefile b/GNUmakefile index 7333a6ebc9..70a7c5f589 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -483,8 +483,17 @@ tinygo-baremetal: # regression test for #2666: e.g. encoding/hex must pass on baremetal $(TINYGO) test -target cortex-m-qemu encoding/hex +.PHONY: testchdir +testchdir: + # test 'build' command with{,out} -C argument + $(TINYGO) build -C tests/testing/chdir chdir.go && rm tests/testing/chdir/chdir + $(TINYGO) build ./tests/testing/chdir/chdir.go && rm chdir + # test 'run' command with{,out} -C argument + EXPECT_DIR=$(PWD)/tests/testing/chdir $(TINYGO) run -C tests/testing/chdir chdir.go + EXPECT_DIR=$(PWD) $(TINYGO) run ./tests/testing/chdir/chdir.go + .PHONY: smoketest -smoketest: +smoketest: testchdir $(TINYGO) version $(TINYGO) targets > /dev/null # regression test for #2892 diff --git a/tests/testing/chdir/chdir.go b/tests/testing/chdir/chdir.go new file mode 100644 index 0000000000..9539738503 --- /dev/null +++ b/tests/testing/chdir/chdir.go @@ -0,0 +1,27 @@ +package main + +import ( + "log" + "os" + "runtime" + "strings" +) + +/* +Test that this program is 'run' in expected directory. 'run' with expected +working-directory in 'EXPECT_DIR' environment variable' with{,out} a -C +argument. +*/ +func main() { + expectDir := os.Getenv("EXPECT_DIR") + cwd, err := os.Getwd() + if err != nil { + log.Fatal(err) + } + if runtime.GOOS == "windows" { + strings.Replace(cwd, "\\", "/", -1) + } + if cwd != expectDir { + log.Fatal("expected:\"%v\" != os.Getwd():\"%v\"", expectDir, cwd) + } +} From 21a6a9281453e838416487fdb68f07123973ece4 Mon Sep 17 00:00:00 2001 From: Roger Standridge <9526806+archie2x@users.noreply.github.com> Date: Wed, 11 Sep 2024 14:00:04 -0700 Subject: [PATCH 4/4] fix test --- tests/testing/chdir/chdir.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/testing/chdir/chdir.go b/tests/testing/chdir/chdir.go index 9539738503..75281c21f0 100644 --- a/tests/testing/chdir/chdir.go +++ b/tests/testing/chdir/chdir.go @@ -3,8 +3,8 @@ package main import ( "log" "os" + "path/filepath" "runtime" - "strings" ) /* @@ -19,9 +19,9 @@ func main() { log.Fatal(err) } if runtime.GOOS == "windows" { - strings.Replace(cwd, "\\", "/", -1) + cwd = filepath.ToSlash(cwd) } if cwd != expectDir { - log.Fatal("expected:\"%v\" != os.Getwd():\"%v\"", expectDir, cwd) + log.Fatalf("expected:\"%v\" != os.Getwd():\"%v\"", expectDir, cwd) } }