diff --git a/builder/env.go b/builder/env.go index 91bc2633..5fec0d82 100644 --- a/builder/env.go +++ b/builder/env.go @@ -6,6 +6,9 @@ import ( "os/exec" "path/filepath" "sort" + "strings" + + "tinygo.org/x/go-llvm" ) // getClangHeaderPath returns the path to the built-in Clang headers. It tries @@ -26,6 +29,7 @@ func getClangHeaderPath(TINYGOROOT string) string { // It looks like we are built with a system-installed LLVM. Do a last // attempt: try to use Clang headers relative to the clang binary. + llvmMajor := strings.Split(llvm.Version, ".")[0] for _, cmdName := range commands["clang"] { binpath, err := exec.LookPath(cmdName) if err == nil { @@ -43,25 +47,35 @@ func getClangHeaderPath(TINYGOROOT string) string { // /usr/lib/llvm-9/lib64/clang/9.0.1/include/ llvmRoot := filepath.Dir(filepath.Dir(binpath)) clangVersionRoot := filepath.Join(llvmRoot, "lib64", "clang") - dirs, err := ioutil.ReadDir(clangVersionRoot) - if err != nil { - // Example include path: - // /usr/lib/llvm-9/lib/clang/9.0.1/include/ - clangVersionRoot = filepath.Join(llvmRoot, "lib", "clang") - dirs, err = ioutil.ReadDir(clangVersionRoot) - if err != nil { - // Unexpected. - continue + dirs64, err64 := ioutil.ReadDir(clangVersionRoot) + // Example include path: + // /usr/lib/llvm-9/lib/clang/9.0.1/include/ + clangVersionRoot = filepath.Join(llvmRoot, "lib", "clang") + dirs32, err32 := ioutil.ReadDir(clangVersionRoot) + if err64 != nil && err32 != nil { + // Unexpected. + continue + } + dirnames := make([]string, len(dirs64)+len(dirs32)) + dirCount := 0 + for _, d := range dirs32 { + name := d.Name() + if name == llvmMajor || strings.HasPrefix(name, llvmMajor+".") { + dirnames[dirCount] = filepath.Join(llvmRoot, "lib", "clang", name) + dirCount++ } } - dirnames := make([]string, len(dirs)) - for i, d := range dirs { - dirnames[i] = d.Name() + for _, d := range dirs64 { + name := d.Name() + if name == llvmMajor || strings.HasPrefix(name, llvmMajor+".") { + dirnames[dirCount] = filepath.Join(llvmRoot, "lib64", "clang", name) + dirCount++ + } } sort.Strings(dirnames) // Check for the highest version first. - for i := len(dirnames) - 1; i >= 0; i-- { - path := filepath.Join(clangVersionRoot, dirnames[i], "include") + for i := dirCount - 1; i >= 0; i-- { + path := filepath.Join(dirnames[i], "include") _, err := os.Stat(filepath.Join(path, "stdint.h")) if err == nil { return path