baremetal,wasm: support command line params and environment variables
This is mainly useful to be able to run `tinygo test`, for example: tinygo test -target=cortex-m-qemu -v math This is not currently supported, but will be in the future.
Этот коммит содержится в:
родитель
c25a7cc747
коммит
f57e9622fd
6 изменённых файлов: 126 добавлений и 37 удалений
|
@ -208,7 +208,7 @@ func mergeDirectory(goroot, tinygoroot, tmpgoroot, importPath string, overrides
|
|||
// with the TinyGo version. This is the case on some targets.
|
||||
func needsSyscallPackage(buildTags []string) bool {
|
||||
for _, tag := range buildTags {
|
||||
if tag == "baremetal" || tag == "darwin" || tag == "nintendoswitch" || tag == "wasi" {
|
||||
if tag == "baremetal" || tag == "darwin" || tag == "nintendoswitch" || tag == "tinygo.wasm" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
86
main_test.go
86
main_test.go
|
@ -162,15 +162,15 @@ func runPlatTests(target string, tests []string, t *testing.T) {
|
|||
runTest(name, target, t, nil, nil)
|
||||
})
|
||||
}
|
||||
t.Run("env.go", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runTest("env.go", target, t, []string{"first", "second"}, []string{"ENV1=VALUE1", "ENV2=VALUE2"})
|
||||
})
|
||||
if target == "" || target == "wasi" {
|
||||
t.Run("filesystem.go", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runTest("filesystem.go", target, t, nil, nil)
|
||||
})
|
||||
t.Run("env.go", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runTest("env.go", target, t, []string{"first", "second"}, []string{"ENV1=VALUE1", "ENV2=VALUE2"})
|
||||
})
|
||||
}
|
||||
if target == "" || target == "wasi" || target == "wasm" {
|
||||
t.Run("rand.go", func(t *testing.T) {
|
||||
|
@ -233,6 +233,42 @@ func runTestWithConfig(name, target string, t *testing.T, options compileopts.Op
|
|||
}
|
||||
}()
|
||||
|
||||
// Determine whether we're on a system that supports environment variables
|
||||
// and command line parameters (operating systems, WASI) or not (baremetal,
|
||||
// WebAssembly in the browser). If we're on a system without an environment,
|
||||
// we need to pass command line arguments and environment variables through
|
||||
// global variables (built into the binary directly) instead of the
|
||||
// conventional way.
|
||||
spec, err := compileopts.LoadTarget(target)
|
||||
if err != nil {
|
||||
t.Fatal("failed to load target spec:", err)
|
||||
}
|
||||
needsEnvInVars := spec.GOOS == "js"
|
||||
for _, tag := range spec.BuildTags {
|
||||
if tag == "baremetal" {
|
||||
needsEnvInVars = true
|
||||
}
|
||||
}
|
||||
if needsEnvInVars {
|
||||
runtimeGlobals := make(map[string]string)
|
||||
if len(cmdArgs) != 0 {
|
||||
runtimeGlobals["osArgs"] = strings.Join(cmdArgs, "\x00")
|
||||
}
|
||||
if len(environmentVars) != 0 {
|
||||
runtimeGlobals["osEnv"] = strings.Join(environmentVars, "\x00")
|
||||
}
|
||||
if len(runtimeGlobals) != 0 {
|
||||
// This sets the global variables like they would be set with
|
||||
// `-ldflags="-X=runtime.osArgs=first\x00second`.
|
||||
// The runtime package has two variables (osArgs and osEnv) that are
|
||||
// both strings, from which the parameters and environment variables
|
||||
// are read.
|
||||
options.GlobalValues = map[string]map[string]string{
|
||||
"runtime": runtimeGlobals,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the test binary.
|
||||
binary := filepath.Join(tmpdir, "test")
|
||||
err = runBuild("./"+path, binary, &options)
|
||||
|
@ -242,37 +278,31 @@ func runTestWithConfig(name, target string, t *testing.T, options compileopts.Op
|
|||
return
|
||||
}
|
||||
|
||||
// Run the test.
|
||||
runComplete := make(chan struct{})
|
||||
// Create the test command, taking care of emulators etc.
|
||||
var cmd *exec.Cmd
|
||||
ranTooLong := false
|
||||
if target == "" {
|
||||
if len(spec.Emulator) == 0 {
|
||||
cmd = exec.Command(binary)
|
||||
cmd.Env = append(cmd.Env, environmentVars...)
|
||||
} else {
|
||||
args := append(spec.Emulator[1:], binary)
|
||||
cmd = exec.Command(spec.Emulator[0], args...)
|
||||
}
|
||||
if len(spec.Emulator) != 0 && spec.Emulator[0] == "wasmtime" {
|
||||
// Allow reading from the current directory.
|
||||
cmd.Args = append(cmd.Args, "--dir=.")
|
||||
for _, v := range environmentVars {
|
||||
cmd.Args = append(cmd.Args, "--env", v)
|
||||
}
|
||||
cmd.Args = append(cmd.Args, cmdArgs...)
|
||||
} else {
|
||||
spec, err := compileopts.LoadTarget(target)
|
||||
if err != nil {
|
||||
t.Fatal("failed to load target spec:", err)
|
||||
}
|
||||
if len(spec.Emulator) == 0 {
|
||||
cmd = exec.Command(binary)
|
||||
} else {
|
||||
args := append(spec.Emulator[1:], binary)
|
||||
cmd = exec.Command(spec.Emulator[0], args...)
|
||||
}
|
||||
|
||||
if len(spec.Emulator) != 0 && spec.Emulator[0] == "wasmtime" {
|
||||
// Allow reading from the current directory.
|
||||
cmd.Args = append(cmd.Args, "--dir=.")
|
||||
for _, v := range environmentVars {
|
||||
cmd.Args = append(cmd.Args, "--env", v)
|
||||
}
|
||||
cmd.Args = append(cmd.Args, cmdArgs...)
|
||||
} else {
|
||||
if !needsEnvInVars {
|
||||
cmd.Args = append(cmd.Args, cmdArgs...) // works on qemu-aarch64 etc
|
||||
cmd.Env = append(cmd.Env, environmentVars...)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test.
|
||||
runComplete := make(chan struct{})
|
||||
ranTooLong := false
|
||||
stdout := &bytes.Buffer{}
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
|
48
src/runtime/nonhosted.go
Обычный файл
48
src/runtime/nonhosted.go
Обычный файл
|
@ -0,0 +1,48 @@
|
|||
// +build baremetal js
|
||||
|
||||
package runtime
|
||||
|
||||
// This file is for non-hosted environments, that don't support command line
|
||||
// parameters or environment variables. To still be able to run certain tests,
|
||||
// command line parameters and environment variables can be passed to the binary
|
||||
// by setting the variables `runtime.osArgs` and `runtime.osEnv`, both of which
|
||||
// are strings separated by newlines.
|
||||
//
|
||||
// The primary use case is `tinygo test`, which takes some parameters (such as
|
||||
// -test.v).
|
||||
|
||||
var env []string
|
||||
|
||||
//go:linkname syscall_runtime_envs syscall.runtime_envs
|
||||
func syscall_runtime_envs() []string {
|
||||
return env
|
||||
}
|
||||
|
||||
var osArgs string
|
||||
var osEnv string
|
||||
|
||||
func init() {
|
||||
if osArgs != "" {
|
||||
s := osArgs
|
||||
start := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == 0 {
|
||||
args = append(args, s[start:i])
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
args = append(args, s[start:])
|
||||
}
|
||||
|
||||
if osEnv != "" {
|
||||
s := osEnv
|
||||
start := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == 0 {
|
||||
env = append(env, s[start:i])
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
env = append(env, s[start:])
|
||||
}
|
||||
}
|
|
@ -15,11 +15,6 @@ func _start() {
|
|||
run()
|
||||
}
|
||||
|
||||
//go:linkname syscall_runtime_envs syscall.runtime_envs
|
||||
func syscall_runtime_envs() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
var handleEvent func()
|
||||
|
||||
//go:linkname setEventHandler syscall/js.setEventHandler
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// +build baremetal
|
||||
// +build baremetal js
|
||||
|
||||
package syscall
|
||||
|
||||
|
@ -47,8 +47,24 @@ const (
|
|||
O_CLOEXEC = 0
|
||||
)
|
||||
|
||||
func runtime_envs() []string
|
||||
|
||||
func Getenv(key string) (value string, found bool) {
|
||||
return "", false // stub
|
||||
env := runtime_envs()
|
||||
for _, keyval := range env {
|
||||
// Split at '=' character.
|
||||
var k, v string
|
||||
for i := 0; i < len(keyval); i++ {
|
||||
if keyval[i] == '=' {
|
||||
k = keyval[:i]
|
||||
v = keyval[i+1:]
|
||||
}
|
||||
}
|
||||
if k == key {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func Open(path string, mode int, perm uint32) (fd int, err error) {
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build baremetal nintendoswitch
|
||||
// +build baremetal nintendoswitch js
|
||||
|
||||
package syscall
|
||||
|
Загрузка…
Создание таблицы
Сослаться в новой задаче