Source file src/cmd/cgo/util.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"go/token"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"slices"
    15  )
    16  
    17  // run runs the command argv, feeding in stdin on standard input.
    18  // It returns the output to standard output and standard error.
    19  // ok indicates whether the command exited successfully.
    20  func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
    21  	if i := slices.Index(argv, "-xc"); i >= 0 && argv[len(argv)-1] == "-" {
    22  		// Some compilers have trouble with standard input.
    23  		// Others have trouble with -xc.
    24  		// Avoid both problems by writing a file with a .c extension.
    25  		f, err := os.CreateTemp("", "cgo-gcc-input-")
    26  		if err != nil {
    27  			fatalf("%s", err)
    28  		}
    29  		name := f.Name()
    30  		f.Close()
    31  		if err := os.WriteFile(name+".c", stdin, 0666); err != nil {
    32  			os.Remove(name)
    33  			fatalf("%s", err)
    34  		}
    35  		defer os.Remove(name)
    36  		defer os.Remove(name + ".c")
    37  
    38  		// Build new argument list without -xc and trailing -.
    39  		new := append(argv[:i:i], argv[i+1:len(argv)-1]...)
    40  
    41  		// Since we are going to write the file to a temporary directory,
    42  		// we will need to add -I . explicitly to the command line:
    43  		// any #include "foo" before would have looked in the current
    44  		// directory as the directory "holding" standard input, but now
    45  		// the temporary directory holds the input.
    46  		// We've also run into compilers that reject "-I." but allow "-I", ".",
    47  		// so be sure to use two arguments.
    48  		// This matters mainly for people invoking cgo -godefs by hand.
    49  		new = append(new, "-I", ".")
    50  
    51  		// Finish argument list with path to C file.
    52  		new = append(new, name+".c")
    53  
    54  		argv = new
    55  		stdin = nil
    56  	}
    57  
    58  	p := exec.Command(argv[0], argv[1:]...)
    59  	p.Stdin = bytes.NewReader(stdin)
    60  	var bout, berr bytes.Buffer
    61  	p.Stdout = &bout
    62  	p.Stderr = &berr
    63  	// Disable escape codes in clang error messages.
    64  	p.Env = append(os.Environ(), "TERM=dumb")
    65  	err := p.Run()
    66  	if _, ok := err.(*exec.ExitError); err != nil && !ok {
    67  		fatalf("exec %s: %s", argv[0], err)
    68  	}
    69  	ok = p.ProcessState.Success()
    70  	stdout, stderr = bout.Bytes(), berr.Bytes()
    71  	return
    72  }
    73  
    74  func lineno(pos token.Pos) string {
    75  	return fset.Position(pos).String()
    76  }
    77  
    78  // Die with an error message.
    79  func fatalf(msg string, args ...any) {
    80  	// If we've already printed other errors, they might have
    81  	// caused the fatal condition. Assume they're enough.
    82  	if nerrors == 0 {
    83  		fmt.Fprintf(os.Stderr, "cgo: "+msg+"\n", args...)
    84  	}
    85  	os.Exit(2)
    86  }
    87  
    88  var nerrors int
    89  
    90  func error_(pos token.Pos, msg string, args ...any) {
    91  	nerrors++
    92  	if pos.IsValid() {
    93  		fmt.Fprintf(os.Stderr, "%s: ", fset.Position(pos).String())
    94  	} else {
    95  		fmt.Fprintf(os.Stderr, "cgo: ")
    96  	}
    97  	fmt.Fprintf(os.Stderr, msg, args...)
    98  	fmt.Fprintf(os.Stderr, "\n")
    99  }
   100  
   101  // create creates a file in the output directory.
   102  func creat(name string) *os.File {
   103  	f, err := os.Create(filepath.Join(outputDir(), name))
   104  	if err != nil {
   105  		fatalf("%s", err)
   106  	}
   107  	return f
   108  }
   109  
   110  // outputDir returns the output directory, making sure that it exists.
   111  func outputDir() string {
   112  	os.MkdirAll(*objDir, 0o700)
   113  	return *objDir
   114  }
   115  

View as plain text