aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2021-08-10 21:35:52 +0200
committerRon Evans <[email protected]>2021-08-12 21:19:24 +0200
commitf57e9622fdb650f14a48cc327db01c216cd0d9c6 (patch)
tree1bda50a5662f0571e17a8363a6470b8555e244cf
parentc25a7cc7477a5fc58d68e125ec2cf62836f23fe2 (diff)
downloadtinygo-f57e9622fdb650f14a48cc327db01c216cd0d9c6.tar.gz
tinygo-f57e9622fdb650f14a48cc327db01c216cd0d9c6.zip
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.
-rw-r--r--loader/goroot.go2
-rw-r--r--main_test.go86
-rw-r--r--src/runtime/nonhosted.go48
-rw-r--r--src/runtime/runtime_wasm_js.go5
-rw-r--r--src/syscall/syscall_nonhosted.go (renamed from src/syscall/syscall_baremetal.go)20
-rw-r--r--src/syscall/tables_nonhosted.go (renamed from src/syscall/tables_baremetal.go)2
6 files changed, 126 insertions, 37 deletions
diff --git a/loader/goroot.go b/loader/goroot.go
index 6770d0458..8f0acf1b8 100644
--- a/loader/goroot.go
+++ b/loader/goroot.go
@@ -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
}
}
diff --git a/main_test.go b/main_test.go
index 2c1b2f864..a502115e4 100644
--- a/main_test.go
+++ b/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...)
- 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...)
+ 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)
}
-
- 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 {
+ 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
diff --git a/src/runtime/nonhosted.go b/src/runtime/nonhosted.go
new file mode 100644
index 000000000..61f5023df
--- /dev/null
+++ b/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:])
+ }
+}
diff --git a/src/runtime/runtime_wasm_js.go b/src/runtime/runtime_wasm_js.go
index b39aef0a5..f4335e121 100644
--- a/src/runtime/runtime_wasm_js.go
+++ b/src/runtime/runtime_wasm_js.go
@@ -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
diff --git a/src/syscall/syscall_baremetal.go b/src/syscall/syscall_nonhosted.go
index 4f0c6e530..885738e4a 100644
--- a/src/syscall/syscall_baremetal.go
+++ b/src/syscall/syscall_nonhosted.go
@@ -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) {
diff --git a/src/syscall/tables_baremetal.go b/src/syscall/tables_nonhosted.go
index 47a536bff..a78eb75fb 100644
--- a/src/syscall/tables_baremetal.go
+++ b/src/syscall/tables_nonhosted.go
@@ -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