Skip to content

Commit 5abf1e9

Browse files
authored
Fix #4421: Add -C DIR flag (#4422)
feature: Fix #4421: Add `-C DIR` flag Signed-off-by: Roger Standridge <[email protected]>
1 parent b5626e7 commit 5abf1e9

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed

GNUmakefile

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,17 @@ tinygo-baremetal:
483483
# regression test for #2666: e.g. encoding/hex must pass on baremetal
484484
$(TINYGO) test -target cortex-m-qemu encoding/hex
485485

486+
.PHONY: testchdir
487+
testchdir:
488+
# test 'build' command with{,out} -C argument
489+
$(TINYGO) build -C tests/testing/chdir chdir.go && rm tests/testing/chdir/chdir
490+
$(TINYGO) build ./tests/testing/chdir/chdir.go && rm chdir
491+
# test 'run' command with{,out} -C argument
492+
EXPECT_DIR=$(PWD)/tests/testing/chdir $(TINYGO) run -C tests/testing/chdir chdir.go
493+
EXPECT_DIR=$(PWD) $(TINYGO) run ./tests/testing/chdir/chdir.go
494+
486495
.PHONY: smoketest
487-
smoketest:
496+
smoketest: testchdir
488497
$(TINYGO) version
489498
$(TINYGO) targets > /dev/null
490499
# regression test for #2892

main.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,7 @@ func main() {
14611461

14621462
// Early command processing, before commands are interpreted by the Go flag
14631463
// library.
1464+
handleChdirFlag()
14641465
switch command {
14651466
case "clang", "ld.lld", "wasm-ld":
14661467
err := builder.RunTool(command, os.Args[2:]...)
@@ -1946,3 +1947,56 @@ type outputEntry struct {
19461947
stderr bool
19471948
data []byte
19481949
}
1950+
1951+
// handleChdirFlag handles the -C flag before doing anything else.
1952+
// The -C flag must be the first flag on the command line, to make it easy to find
1953+
// even with commands that have custom flag parsing.
1954+
// handleChdirFlag handles the flag by chdir'ing to the directory
1955+
// and then removing that flag from the command line entirely.
1956+
//
1957+
// We have to handle the -C flag this way for two reasons:
1958+
//
1959+
// 1. Toolchain selection needs to be in the right directory to look for go.mod and go.work.
1960+
//
1961+
// 2. A toolchain switch later on reinvokes the new go command with the same arguments.
1962+
// The parent toolchain has already done the chdir; the child must not try to do it again.
1963+
1964+
func handleChdirFlag() {
1965+
used := 2 // b.c. command at os.Args[1]
1966+
if used >= len(os.Args) {
1967+
return
1968+
}
1969+
1970+
var dir string
1971+
switch a := os.Args[used]; {
1972+
default:
1973+
return
1974+
1975+
case a == "-C", a == "--C":
1976+
if used+1 >= len(os.Args) {
1977+
return
1978+
}
1979+
dir = os.Args[used+1]
1980+
os.Args = slicesDelete(os.Args, used, used+2)
1981+
1982+
case strings.HasPrefix(a, "-C="), strings.HasPrefix(a, "--C="):
1983+
_, dir, _ = strings.Cut(a, "=")
1984+
os.Args = slicesDelete(os.Args, used, used+1)
1985+
}
1986+
1987+
if err := os.Chdir(dir); err != nil {
1988+
fmt.Fprintln(os.Stderr, "cannot chdir:", err)
1989+
os.Exit(1)
1990+
}
1991+
}
1992+
1993+
// go1.19 compatibility: lacks slices package
1994+
func slicesDelete[S ~[]E, E any](s S, i, j int) S {
1995+
_ = s[i:j:len(s)] // bounds check
1996+
1997+
if i == j {
1998+
return s
1999+
}
2000+
2001+
return append(s[:i], s[j:]...)
2002+
}

tests/testing/chdir/chdir.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"os"
6+
"path/filepath"
7+
"runtime"
8+
)
9+
10+
/*
11+
Test that this program is 'run' in expected directory. 'run' with expected
12+
working-directory in 'EXPECT_DIR' environment variable' with{,out} a -C
13+
argument.
14+
*/
15+
func main() {
16+
expectDir := os.Getenv("EXPECT_DIR")
17+
cwd, err := os.Getwd()
18+
if err != nil {
19+
log.Fatal(err)
20+
}
21+
if runtime.GOOS == "windows" {
22+
cwd = filepath.ToSlash(cwd)
23+
}
24+
if cwd != expectDir {
25+
log.Fatalf("expected:\"%v\" != os.Getwd():\"%v\"", expectDir, cwd)
26+
}
27+
}

0 commit comments

Comments
 (0)