main: add fallback mechanism for LLVM commands

On Debian, all LLVM commands have a version suffix (clang-8, ld.lld-8,
wasm-ld-8, etc.). However. Most other distributions only provide a
version prefix for Clang and not for all the other commands.

This commit fixes the issue by trying the command with the version
suffix first and falling back to one without if needed.
This commit is contained in:
Ayke van Laethem
2019-05-03 19:30:54 +02:00
committed by Ron Evans
parent 9a54ee4241
commit 9cad8bd0c8
7 changed files with 51 additions and 46 deletions
+3 -7
View File
@@ -5,7 +5,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
@@ -192,13 +191,13 @@ func loadBuiltins(target string) (path string, err error) {
srcs[i] = filepath.Join(builtinsDir, name) srcs[i] = filepath.Join(builtinsDir, name)
} }
if path, err := cacheLoad(outfile, commands["clang"], srcs); path != "" || err != nil { if path, err := cacheLoad(outfile, commands["clang"][0], srcs); path != "" || err != nil {
return path, err return path, err
} }
var cachepath string var cachepath string
err = compileBuiltins(target, func(path string) error { err = compileBuiltins(target, func(path string) error {
path, err := cacheStore(path, outfile, commands["clang"], srcs) path, err := cacheStore(path, outfile, commands["clang"][0], srcs)
cachepath = path cachepath = path
return err return err
}) })
@@ -240,10 +239,7 @@ func compileBuiltins(target string, callback func(path string) error) error {
// Note: -fdebug-prefix-map is necessary to make the output archive // Note: -fdebug-prefix-map is necessary to make the output archive
// reproducible. Otherwise the temporary directory is stored in the // reproducible. Otherwise the temporary directory is stored in the
// archive itself, which varies each run. // archive itself, which varies each run.
cmd := exec.Command(commands["clang"], "-c", "-Oz", "-g", "-Werror", "-Wall", "-std=c11", "-fshort-enums", "-nostdlibinc", "-ffunction-sections", "-fdata-sections", "--target="+target, "-fdebug-prefix-map="+dir+"="+remapDir, "-o", objpath, srcpath) err := execCommand(commands["clang"], "-c", "-Oz", "-g", "-Werror", "-Wall", "-std=c11", "-fshort-enums", "-nostdlibinc", "-ffunction-sections", "-fdata-sections", "--target="+target, "-fdebug-prefix-map="+dir+"="+remapDir, "-o", objpath, srcpath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil { if err != nil {
return &commandError{"failed to build", srcpath, err} return &commandError{"failed to build", srcpath, err}
} }
+30 -7
View File
@@ -1,10 +1,33 @@
// +build !darwin
package main package main
// commands used by the compilation process might have different file names on Linux than those used on macOS. import (
var commands = map[string]string{ "errors"
"clang": "clang-8", "os"
"ld.lld": "ld.lld-8", "os/exec"
"wasm-ld": "wasm-ld-8", "strings"
)
// Commands used by the compilation process might have different file names
// across operating systems and distributions.
var commands = map[string][]string{
"clang": {"clang-8"},
"ld.lld": {"ld.lld-8", "ld.lld"},
"wasm-ld": {"wasm-ld-8", "wasm-ld"},
}
func execCommand(cmdNames []string, args ...string) error {
for _, cmdName := range cmdNames {
cmd := exec.Command(cmdName, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
if err, ok := err.(*exec.Error); ok && err.Err == exec.ErrNotFound {
// this command was not found, try the next
continue
}
}
return nil
}
return errors.New("none of these commands were found in your $PATH: " + strings.Join(cmdNames, " "))
} }
-10
View File
@@ -1,10 +0,0 @@
// +build darwin
package main
// commands used by the compilation process might have different file names on macOS than those used on Linux.
var commands = map[string]string{
"clang": "clang-8",
"ld.lld": "ld.lld",
"wasm-ld": "wasm-ld",
}
+5 -2
View File
@@ -24,7 +24,7 @@ import "C"
// This version uses the built-in linker when trying to use lld. // This version uses the built-in linker when trying to use lld.
func Link(linker string, flags ...string) error { func Link(linker string, flags ...string) error {
switch linker { switch linker {
case "ld.lld", commands["ld.lld"]: case "ld.lld":
flags = append([]string{"tinygo:" + linker}, flags...) flags = append([]string{"tinygo:" + linker}, flags...)
var cflag *C.char var cflag *C.char
buf := C.calloc(C.size_t(len(flags)), C.size_t(unsafe.Sizeof(cflag))) buf := C.calloc(C.size_t(len(flags)), C.size_t(unsafe.Sizeof(cflag)))
@@ -39,7 +39,7 @@ func Link(linker string, flags ...string) error {
return errors.New("failed to link using built-in ld.lld") return errors.New("failed to link using built-in ld.lld")
} }
return nil return nil
case "wasm-ld", commands["wasm-ld"]: case "wasm-ld":
flags = append([]string{"tinygo:" + linker}, flags...) flags = append([]string{"tinygo:" + linker}, flags...)
var cflag *C.char var cflag *C.char
buf := C.calloc(C.size_t(len(flags)), C.size_t(unsafe.Sizeof(cflag))) buf := C.calloc(C.size_t(len(flags)), C.size_t(unsafe.Sizeof(cflag)))
@@ -57,6 +57,9 @@ func Link(linker string, flags ...string) error {
return nil return nil
default: default:
// Fall back to external command. // Fall back to external command.
if cmdNames, ok := commands[linker]; ok {
return execCommand(cmdNames, flags...)
}
cmd := exec.Command(linker, flags...) cmd := exec.Command(linker, flags...)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
+3
View File
@@ -14,6 +14,9 @@ import (
// //
// This version always runs the linker as an external command. // This version always runs the linker as an external command.
func Link(linker string, flags ...string) error { func Link(linker string, flags ...string) error {
if cmdNames, ok := commands[linker]; ok {
return execCommand(cmdNames, flags...)
}
cmd := exec.Command(linker, flags...) cmd := exec.Command(linker, flags...)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
+9 -19
View File
@@ -222,14 +222,11 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
for i, path := range spec.ExtraFiles { for i, path := range spec.ExtraFiles {
abspath := filepath.Join(root, path) abspath := filepath.Join(root, path)
outpath := filepath.Join(dir, "extra-"+strconv.Itoa(i)+"-"+filepath.Base(path)+".o") outpath := filepath.Join(dir, "extra-"+strconv.Itoa(i)+"-"+filepath.Base(path)+".o")
cmdName := spec.Compiler cmdNames := []string{spec.Compiler}
if name, ok := commands[cmdName]; ok { if names, ok := commands[spec.Compiler]; ok {
cmdName = name cmdNames = names
} }
cmd := exec.Command(cmdName, append(cflags, "-c", "-o", outpath, abspath)...) err := execCommand(cmdNames, append(cflags, "-c", "-o", outpath, abspath)...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil { if err != nil {
return &commandError{"failed to build", path, err} return &commandError{"failed to build", path, err}
} }
@@ -241,14 +238,11 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
for _, file := range pkg.CFiles { for _, file := range pkg.CFiles {
path := filepath.Join(pkg.Package.Dir, file) path := filepath.Join(pkg.Package.Dir, file)
outpath := filepath.Join(dir, "pkg"+strconv.Itoa(i)+"-"+file+".o") outpath := filepath.Join(dir, "pkg"+strconv.Itoa(i)+"-"+file+".o")
cmdName := spec.Compiler cmdNames := []string{spec.Compiler}
if name, ok := commands[cmdName]; ok { if names, ok := commands[spec.Compiler]; ok {
cmdName = name cmdNames = names
} }
cmd := exec.Command(cmdName, append(cflags, "-c", "-o", outpath, path)...) err := execCommand(cmdNames, append(cflags, "-c", "-o", outpath, path)...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil { if err != nil {
return &commandError{"failed to build", path, err} return &commandError{"failed to build", path, err}
} }
@@ -257,11 +251,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
} }
// Link the object files together. // Link the object files together.
if linker, ok := commands[spec.Linker]; ok { err = Link(spec.Linker, ldflags...)
err = Link(linker, ldflags...)
} else {
err = Link(spec.Linker, ldflags...)
}
if err != nil { if err != nil {
return &commandError{"failed to link", executable, err} return &commandError{"failed to link", executable, err}
} }
+1 -1
View File
@@ -211,7 +211,7 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
GOOS: goos, GOOS: goos,
GOARCH: goarch, GOARCH: goarch,
BuildTags: []string{goos, goarch}, BuildTags: []string{goos, goarch},
Compiler: commands["clang"], Compiler: "clang",
Linker: "cc", Linker: "cc",
GDB: "gdb", GDB: "gdb",
GDBCmds: []string{"run"}, GDBCmds: []string{"run"},