
This is necessary because LLVM defines many options in global variables that are modified when invoking Clang. In particular, LLVM 10 seems to have a bug in which it always sets the -pgo-warn-misexpect flag. Setting it multiple times (over various cc1 invocations) results in an error: clang (LLVM option parsing): for the --pgo-warn-misexpect option: may only occur zero or one times! This is fixed by running the Clang invocation in a new `tinygo` invocation. Because we've had issues with lld in the past, also run lld in a separate process so similar issues won't happen with lld in the future.
59 строки
1,6 КиБ
Go
59 строки
1,6 КиБ
Go
package builder
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"os/exec"
|
|
|
|
"github.com/tinygo-org/tinygo/goenv"
|
|
)
|
|
|
|
// runCCompiler invokes a C compiler with the given arguments.
|
|
func runCCompiler(command string, flags ...string) error {
|
|
if hasBuiltinTools && command == "clang" {
|
|
// Compile this with the internal Clang compiler.
|
|
headerPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
|
if headerPath == "" {
|
|
return errors.New("could not locate Clang headers")
|
|
}
|
|
flags = append(flags, "-I"+headerPath)
|
|
cmd := exec.Command(os.Args[0], append([]string{"clang"}, flags...)...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
return cmd.Run()
|
|
}
|
|
|
|
// Running some other compiler. Maybe it has been defined in the
|
|
// commands map (unlikely).
|
|
if cmdNames, ok := commands[command]; ok {
|
|
return execCommand(cmdNames, flags...)
|
|
}
|
|
|
|
// Alternatively, run the compiler directly.
|
|
cmd := exec.Command(command, flags...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
return cmd.Run()
|
|
}
|
|
|
|
// link invokes a linker with the given name and flags.
|
|
func link(linker string, flags ...string) error {
|
|
if hasBuiltinTools && (linker == "ld.lld" || linker == "wasm-ld") {
|
|
// Run command with internal linker.
|
|
cmd := exec.Command(os.Args[0], append([]string{linker}, flags...)...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
return cmd.Run()
|
|
}
|
|
|
|
// Fall back to external command.
|
|
if cmdNames, ok := commands[linker]; ok {
|
|
return execCommand(cmdNames, flags...)
|
|
}
|
|
|
|
cmd := exec.Command(linker, flags...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Dir = goenv.Get("TINYGOROOT")
|
|
return cmd.Run()
|
|
}
|