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
2 changes: 1 addition & 1 deletion .github/workflows/compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
env:
# Oldest versions currently supported by TinyGo
LLVM: "15"
Go: "1.25" # when updating this, also update minorMin in builder/config.go
Go: "1.25" # when updating this, also update MinimumGoMinorVersion in compileopts/config.go
steps:
- name: Checkout
uses: actions/checkout@v6
Expand Down
8 changes: 2 additions & 6 deletions builder/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,17 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
spec.OpenOCDCommands = options.OpenOCDCommands
}

// Version range supported by TinyGo.
const minorMin = 25 // when updating the min version, also update .github/workflows/compat.yml
const minorMax = 27

// Check that we support this Go toolchain version.
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
if err != nil {
return nil, err
}

if options.GoCompatibility {
if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax {
if gorootMajor != 1 || gorootMinor < compileopts.MinimumGoMinorVersion || gorootMinor > compileopts.MaximumGoMinorVersion {
// 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.%d through 1.%d, got go%d.%d", minorMin, minorMax, gorootMajor, gorootMinor)
return nil, fmt.Errorf("requires go version 1.%d through 1.%d, got go%d.%d", compileopts.MinimumGoMinorVersion, compileopts.MaximumGoMinorVersion, gorootMajor, gorootMinor)
}
}

Expand Down
6 changes: 6 additions & 0 deletions compileopts/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ import (
"github.com/tinygo-org/tinygo/goenv"
)

// Go minor version range supported by TinyGo.
const (
MinimumGoMinorVersion = 25
MaximumGoMinorVersion = 27
)

// Library versions. Whenever an existing library is changed, this number should
// be added/increased so that existing caches are invalidated.
//
Expand Down
118 changes: 118 additions & 0 deletions fix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package main

import (
"errors"
"flag"
"fmt"
"io"
"os"
"strings"

"github.com/tinygo-org/tinygo/builder"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/compiler"
"github.com/tinygo-org/tinygo/fix"
"github.com/tinygo-org/tinygo/goenv"
"github.com/tinygo-org/tinygo/loader"
"golang.org/x/tools/go/buildutil"
)

const usageFix = `usage: tinygo fix [flags] [packages]

Apply Go fix analyzers using TinyGo's package loader, including package tests.
Use -diff to print changes without writing files. A nonempty diff exits with 1.
Use -tests=false to exclude test files from analysis.
Use -target and -tags to select one target configuration.
Only named packages are changed, not their dependencies or host Go sources.

Run tinygo fix help for analyzer names or tinygo fix help <name> for details.
The -fixtool and -toolexec flags are not supported.
`

func runFix(args []string, stdout, stderr io.Writer) int {
set := flag.NewFlagSet("fix", flag.ContinueOnError)
set.SetOutput(stderr)
set.Usage = func() {
fmt.Fprint(stderr, usageFix)
set.PrintDefaults()
}
diff := set.Bool("diff", false, "print a unified diff without writing files")
includeTests := set.Bool("tests", true, "include test files when analyzing packages")
options := &compileopts.Options{
GOOS: goenv.Get("GOOS"), GOARCH: goenv.Get("GOARCH"),
GOARM: goenv.Get("GOARM"), GOMIPS: goenv.Get("GOMIPS"),
GoCompatibility: true, Opt: "z", PanicStrategy: "print",
}
set.StringVar(&options.Target, "target", "", "chip/board name or JSON target specification file")
set.StringVar(&options.GC, "gc", "", "garbage collector")
set.StringVar(&options.Scheduler, "scheduler", "", "goroutine scheduler")
set.StringVar(&options.Serial, "serial", "", "serial output")
set.StringVar(&options.PanicUnwind, "panic-unwind", "", "panic unwind strategy")
set.StringVar(&options.LLVMFeatures, "llvm-features", "", "LLVM target features")
set.StringVar(&options.Directory, "C", "", "change to directory before loading packages")
var tags buildutil.TagsFlag
set.Var(&tags, "tags", "build tags")
analyzerFlags := fix.RegisterFlags(set)
if err := set.Parse(args); err != nil {
if errors.Is(err, flag.ErrHelp) {
return 0
}
return 2
}
patterns := set.Args()
if len(patterns) > 0 && patterns[0] == "help" {
for _, a := range fix.Analyzers() {
if len(patterns) == 1 {
fmt.Fprintf(stdout, "%-18s %s\n", a.Name, strings.SplitN(a.Doc, "\n", 2)[0])
} else if len(patterns) == 2 && patterns[1] == a.Name {
fmt.Fprintln(stdout, a.Doc)
a.Flags.SetOutput(stdout)
a.Flags.PrintDefaults()
return 0
}
}
if len(patterns) == 1 {
return 0
}
fmt.Fprintln(stderr, "unknown analyzer or invalid help arguments")
return 2
}
options.Tags = tags
if options.Directory != "" {
if err := os.Chdir(options.Directory); err != nil {
fmt.Fprintln(stderr, err)
return 1
}
options.Directory = ""
}
if err := options.Verify(); err != nil {
fmt.Fprintln(stderr, err)
return 2
}
config, err := builder.NewConfig(options)
if err != nil {
fmt.Fprintln(stderr, err)
return 1
}
machine, err := compiler.NewTargetMachine(&compiler.Config{
Triple: config.Triple(), CPU: config.CPU(), Features: config.Features(),
CodeModel: config.CodeModel(), RelocationModel: config.RelocationModel(),
})
if err != nil {
fmt.Fprintln(stderr, err)
return 1
}
defer machine.Dispose()
sizes := compiler.Sizes(machine)
changed, err := fix.Run(func(overlay map[string][]byte) (*loader.Analysis, error) {
return loader.LoadForAnalysis(config, patterns, sizes, overlay, *includeTests)
}, analyzerFlags.Selected(), *diff, stdout, stderr)
if err != nil {
printBuildOutput(err, false)
return 1
}
if *diff && changed {
return 1
}
return 0
}
Loading
Loading