all: try more locations to find Clang built-in headers

This commit fixes the case where TinyGo was built with `go build` and
LLVM sources were never downloaded into the TinyGo source directory.
Этот коммит содержится в:
Ayke van Laethem 2019-06-13 13:52:45 +02:00 коммит произвёл Ron Evans
родитель 3e1c0d90c5
коммит a3d1f1a514
4 изменённых файлов: 59 добавлений и 11 удалений

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

@ -41,6 +41,7 @@ type Config struct {
PanicStrategy string // panic strategy ("abort" or "trap") PanicStrategy string // panic strategy ("abort" or "trap")
CFlags []string // cflags to pass to cgo CFlags []string // cflags to pass to cgo
LDFlags []string // ldflags to pass to cgo LDFlags []string // ldflags to pass to cgo
ClangHeaders string // Clang built-in header include path
DumpSSA bool // dump Go SSA, for compiler debugging DumpSSA bool // dump Go SSA, for compiler debugging
Debug bool // add debug symbols for gdb Debug bool // add debug symbols for gdb
GOROOT string // GOROOT GOROOT string // GOROOT
@ -235,9 +236,10 @@ func (c *Compiler) Compile(mainPath string) []error {
MaxAlign: int64(c.targetData.PrefTypeAlignment(c.i8ptrType)), MaxAlign: int64(c.targetData.PrefTypeAlignment(c.i8ptrType)),
}, },
}, },
Dir: wd, Dir: wd,
TINYGOROOT: c.TINYGOROOT, TINYGOROOT: c.TINYGOROOT,
CFlags: c.CFlags, CFlags: c.CFlags,
ClangHeaders: c.ClangHeaders,
} }
if strings.HasSuffix(mainPath, ".go") { if strings.HasSuffix(mainPath, ".go") {
_, err = lprogram.ImportFile(mainPath) _, err = lprogram.ImportFile(mainPath)

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

@ -26,6 +26,7 @@ type Program struct {
Dir string // current working directory (for error reporting) Dir string // current working directory (for error reporting)
TINYGOROOT string // root of the TinyGo installation or root of the source code TINYGOROOT string // root of the TinyGo installation or root of the source code
CFlags []string CFlags []string
ClangHeaders string
} }
// Package holds a loaded package, its imports, and its parsed files. // Package holds a loaded package, its imports, and its parsed files.
@ -306,15 +307,11 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
files = append(files, f) files = append(files, f)
} }
if len(p.CgoFiles) != 0 { if len(p.CgoFiles) != 0 {
clangIncludes := "" cflags := append(p.CFlags, "-I"+p.Package.Dir)
if _, err := os.Stat(filepath.Join(p.TINYGOROOT, "llvm", "tools", "clang", "lib", "Headers")); !os.IsNotExist(err) { if p.ClangHeaders != "" {
// Running from the source directory. cflags = append(cflags, "-I"+p.ClangHeaders)
clangIncludes = filepath.Join(p.TINYGOROOT, "llvm", "tools", "clang", "lib", "Headers")
} else {
// Running from the installation directory.
clangIncludes = filepath.Join(p.TINYGOROOT, "lib", "clang", "include")
} }
generated, errs := cgo.Process(files, p.Program.Dir, p.fset, append(p.CFlags, "-I"+p.Package.Dir, "-I"+clangIncludes)) generated, errs := cgo.Process(files, p.Program.Dir, p.fset, cflags)
if errs != nil { if errs != nil {
fileErrs = append(fileErrs, errs...) fileErrs = append(fileErrs, errs...)
} }

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

@ -101,6 +101,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
PanicStrategy: config.panicStrategy, PanicStrategy: config.panicStrategy,
CFlags: cflags, CFlags: cflags,
LDFlags: ldflags, LDFlags: ldflags,
ClangHeaders: getClangHeaderPath(root),
Debug: config.debug, Debug: config.debug,
DumpSSA: config.dumpSSA, DumpSSA: config.dumpSSA,
TINYGOROOT: root, TINYGOROOT: root,

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

@ -401,3 +401,51 @@ func getGorootVersion(goroot string) (major, minor int, err error) {
} }
return return
} }
// getClangHeaderPath returns the path to the built-in Clang headers. It tries
// multiple locations, which should make it find the directory when installed in
// various ways.
func getClangHeaderPath(TINYGOROOT string) string {
// Check whether we're running from the source directory.
path := filepath.Join(TINYGOROOT, "llvm", "tools", "clang", "lib", "Headers")
if _, err := os.Stat(path); !os.IsNotExist(err) {
return path
}
// Check whether we're running from the installation directory.
path = filepath.Join(TINYGOROOT, "lib", "clang", "include")
if _, err := os.Stat(path); !os.IsNotExist(err) {
return path
}
// 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.
for _, cmdName := range commands["clang"] {
binpath, err := exec.LookPath(cmdName)
if err == nil {
// This should be the command that will also be used by
// execCommand. To avoid inconsistencies, make sure we use the
// headers relative to this command.
binpath, err = filepath.EvalSymlinks(binpath)
if err != nil {
// Unexpected.
return ""
}
// Example executable:
// /usr/lib/llvm-8/bin/clang
// Example include path:
// /usr/lib/llvm-8/lib/clang/8.0.1/include/
llvmRoot := filepath.Dir(filepath.Dir(binpath))
clangVersionRoot := filepath.Join(llvmRoot, "lib", "clang")
dirnames, err := ioutil.ReadDir(clangVersionRoot)
if err != nil || len(dirnames) != 1 {
// Unexpected.
return ""
}
return filepath.Join(clangVersionRoot, dirnames[0].Name(), "include")
}
}
// Could not find it.
return ""
}