main: move target specification into a separate package

Этот коммит содержится в:
Ayke van Laethem 2019-10-31 15:39:01 +01:00 коммит произвёл Ron Evans
родитель dff6e6566d
коммит e7cf75030c
7 изменённых файлов: 129 добавлений и 114 удалений

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

@ -65,7 +65,7 @@ commands:
- go-cache-v2-{{ checksum "go.mod" }}
- llvm-source-linux
- run: go install .
- run: go test -v ./cgo ./interp ./transform .
- run: go test -v ./cgo ./compileopts ./interp ./transform .
- run: make gen-device -j4
- run: make smoketest RISCV=0
- save_cache:

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

@ -139,7 +139,7 @@ tinygo:
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -o build/tinygo$(EXE) -tags byollvm .
test:
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test -v -tags byollvm ./cgo ./interp ./transform .
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test -v -tags byollvm ./cgo ./compileopts ./interp ./transform .
tinygo-test:
cd tests/tinygotest && tinygo test

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

@ -1,13 +1,13 @@
package main
package compileopts
// This file loads a target specification from a JSON file.
import (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
@ -300,104 +300,3 @@ func (spec *TargetSpec) OpenOCDConfiguration() (args []string, err error) {
args = append(args, "-f", "target/"+spec.OpenOCDTarget+".cfg")
return args, nil
}
// getGorootVersion returns the major and minor version for a given GOROOT path.
// If the goroot cannot be determined, (0, 0) is returned.
func getGorootVersion(goroot string) (major, minor int, err error) {
s, err := getGorootVersionString(goroot)
if err != nil {
return 0, 0, err
}
if s == "" || s[:2] != "go" {
return 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
}
parts := strings.Split(s[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)
if n == 2 && err == io.EOF {
// Means there were no trailing characters (i.e., not an alpha/beta)
err = nil
}
if err != nil {
return 0, 0, fmt.Errorf("failed to parse version: %s", err)
}
return
}
// getGorootVersionString returns the version string as reported by the Go
// toolchain for the given GOROOT path. It is usually of the form `go1.x.y` but
// can have some variations (for beta releases, for example).
func getGorootVersionString(goroot string) (string, error) {
if data, err := ioutil.ReadFile(filepath.Join(
goroot, "src", "runtime", "internal", "sys", "zversion.go")); err == nil {
r := regexp.MustCompile("const TheVersion = `(.*)`")
matches := r.FindSubmatch(data)
if len(matches) != 2 {
return "", errors.New("Invalid go version output:\n" + string(data))
}
return string(matches[1]), nil
} else if data, err := ioutil.ReadFile(filepath.Join(goroot, "VERSION")); err == nil {
return string(data), nil
} else {
return "", err
}
}
// getClangHeaderPath returns the path to the built-in Clang headers. It tries
// multiple locations, which should make it find the directory when installed in
// various ways.
func getClangHeaderPath(TINYGOROOT string) string {
// Check whether we're running from the source directory.
path := filepath.Join(TINYGOROOT, "llvm", "tools", "clang", "lib", "Headers")
if _, err := os.Stat(path); !os.IsNotExist(err) {
return path
}
// Check whether we're running from the installation directory.
path = filepath.Join(TINYGOROOT, "lib", "clang", "include")
if _, err := os.Stat(path); !os.IsNotExist(err) {
return path
}
// It looks like we are built with a system-installed LLVM. Do a last
// attempt: try to use Clang headers relative to the clang binary.
for _, cmdName := range commands["clang"] {
binpath, err := exec.LookPath(cmdName)
if err == nil {
// This should be the command that will also be used by
// execCommand. To avoid inconsistencies, make sure we use the
// headers relative to this command.
binpath, err = filepath.EvalSymlinks(binpath)
if err != nil {
// Unexpected.
return ""
}
// Example executable:
// /usr/lib/llvm-8/bin/clang
// Example include path:
// /usr/lib/llvm-8/lib/clang/8.0.1/include/
llvmRoot := filepath.Dir(filepath.Dir(binpath))
clangVersionRoot := filepath.Join(llvmRoot, "lib", "clang")
dirnames, err := ioutil.ReadDir(clangVersionRoot)
if err != nil || len(dirnames) != 1 {
// Unexpected.
return ""
}
return filepath.Join(clangVersionRoot, dirnames[0].Name(), "include")
}
}
// Could not find it.
return ""
}

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

@ -1,4 +1,4 @@
package main
package compileopts
import "testing"

13
main.go
Просмотреть файл

@ -17,6 +17,7 @@ import (
"syscall"
"time"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/compiler"
"github.com/tinygo-org/tinygo/goenv"
"github.com/tinygo-org/tinygo/interp"
@ -66,7 +67,7 @@ type BuildConfig struct {
}
// Helper function for Compiler object.
func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, action func(string) error) error {
func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *BuildConfig, action func(string) error) error {
if config.gc == "" && spec.GC != "" {
config.gc = spec.GC
}
@ -335,7 +336,7 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
}
func Build(pkgName, outpath, target string, config *BuildConfig) error {
spec, err := LoadTarget(target)
spec, err := compileopts.LoadTarget(target)
if err != nil {
return err
}
@ -369,7 +370,7 @@ func Build(pkgName, outpath, target string, config *BuildConfig) error {
}
func Test(pkgName, target string, config *BuildConfig) error {
spec, err := LoadTarget(target)
spec, err := compileopts.LoadTarget(target)
if err != nil {
return err
}
@ -396,7 +397,7 @@ func Test(pkgName, target string, config *BuildConfig) error {
}
func Flash(pkgName, target, port string, config *BuildConfig) error {
spec, err := LoadTarget(target)
spec, err := compileopts.LoadTarget(target)
if err != nil {
return err
}
@ -503,7 +504,7 @@ func Flash(pkgName, target, port string, config *BuildConfig) error {
// Note: this command is expected to execute just before exiting, as it
// modifies global state.
func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig) error {
spec, err := LoadTarget(target)
spec, err := compileopts.LoadTarget(target)
if err != nil {
return err
}
@ -594,7 +595,7 @@ func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig)
// Compile and run the given program, directly or in an emulator.
func Run(pkgName, target string, config *BuildConfig) error {
spec, err := LoadTarget(target)
spec, err := compileopts.LoadTarget(target)
if err != nil {
return err
}

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

@ -14,6 +14,7 @@ import (
"sort"
"testing"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/loader"
)
@ -142,7 +143,7 @@ func runTest(path, tmpdir string, target string, t *testing.T) {
if target == "" {
cmd = exec.Command(binary)
} else {
spec, err := LoadTarget(target)
spec, err := compileopts.LoadTarget(target)
if err != nil {
t.Fatal("failed to load target spec:", err)
}

114
paths.go Обычный файл
Просмотреть файл

@ -0,0 +1,114 @@
package main
import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
)
// getGorootVersion returns the major and minor version for a given GOROOT path.
// If the goroot cannot be determined, (0, 0) is returned.
func getGorootVersion(goroot string) (major, minor int, err error) {
s, err := getGorootVersionString(goroot)
if err != nil {
return 0, 0, err
}
if s == "" || s[:2] != "go" {
return 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
}
parts := strings.Split(s[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)
if n == 2 && err == io.EOF {
// Means there were no trailing characters (i.e., not an alpha/beta)
err = nil
}
if err != nil {
return 0, 0, fmt.Errorf("failed to parse version: %s", err)
}
return
}
// getGorootVersionString returns the version string as reported by the Go
// toolchain for the given GOROOT path. It is usually of the form `go1.x.y` but
// can have some variations (for beta releases, for example).
func getGorootVersionString(goroot string) (string, error) {
if data, err := ioutil.ReadFile(filepath.Join(
goroot, "src", "runtime", "internal", "sys", "zversion.go")); err == nil {
r := regexp.MustCompile("const TheVersion = `(.*)`")
matches := r.FindSubmatch(data)
if len(matches) != 2 {
return "", errors.New("Invalid go version output:\n" + string(data))
}
return string(matches[1]), nil
} else if data, err := ioutil.ReadFile(filepath.Join(goroot, "VERSION")); err == nil {
return string(data), nil
} else {
return "", err
}
}
// getClangHeaderPath returns the path to the built-in Clang headers. It tries
// multiple locations, which should make it find the directory when installed in
// various ways.
func getClangHeaderPath(TINYGOROOT string) string {
// Check whether we're running from the source directory.
path := filepath.Join(TINYGOROOT, "llvm", "tools", "clang", "lib", "Headers")
if _, err := os.Stat(path); !os.IsNotExist(err) {
return path
}
// Check whether we're running from the installation directory.
path = filepath.Join(TINYGOROOT, "lib", "clang", "include")
if _, err := os.Stat(path); !os.IsNotExist(err) {
return path
}
// It looks like we are built with a system-installed LLVM. Do a last
// attempt: try to use Clang headers relative to the clang binary.
for _, cmdName := range commands["clang"] {
binpath, err := exec.LookPath(cmdName)
if err == nil {
// This should be the command that will also be used by
// execCommand. To avoid inconsistencies, make sure we use the
// headers relative to this command.
binpath, err = filepath.EvalSymlinks(binpath)
if err != nil {
// Unexpected.
return ""
}
// Example executable:
// /usr/lib/llvm-8/bin/clang
// Example include path:
// /usr/lib/llvm-8/lib/clang/8.0.1/include/
llvmRoot := filepath.Dir(filepath.Dir(binpath))
clangVersionRoot := filepath.Join(llvmRoot, "lib", "clang")
dirnames, err := ioutil.ReadDir(clangVersionRoot)
if err != nil || len(dirnames) != 1 {
// Unexpected.
return ""
}
return filepath.Join(clangVersionRoot, dirnames[0].Name(), "include")
}
}
// Could not find it.
return ""
}