Browse Source

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.
pull/412/head
Ayke van Laethem 5 years ago
committed by Ron Evans
parent
commit
a3d1f1a514
  1. 8
      compiler/compiler.go
  2. 13
      loader/loader.go
  3. 1
      main.go
  4. 48
      target.go

8
compiler/compiler.go

@ -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)

13
loader/loader.go

@ -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

@ -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

@ -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 ""
}

Loading…
Cancel
Save