Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions builder/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package builder

import (
"fmt"
"runtime"

"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
Expand All @@ -23,20 +24,37 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
spec.OpenOCDCommands = options.OpenOCDCommands
}

major, minor, err := goenv.GetGorootVersion()
// Version range supported by TinyGo.
const minorMin = 19
const minorMax = 23

// Check that we support this Go toolchain version.
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
if err != nil {
return nil, err
}
if major != 1 || minor < 19 || minor > 23 {
if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax {
// Note: when this gets updated, also update the Go compatibility matrix:
// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
return nil, fmt.Errorf("requires go version 1.19 through 1.23, got go%d.%d", major, minor)
return nil, fmt.Errorf("requires go version 1.19 through 1.23, got go%d.%d", gorootMajor, gorootMinor)
}

// Check that the Go toolchain version isn't too new, if we haven't been
// compiled with the latest Go version.
// This may be a bit too aggressive: if the newer version doesn't change the
// Go language we will most likely be able to compile it.
buildMajor, buildMinor, err := goenv.Parse(runtime.Version())
if err != nil {
return nil, err
}
if buildMajor != 1 || buildMinor < gorootMinor {
return nil, fmt.Errorf("cannot compile with Go toolchain version go%d.%d (TinyGo was built using toolchain version %s)", gorootMajor, gorootMinor, runtime.Version())
}

return &compileopts.Config{
Options: options,
Target: spec,
GoMinorVersion: minor,
GoMinorVersion: gorootMinor,
TestConfig: options.TestConfig,
}, nil
}
2 changes: 2 additions & 0 deletions errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func TestErrors(t *testing.T) {
{name: "cgo"},
{name: "compiler"},
{name: "interp"},
{name: "invalidmain"},
{name: "invalidname"},
{name: "linker-flashoverflow", target: "cortex-m-qemu"},
{name: "linker-ramoverflow", target: "cortex-m-qemu"},
{name: "linker-undefined", target: "darwin/arm64"},
Expand Down
12 changes: 9 additions & 3 deletions goenv/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,25 @@ func GetGorootVersion() (major, minor int, err error) {
if err != nil {
return 0, 0, err
}
return Parse(s)
}

if s == "" || s[:2] != "go" {
// Parse parses the Go version (like "go1.3.2") in the parameter and return the
// major and minor version: 1 and 3 in this example. If there is an error, (0,
// 0) and an error will be returned.
func Parse(version string) (major, minor int, err error) {
if version == "" || version[:2] != "go" {
return 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
}

parts := strings.Split(s[2:], ".")
parts := strings.Split(version[2:], ".")
if len(parts) < 2 {
return 0, 0, errors.New("could not parse Go version: version has less than two parts")
}

// Ignore the errors, we don't really handle errors here anyway.
var trailing string
n, err := fmt.Sscanf(s, "go%d.%d%s", &major, &minor, &trailing)
n, err := fmt.Sscanf(version, "go%d.%d%s", &major, &minor, &trailing)
if n == 2 && err == io.EOF {
// Means there were no trailing characters (i.e., not an alpha/beta)
err = nil
Expand Down
18 changes: 15 additions & 3 deletions loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,12 @@ func (p *Package) Check() error {
packageName := p.ImportPath
if p == p.program.MainPkg() {
if p.Name != "main" {
// Sanity check. Should not ever trigger.
panic("expected main package to have name 'main'")
return Errors{p, []error{
scanner.Error{
Pos: p.program.fset.Position(p.Files[0].Name.Pos()),
Msg: fmt.Sprintf("expected main package to have name \"main\", not %#v", p.Name),
},
}}
}
packageName = "main"
}
Expand All @@ -428,7 +432,15 @@ func (p *Package) Check() error {
if err, ok := err.(Errors); ok {
return err
}
return Errors{p, typeErrors}
if len(typeErrors) != 0 {
// Got type errors, so return them.
return Errors{p, typeErrors}
}
// This can happen in some weird cases.
// The only case I know is when compiling a Go 1.23 program, with a
// TinyGo version that supports Go 1.23 but is compiled using Go 1.22.
// So this should be pretty rare.
return Errors{p, []error{err}}
}
p.Pkg = typesPkg

Expand Down
6 changes: 6 additions & 0 deletions testdata/errors/invalidmain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// some comment to move the first line

package foobar

// ERROR: # command-line-arguments
// ERROR: invalidmain.go:3:9: expected main package to have name "main", not "foobar"
6 changes: 6 additions & 0 deletions testdata/errors/invalidname.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package main

import _ "github.com/tinygo-org/tinygo/testdata/errors/invalidname"

// ERROR: # github.com/tinygo-org/tinygo/testdata/errors/invalidname
// ERROR: invalidname{{[\\/]}}invalidname.go:3:9: invalid package name _
3 changes: 3 additions & 0 deletions testdata/errors/invalidname/invalidname.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// some comment to move the 'package' line

package _
Loading