From 53ebde225e0ecaff8c3b71356a4726fad753d47c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 1 Feb 2016 12:22:39 -0500 Subject: [PATCH] cmd/cgo: do not use gcc -xc - to compile standard input We have private reports of compilers that mishandle that. Write to a temporary file instead. Change-Id: I92e3cf4274b1a8048741e07fb52b8900c93b915e Reviewed-on: https://go-review.googlesource.com/19616 Reviewed-by: Ian Lance Taylor --- src/cmd/cgo/util.go | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go index 3adb8e8783..52ca160ad9 100644 --- a/src/cmd/cgo/util.go +++ b/src/cmd/cgo/util.go @@ -8,6 +8,7 @@ import ( "bytes" "fmt" "go/token" + "io/ioutil" "os" "os/exec" ) @@ -16,6 +17,43 @@ import ( // It returns the output to standard output and standard error. // ok indicates whether the command exited successfully. func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) { + if i := find(argv, "-xc"); i >= 0 && argv[len(argv)-1] == "-" { + // Some compilers have trouble with standard input. + // Others have trouble with -xc. + // Avoid both problems by writing a file with a .c extension. + f, err := ioutil.TempFile("", "cgo-gcc-input-") + if err != nil { + fatalf("%s", err) + } + name := f.Name() + f.Close() + if err := ioutil.WriteFile(name+".c", stdin, 0666); err != nil { + os.Remove(name) + fatalf("%s", err) + } + defer os.Remove(name) + defer os.Remove(name + ".c") + + // Build new argument list without -xc and trailing -. + new := append(argv[:i:i], argv[i+1:len(argv)-1]...) + + // Since we are going to write the file to a temporary directory, + // we will need to add -I . explicitly to the command line: + // any #include "foo" before would have looked in the current + // directory as the directory "holding" standard input, but now + // the temporary directory holds the input. + // We've also run into compilers that reject "-I." but allow "-I", ".", + // so be sure to use two arguments. + // This matters mainly for people invoking cgo -godefs by hand. + new = append(new, "-I", ".") + + // Finish argument list with path to C file. + new = append(new, name+".c") + + argv = new + stdin = nil + } + p := exec.Command(argv[0], argv[1:]...) p.Stdin = bytes.NewReader(stdin) var bout, berr bytes.Buffer @@ -30,6 +68,15 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) { return } +func find(argv []string, target string) int { + for i, arg := range argv { + if arg == target { + return i + } + } + return -1 +} + func lineno(pos token.Pos) string { return fset.Position(pos).String() }