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 {
|
||||
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,
|
||||
|
|
2
main.go
2
main.go
|
@ -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
Обычный файл
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
Обычный файл
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 (
|
||||
"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",
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче