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.
Этот коммит содержится в:
родитель
3e1c0d90c5
коммит
a3d1f1a514
4 изменённых файлов: 59 добавлений и 11 удалений
|
@ -41,6 +41,7 @@ type Config struct {
|
|||
PanicStrategy string // panic strategy ("abort" or "trap")
|
||||
CFlags []string // cflags 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
|
||||
Debug bool // add debug symbols for gdb
|
||||
GOROOT string // GOROOT
|
||||
|
@ -235,9 +236,10 @@ func (c *Compiler) Compile(mainPath string) []error {
|
|||
MaxAlign: int64(c.targetData.PrefTypeAlignment(c.i8ptrType)),
|
||||
},
|
||||
},
|
||||
Dir: wd,
|
||||
TINYGOROOT: c.TINYGOROOT,
|
||||
CFlags: c.CFlags,
|
||||
Dir: wd,
|
||||
TINYGOROOT: c.TINYGOROOT,
|
||||
CFlags: c.CFlags,
|
||||
ClangHeaders: c.ClangHeaders,
|
||||
}
|
||||
if strings.HasSuffix(mainPath, ".go") {
|
||||
_, err = lprogram.ImportFile(mainPath)
|
||||
|
|
|
@ -26,6 +26,7 @@ type Program struct {
|
|||
Dir string // current working directory (for error reporting)
|
||||
TINYGOROOT string // root of the TinyGo installation or root of the source code
|
||||
CFlags []string
|
||||
ClangHeaders string
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
if len(p.CgoFiles) != 0 {
|
||||
clangIncludes := ""
|
||||
if _, err := os.Stat(filepath.Join(p.TINYGOROOT, "llvm", "tools", "clang", "lib", "Headers")); !os.IsNotExist(err) {
|
||||
// Running from the source directory.
|
||||
clangIncludes = filepath.Join(p.TINYGOROOT, "llvm", "tools", "clang", "lib", "Headers")
|
||||
} else {
|
||||
// Running from the installation directory.
|
||||
clangIncludes = filepath.Join(p.TINYGOROOT, "lib", "clang", "include")
|
||||
cflags := append(p.CFlags, "-I"+p.Package.Dir)
|
||||
if p.ClangHeaders != "" {
|
||||
cflags = append(cflags, "-I"+p.ClangHeaders)
|
||||
}
|
||||
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 {
|
||||
fileErrs = append(fileErrs, errs...)
|
||||
}
|
||||
|
|
1
main.go
1
main.go
|
@ -101,6 +101,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
|||
PanicStrategy: config.panicStrategy,
|
||||
CFlags: cflags,
|
||||
LDFlags: ldflags,
|
||||
ClangHeaders: getClangHeaderPath(root),
|
||||
Debug: config.debug,
|
||||
DumpSSA: config.dumpSSA,
|
||||
TINYGOROOT: root,
|
||||
|
|
48
target.go
48
target.go
|
@ -401,3 +401,51 @@ func getGorootVersion(goroot string) (major, minor int, err error) {
|
|||
}
|
||||
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 ""
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче