mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-14 07:53:40 +00:00
loader: merge roots from both Go and TinyGo in a cached directory
This commit changes the way that packages are looked up. Instead of working around the loader package by modifying the GOROOT variable for specific packages, create a new GOROOT using symlinks. This GOROOT is cached for the specified configuration (Go version, underlying GOROOT path, TinyGo path, whether to override the syscall package). This will also enable go module support in the future. Windows is a bit harder to support, because it only allows the creation of symlinks when developer mode is enabled. This is worked around by using symlinks and if that fails, using directory junctions or hardlinks instead. This should work in the vast majority of cases. The only case it doesn't work, is if developer mode is disabled and TinyGo, the Go toolchain, and the cache directory are not all on the same filesystem. If this is a problem, it is still possible to improve the code by using file copies instead. As a side effect, this also makes diagnostics use a relative file path only when the file is not in GOROOT or in TINYGOROOT.
This commit is contained in:
committed by
Ron Evans
parent
bde73fc214
commit
35015a7918
+23
-12
@@ -16,14 +16,13 @@ import (
|
||||
"text/template"
|
||||
|
||||
"github.com/tinygo-org/tinygo/cgo"
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
)
|
||||
|
||||
// Program holds all packages and some metadata about the program as a whole.
|
||||
type Program struct {
|
||||
mainPkg string
|
||||
Build *build.Context
|
||||
OverlayBuild *build.Context
|
||||
OverlayPath func(path string) string
|
||||
Packages map[string]*Package
|
||||
sorted []*Package
|
||||
fset *token.FileSet
|
||||
@@ -55,10 +54,6 @@ func (p *Program) Import(path, srcDir string, pos token.Position) (*Package, err
|
||||
|
||||
// Load this package.
|
||||
ctx := p.Build
|
||||
if newPath := p.OverlayPath(path); newPath != "" {
|
||||
ctx = p.OverlayBuild
|
||||
path = newPath
|
||||
}
|
||||
buildPkg, err := ctx.Import(path, srcDir, build.ImportComment)
|
||||
if err != nil {
|
||||
return nil, scanner.Error{
|
||||
@@ -320,14 +315,30 @@ func (p *Program) parseFile(path string, mode parser.Mode) (*ast.File, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer rd.Close()
|
||||
relpath := path
|
||||
if filepath.IsAbs(path) {
|
||||
rp, err := filepath.Rel(p.Dir, path)
|
||||
if err == nil {
|
||||
relpath = rp
|
||||
diagnosticPath := path
|
||||
if strings.HasPrefix(path, p.Build.GOROOT+string(filepath.Separator)) {
|
||||
// If this file is part of the synthetic GOROOT, try to infer the
|
||||
// original path.
|
||||
relpath := path[len(filepath.Join(p.Build.GOROOT, "src"))+1:]
|
||||
realgorootPath := filepath.Join(goenv.Get("GOROOT"), "src", relpath)
|
||||
if _, err := os.Stat(realgorootPath); err == nil {
|
||||
diagnosticPath = realgorootPath
|
||||
}
|
||||
maybeInTinyGoRoot := false
|
||||
for prefix := range pathsToOverride(needsSyscallPackage(p.Build.BuildTags)) {
|
||||
if !strings.HasPrefix(relpath, prefix) {
|
||||
continue
|
||||
}
|
||||
maybeInTinyGoRoot = true
|
||||
}
|
||||
if maybeInTinyGoRoot {
|
||||
tinygoPath := filepath.Join(p.TINYGOROOT, "src", relpath)
|
||||
if _, err := os.Stat(tinygoPath); err == nil {
|
||||
diagnosticPath = tinygoPath
|
||||
}
|
||||
}
|
||||
}
|
||||
return parser.ParseFile(p.fset, relpath, rd, mode)
|
||||
return parser.ParseFile(p.fset, diagnosticPath, rd, mode)
|
||||
}
|
||||
|
||||
// Parse parses and typechecks this package.
|
||||
|
||||
Reference in New Issue
Block a user