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.
Этот коммит содержится в:
Ayke 2019-01-05 11:46:25 +01:00 коммит произвёл Ron Evans
родитель f44dff6f59
коммит 107fccb288
9 изменённых файлов: 125 добавлений и 23 удалений

Просмотреть файл

@ -32,6 +32,8 @@ func init() {
type Config struct {
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)
GOOS string //
GOARCH string //
GC string // garbage collection strategy
CFlags []string // cflags 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
RootDir string // GOROOT for TinyGo
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
}
@ -97,7 +99,7 @@ func NewCompiler(pkgName string, config Config) (*Compiler, error) {
config.Triple = llvm.DefaultTargetTriple()
}
if len(config.BuildTags) == 0 {
config.BuildTags = []string{runtime.GOOS, runtime.GOARCH}
config.BuildTags = []string{config.GOOS, config.GOARCH}
}
c := &Compiler{
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
// fails (in any stage).
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
// the TinyGo root.
gopath := c.GOPATH
@ -195,8 +195,8 @@ func (c *Compiler) Compile(mainPath string) error {
}
lprogram := &loader.Program{
Build: &build.Context{
GOARCH: tripleSplit[0],
GOOS: tripleSplit[2],
GOARCH: c.GOARCH,
GOOS: c.GOOS,
GOROOT: c.RootDir,
GOPATH: gopath,
CgoEnabled: true,

Просмотреть файл

@ -52,6 +52,8 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
compilerConfig := compiler.Config{
Triple: spec.Triple,
CPU: spec.CPU,
GOOS: spec.GOOS,
GOARCH: spec.GOARCH,
GC: config.gc,
CFlags: spec.CFlags,
LDFlags: spec.LDFlags,

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
const GOARCH = "amd64"

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 Обычный файл
Просмотреть файл

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

Просмотреть файл

@ -2,14 +2,13 @@ package main
import (
"encoding/json"
"errors"
"io"
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
"github.com/aykevl/go-llvm"
)
// Target specification for a given target. Used for bare metal targets.
@ -21,6 +20,8 @@ type TargetSpec struct {
Inherits []string `json:"inherits"`
Triple string `json:"llvm-target"`
CPU string `json:"cpu"`
GOOS string `json:"goos"`
GOARCH string `json:"goarch"`
BuildTags []string `json:"build-tags"`
GC string `json:"gc"`
Compiler string `json:"compiler"`
@ -48,6 +49,12 @@ func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) {
if 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...)
if spec2.GC != "" {
spec.GC = spec2.GC
@ -134,7 +141,27 @@ func (spec *TargetSpec) resolveInherits() error {
// Load a target specification.
func LoadTarget(target string) (*TargetSpec, error) {
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.
@ -154,22 +181,60 @@ func LoadTarget(target string) (*TargetSpec, error) {
// an error.
return nil, err
} else {
// No target spec available. Use the default one, useful on most systems
// with a regular OS.
*spec = TargetSpec{
Triple: target,
BuildTags: []string{runtime.GOOS, runtime.GOARCH},
Compiler: commands["clang"],
Linker: "cc",
LDFlags: []string{"-no-pie"}, // WARNING: clang < 5.0 requires -nopie
Objcopy: "objcopy",
GDB: "gdb",
GDBCmds: []string{"run"},
// Load target from given triple, ignore GOOS/GOARCH environment
// variables.
tripleSplit := strings.Split(target, "-")
if len(tripleSplit) == 1 {
return nil, errors.New("expected a full LLVM target or a custom target in -target flag")
}
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
// recovered.
func sourceDir() string {

Просмотреть файл

@ -1,5 +1,7 @@
{
"build-tags": ["avr", "js", "wasm"],
"goos": "js",
"goarch": "wasm",
"compiler": "avr-gcc",
"linker": "avr-gcc",
"objcopy": "avr-objcopy",

Просмотреть файл

@ -1,5 +1,7 @@
{
"build-tags": ["tinygo.arm", "js", "wasm"],
"goos": "js",
"goarch": "wasm",
"compiler": "clang-7",
"gc": "marksweep",
"linker": "arm-none-eabi-ld",