github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/go/toolchain/exec.go (about)

     1  // Copyright 2023 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  //go:build !js && !wasip1
     6  
     7  package toolchain
     8  
     9  import (
    10  	"os"
    11  	"os/exec"
    12  	"runtime"
    13  	"syscall"
    14  
    15  	"github.com/go-asm/go/cmd/go/base"
    16  	"github.com/go-asm/go/godebug"
    17  )
    18  
    19  // execGoToolchain execs the Go toolchain with the given name (gotoolchain),
    20  // GOROOT directory, and go command executable.
    21  // The GOROOT directory is empty if we are invoking a command named
    22  // gotoolchain found in $PATH.
    23  func execGoToolchain(gotoolchain, dir, exe string) {
    24  	os.Setenv(targetEnv, gotoolchain)
    25  	if dir == "" {
    26  		os.Unsetenv("GOROOT")
    27  	} else {
    28  		os.Setenv("GOROOT", dir)
    29  	}
    30  
    31  	// On Windows, there is no syscall.Exec, so the best we can do
    32  	// is run a subprocess and exit with the same status.
    33  	// Doing the same on Unix would be a problem because it wouldn't
    34  	// propagate signals and such, but there are no signals on Windows.
    35  	// We also use the exec case when GODEBUG=gotoolchainexec=0,
    36  	// to allow testing this code even when not on Windows.
    37  	if godebug.New("#gotoolchainexec").Value() == "0" || runtime.GOOS == "windows" {
    38  		cmd := exec.Command(exe, os.Args[1:]...)
    39  		cmd.Stdin = os.Stdin
    40  		cmd.Stdout = os.Stdout
    41  		cmd.Stderr = os.Stderr
    42  		err := cmd.Run()
    43  		if err != nil {
    44  			if e, ok := err.(*exec.ExitError); ok && e.ProcessState != nil {
    45  				if e.ProcessState.Exited() {
    46  					os.Exit(e.ProcessState.ExitCode())
    47  				}
    48  				base.Fatalf("exec %s: %s", gotoolchain, e.ProcessState)
    49  			}
    50  			base.Fatalf("exec %s: %s", exe, err)
    51  		}
    52  		os.Exit(0)
    53  	}
    54  	err := syscall.Exec(exe, os.Args, os.Environ())
    55  	base.Fatalf("exec %s: %v", gotoolchain, err)
    56  }