Make lib64 clang include path check more robust.

On Fedora 33+, there is a buggy package that installs to
`/usr/lib64/clang/{version}/lib`, even on 32-bit systems. The original
code sees the `/usr/lib64/clang/{version}` directory, checks for an
`include` subdirectory, and then gives up because it doesn't exist.

To be more robust, check both `/usr/lib64/clang/{version}/include` and
`/usr/lib/clang/{version}/include`, and only allow versions that match
the LLVM major version used to build tinygo.
Этот коммит содержится в:
Elliott Sales de Andrade 2020-10-30 04:03:01 -04:00 коммит произвёл Ayke
родитель 387bca8e32
коммит b3bd891ee0

Просмотреть файл

@ -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 {
dirs64, err64 := ioutil.ReadDir(clangVersionRoot)
// 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 {
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++
}
}
for _, d := range dirs64 {
name := d.Name()
if name == llvmMajor || strings.HasPrefix(name, llvmMajor+".") {
dirnames[dirCount] = filepath.Join(llvmRoot, "lib64", "clang", name)
dirCount++
}
dirnames := make([]string, len(dirs))
for i, d := range dirs {
dirnames[i] = d.Name()
}
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