all: add support for more architectures and GOOS/GOARCH (#118)
This commit does two things: * It adds support for the GOOS and GOARCH environment variables. They fall back to runtime.GO* only when not available. * It adds support for 3 new architectures: 386, arm, and arm64. For now, this is Linux-only.
Этот коммит содержится в:
родитель
f44dff6f59
коммит
107fccb288
9 изменённых файлов: 125 добавлений и 23 удалений
|
@ -32,6 +32,8 @@ func init() {
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Triple string // LLVM target triple, e.g. x86_64-unknown-linux-gnu (empty string means default)
|
Triple string // LLVM target triple, e.g. x86_64-unknown-linux-gnu (empty string means default)
|
||||||
CPU string // LLVM CPU name, e.g. atmega328p (empty string means default)
|
CPU string // LLVM CPU name, e.g. atmega328p (empty string means default)
|
||||||
|
GOOS string //
|
||||||
|
GOARCH string //
|
||||||
GC string // garbage collection strategy
|
GC string // garbage collection strategy
|
||||||
CFlags []string // cflags to pass to cgo
|
CFlags []string // cflags to pass to cgo
|
||||||
LDFlags []string // ldflags to pass to cgo
|
LDFlags []string // ldflags to pass to cgo
|
||||||
|
@ -39,7 +41,7 @@ type Config struct {
|
||||||
Debug bool // add debug symbols for gdb
|
Debug bool // add debug symbols for gdb
|
||||||
RootDir string // GOROOT for TinyGo
|
RootDir string // GOROOT for TinyGo
|
||||||
GOPATH string // GOPATH, like `go env GOPATH`
|
GOPATH string // GOPATH, like `go env GOPATH`
|
||||||
BuildTags []string // build tags for TinyGo (empty means {runtime.GOOS/runtime.GOARCH})
|
BuildTags []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH})
|
||||||
InitInterp bool // use new init interpretation, meaning the old one is disabled
|
InitInterp bool // use new init interpretation, meaning the old one is disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +99,7 @@ func NewCompiler(pkgName string, config Config) (*Compiler, error) {
|
||||||
config.Triple = llvm.DefaultTargetTriple()
|
config.Triple = llvm.DefaultTargetTriple()
|
||||||
}
|
}
|
||||||
if len(config.BuildTags) == 0 {
|
if len(config.BuildTags) == 0 {
|
||||||
config.BuildTags = []string{runtime.GOOS, runtime.GOARCH}
|
config.BuildTags = []string{config.GOOS, config.GOARCH}
|
||||||
}
|
}
|
||||||
c := &Compiler{
|
c := &Compiler{
|
||||||
Config: config,
|
Config: config,
|
||||||
|
@ -178,8 +180,6 @@ func (c *Compiler) selectGC() string {
|
||||||
// Compile the given package path or .go file path. Return an error when this
|
// Compile the given package path or .go file path. Return an error when this
|
||||||
// fails (in any stage).
|
// fails (in any stage).
|
||||||
func (c *Compiler) Compile(mainPath string) error {
|
func (c *Compiler) Compile(mainPath string) error {
|
||||||
tripleSplit := strings.Split(c.Triple, "-")
|
|
||||||
|
|
||||||
// Prefix the GOPATH with the system GOROOT, as GOROOT is already set to
|
// Prefix the GOPATH with the system GOROOT, as GOROOT is already set to
|
||||||
// the TinyGo root.
|
// the TinyGo root.
|
||||||
gopath := c.GOPATH
|
gopath := c.GOPATH
|
||||||
|
@ -195,8 +195,8 @@ func (c *Compiler) Compile(mainPath string) error {
|
||||||
}
|
}
|
||||||
lprogram := &loader.Program{
|
lprogram := &loader.Program{
|
||||||
Build: &build.Context{
|
Build: &build.Context{
|
||||||
GOARCH: tripleSplit[0],
|
GOARCH: c.GOARCH,
|
||||||
GOOS: tripleSplit[2],
|
GOOS: c.GOOS,
|
||||||
GOROOT: c.RootDir,
|
GOROOT: c.RootDir,
|
||||||
GOPATH: gopath,
|
GOPATH: gopath,
|
||||||
CgoEnabled: true,
|
CgoEnabled: true,
|
||||||
|
|
2
main.go
2
main.go
|
@ -52,6 +52,8 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
|
||||||
compilerConfig := compiler.Config{
|
compilerConfig := compiler.Config{
|
||||||
Triple: spec.Triple,
|
Triple: spec.Triple,
|
||||||
CPU: spec.CPU,
|
CPU: spec.CPU,
|
||||||
|
GOOS: spec.GOOS,
|
||||||
|
GOARCH: spec.GOARCH,
|
||||||
GC: config.gc,
|
GC: config.gc,
|
||||||
CFlags: spec.CFlags,
|
CFlags: spec.CFlags,
|
||||||
LDFlags: spec.LDFlags,
|
LDFlags: spec.LDFlags,
|
||||||
|
|
11
src/runtime/arch_386.go
Обычный файл
11
src/runtime/arch_386.go
Обычный файл
|
@ -0,0 +1,11 @@
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
const GOARCH = "386"
|
||||||
|
|
||||||
|
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||||
|
const TargetBits = 32
|
||||||
|
|
||||||
|
// Align on word boundary.
|
||||||
|
func align(ptr uintptr) uintptr {
|
||||||
|
return (ptr + 3) &^ 3
|
||||||
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
// +build amd64
|
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
const GOARCH = "amd64"
|
const GOARCH = "amd64"
|
||||||
|
|
11
src/runtime/arch_arm.go
Обычный файл
11
src/runtime/arch_arm.go
Обычный файл
|
@ -0,0 +1,11 @@
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
const GOARCH = "arm"
|
||||||
|
|
||||||
|
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||||
|
const TargetBits = 32
|
||||||
|
|
||||||
|
// Align on word boundary.
|
||||||
|
func align(ptr uintptr) uintptr {
|
||||||
|
return (ptr + 3) &^ 3
|
||||||
|
}
|
11
src/runtime/arch_arm64.go
Обычный файл
11
src/runtime/arch_arm64.go
Обычный файл
|
@ -0,0 +1,11 @@
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
const GOARCH = "arm64"
|
||||||
|
|
||||||
|
// The bitness of the CPU (e.g. 8, 32, 64).
|
||||||
|
const TargetBits = 64
|
||||||
|
|
||||||
|
// Align on word boundary.
|
||||||
|
func align(ptr uintptr) uintptr {
|
||||||
|
return (ptr + 7) &^ 7
|
||||||
|
}
|
95
target.go
95
target.go
|
@ -2,14 +2,13 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aykevl/go-llvm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Target specification for a given target. Used for bare metal targets.
|
// Target specification for a given target. Used for bare metal targets.
|
||||||
|
@ -21,6 +20,8 @@ type TargetSpec struct {
|
||||||
Inherits []string `json:"inherits"`
|
Inherits []string `json:"inherits"`
|
||||||
Triple string `json:"llvm-target"`
|
Triple string `json:"llvm-target"`
|
||||||
CPU string `json:"cpu"`
|
CPU string `json:"cpu"`
|
||||||
|
GOOS string `json:"goos"`
|
||||||
|
GOARCH string `json:"goarch"`
|
||||||
BuildTags []string `json:"build-tags"`
|
BuildTags []string `json:"build-tags"`
|
||||||
GC string `json:"gc"`
|
GC string `json:"gc"`
|
||||||
Compiler string `json:"compiler"`
|
Compiler string `json:"compiler"`
|
||||||
|
@ -48,6 +49,12 @@ func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) {
|
||||||
if spec2.CPU != "" {
|
if spec2.CPU != "" {
|
||||||
spec.CPU = spec2.CPU
|
spec.CPU = spec2.CPU
|
||||||
}
|
}
|
||||||
|
if spec2.GOOS != "" {
|
||||||
|
spec.GOOS = spec2.GOOS
|
||||||
|
}
|
||||||
|
if spec2.GOARCH != "" {
|
||||||
|
spec.GOARCH = spec2.GOARCH
|
||||||
|
}
|
||||||
spec.BuildTags = append(spec.BuildTags, spec2.BuildTags...)
|
spec.BuildTags = append(spec.BuildTags, spec2.BuildTags...)
|
||||||
if spec2.GC != "" {
|
if spec2.GC != "" {
|
||||||
spec.GC = spec2.GC
|
spec.GC = spec2.GC
|
||||||
|
@ -134,7 +141,27 @@ func (spec *TargetSpec) resolveInherits() error {
|
||||||
// Load a target specification.
|
// Load a target specification.
|
||||||
func LoadTarget(target string) (*TargetSpec, error) {
|
func LoadTarget(target string) (*TargetSpec, error) {
|
||||||
if target == "" {
|
if target == "" {
|
||||||
target = llvm.DefaultTargetTriple()
|
// Configure based on GOOS/GOARCH environment variables (falling back to
|
||||||
|
// runtime.GOOS/runtime.GOARCH), and generate a LLVM target based on it.
|
||||||
|
goos := os.Getenv("GOOS")
|
||||||
|
if goos == "" {
|
||||||
|
goos = runtime.GOOS
|
||||||
|
}
|
||||||
|
goarch := os.Getenv("GOARCH")
|
||||||
|
if goarch == "" {
|
||||||
|
goarch = runtime.GOARCH
|
||||||
|
}
|
||||||
|
llvmos := goos
|
||||||
|
llvmarch := map[string]string{
|
||||||
|
"386": "i386",
|
||||||
|
"amd64": "x86_64",
|
||||||
|
"arm64": "aarch64",
|
||||||
|
}[goarch]
|
||||||
|
if llvmarch == "" {
|
||||||
|
llvmarch = goarch
|
||||||
|
}
|
||||||
|
target = llvmarch + "--" + llvmos
|
||||||
|
return defaultTarget(goos, goarch, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// See whether there is a target specification for this target (e.g.
|
// See whether there is a target specification for this target (e.g.
|
||||||
|
@ -154,22 +181,60 @@ func LoadTarget(target string) (*TargetSpec, error) {
|
||||||
// an error.
|
// an error.
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
// No target spec available. Use the default one, useful on most systems
|
// Load target from given triple, ignore GOOS/GOARCH environment
|
||||||
// with a regular OS.
|
// variables.
|
||||||
*spec = TargetSpec{
|
tripleSplit := strings.Split(target, "-")
|
||||||
Triple: target,
|
if len(tripleSplit) == 1 {
|
||||||
BuildTags: []string{runtime.GOOS, runtime.GOARCH},
|
return nil, errors.New("expected a full LLVM target or a custom target in -target flag")
|
||||||
Compiler: commands["clang"],
|
|
||||||
Linker: "cc",
|
|
||||||
LDFlags: []string{"-no-pie"}, // WARNING: clang < 5.0 requires -nopie
|
|
||||||
Objcopy: "objcopy",
|
|
||||||
GDB: "gdb",
|
|
||||||
GDBCmds: []string{"run"},
|
|
||||||
}
|
}
|
||||||
return spec, nil
|
goos := tripleSplit[2]
|
||||||
|
goarch := map[string]string{ // map from LLVM arch to Go arch
|
||||||
|
"i386": "386",
|
||||||
|
"x86_64": "amd64",
|
||||||
|
"aarch64": "arm64",
|
||||||
|
}[tripleSplit[0]]
|
||||||
|
if goarch == "" {
|
||||||
|
goarch = tripleSplit[0]
|
||||||
|
}
|
||||||
|
return defaultTarget(goos, goarch, target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
||||||
|
// No target spec available. Use the default one, useful on most systems
|
||||||
|
// with a regular OS.
|
||||||
|
spec := TargetSpec{
|
||||||
|
Triple: triple,
|
||||||
|
GOOS: goos,
|
||||||
|
GOARCH: goarch,
|
||||||
|
BuildTags: []string{goos, goarch},
|
||||||
|
Compiler: commands["clang"],
|
||||||
|
Linker: "cc",
|
||||||
|
LDFlags: []string{"-no-pie"}, // WARNING: clang < 5.0 requires -nopie
|
||||||
|
Objcopy: "objcopy",
|
||||||
|
GDB: "gdb",
|
||||||
|
GDBCmds: []string{"run"},
|
||||||
|
}
|
||||||
|
if goarch != runtime.GOARCH {
|
||||||
|
// Some educated guesses as to how to invoke helper programs.
|
||||||
|
if goarch == "arm" {
|
||||||
|
spec.Linker = "arm-linux-gnueabi-gcc"
|
||||||
|
spec.Objcopy = "arm-linux-gnueabi-objcopy"
|
||||||
|
spec.GDB = "arm-linux-gnueabi-gdb"
|
||||||
|
}
|
||||||
|
if goarch == "arm64" {
|
||||||
|
spec.Linker = "aarch64-linux-gnu-gcc"
|
||||||
|
spec.Objcopy = "aarch64-linux-gnu-objcopy"
|
||||||
|
spec.GDB = "aarch64-linux-gnu-gdb"
|
||||||
|
}
|
||||||
|
if goarch == "386" {
|
||||||
|
spec.CFlags = []string{"-m32"}
|
||||||
|
spec.LDFlags = []string{"-m32"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &spec, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Return the source directory of this package, or "." when it cannot be
|
// Return the source directory of this package, or "." when it cannot be
|
||||||
// recovered.
|
// recovered.
|
||||||
func sourceDir() string {
|
func sourceDir() string {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
{
|
{
|
||||||
"build-tags": ["avr", "js", "wasm"],
|
"build-tags": ["avr", "js", "wasm"],
|
||||||
|
"goos": "js",
|
||||||
|
"goarch": "wasm",
|
||||||
"compiler": "avr-gcc",
|
"compiler": "avr-gcc",
|
||||||
"linker": "avr-gcc",
|
"linker": "avr-gcc",
|
||||||
"objcopy": "avr-objcopy",
|
"objcopy": "avr-objcopy",
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
{
|
{
|
||||||
"build-tags": ["tinygo.arm", "js", "wasm"],
|
"build-tags": ["tinygo.arm", "js", "wasm"],
|
||||||
|
"goos": "js",
|
||||||
|
"goarch": "wasm",
|
||||||
"compiler": "clang-7",
|
"compiler": "clang-7",
|
||||||
"gc": "marksweep",
|
"gc": "marksweep",
|
||||||
"linker": "arm-none-eabi-ld",
|
"linker": "arm-none-eabi-ld",
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче