WASI & darwin: support env variables based on libc
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
Этот коммит содержится в:
родитель
c299386906
коммит
9841ac4acd
9 изменённых файлов: 115 добавлений и 12 удалений
16
main_test.go
16
main_test.go
|
@ -58,6 +58,9 @@ func TestCompiler(t *testing.T) {
|
|||
if runtime.GOOS != "windows" {
|
||||
t.Run("Host", func(t *testing.T) {
|
||||
runPlatTests("", matches, t)
|
||||
if runtime.GOOS == "darwin" {
|
||||
runTest("testdata/libc/env.go", "", t, []string{"ENV1=VALUE1", "ENV2=VALUE2"}...)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -104,6 +107,7 @@ func TestCompiler(t *testing.T) {
|
|||
|
||||
t.Run("WASI", func(t *testing.T) {
|
||||
runPlatTests("wasi", matches, t)
|
||||
runTest("testdata/libc/env.go", "wasi", t, []string{"ENV1=VALUE1", "ENV2=VALUE2"}...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +117,6 @@ func runPlatTests(target string, matches []string, t *testing.T) {
|
|||
|
||||
for _, path := range matches {
|
||||
path := path // redefine to avoid race condition
|
||||
|
||||
t.Run(filepath.Base(path), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runTest(path, target, t)
|
||||
|
@ -133,7 +136,7 @@ func runBuild(src, out string, opts *compileopts.Options) error {
|
|||
return Build(src, out, opts)
|
||||
}
|
||||
|
||||
func runTest(path, target string, t *testing.T) {
|
||||
func runTest(path, target string, t *testing.T, environmentVars ...string) {
|
||||
// Get the expected output for this test.
|
||||
txtpath := path[:len(path)-3] + ".txt"
|
||||
if path[len(path)-1] == os.PathSeparator {
|
||||
|
@ -182,6 +185,7 @@ func runTest(path, target string, t *testing.T) {
|
|||
ranTooLong := false
|
||||
if target == "" {
|
||||
cmd = exec.Command(binary)
|
||||
cmd.Env = append(cmd.Env, environmentVars...)
|
||||
} else {
|
||||
spec, err := compileopts.LoadTarget(target)
|
||||
if err != nil {
|
||||
|
@ -193,6 +197,14 @@ func runTest(path, target string, t *testing.T) {
|
|||
args := append(spec.Emulator[1:], binary)
|
||||
cmd = exec.Command(spec.Emulator[0], args...)
|
||||
}
|
||||
|
||||
if len(spec.Emulator) != 0 && spec.Emulator[0] == "wasmtime" {
|
||||
for _, v := range environmentVars {
|
||||
cmd.Args = append(cmd.Args, "--env", v)
|
||||
}
|
||||
} else {
|
||||
cmd.Env = append(cmd.Env, environmentVars...)
|
||||
}
|
||||
}
|
||||
stdout := &bytes.Buffer{}
|
||||
cmd.Stdout = stdout
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package os
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func Getenv(key string) string {
|
||||
return ""
|
||||
v, _ := syscall.Getenv(key)
|
||||
return v
|
||||
}
|
||||
|
||||
func LookupEnv(key string) (string, bool) {
|
||||
return "", false
|
||||
return syscall.Getenv(key)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// +build baremetal wasi
|
||||
// +build baremetal
|
||||
|
||||
package syscall
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// +build darwin nintendoswitch
|
||||
// +build darwin nintendoswitch wasi
|
||||
|
||||
package syscall
|
||||
|
||||
|
@ -6,6 +6,12 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
type sliceHeader struct {
|
||||
buf *byte
|
||||
len uintptr
|
||||
cap uintptr
|
||||
}
|
||||
|
||||
func Close(fd int) (err error) {
|
||||
return ENOSYS // TODO
|
||||
}
|
||||
|
@ -48,18 +54,32 @@ func Getpid() (pid int) {
|
|||
}
|
||||
|
||||
func Getenv(key string) (value string, found bool) {
|
||||
return "", false // TODO
|
||||
data := append([]byte(key), 0)
|
||||
raw := libc_getenv(&data[0])
|
||||
if raw == nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
ptr := uintptr(unsafe.Pointer(raw))
|
||||
for size := uintptr(0); ; size++ {
|
||||
v := *(*byte)(unsafe.Pointer(ptr))
|
||||
if v == 0 {
|
||||
src := *(*[]byte)(unsafe.Pointer(&sliceHeader{buf: raw, len: size, cap: size}))
|
||||
return string(src), true
|
||||
}
|
||||
ptr += unsafe.Sizeof(byte(0))
|
||||
}
|
||||
}
|
||||
|
||||
func splitSlice(p []byte) (buf *byte, len uintptr) {
|
||||
slice := (*struct {
|
||||
buf *byte
|
||||
len uintptr
|
||||
cap uintptr
|
||||
})(unsafe.Pointer(&p))
|
||||
slice := (*sliceHeader)(unsafe.Pointer(&p))
|
||||
return slice.buf, slice.len
|
||||
}
|
||||
|
||||
// ssize_t write(int fd, const void *buf, size_t count)
|
||||
//export write
|
||||
func libc_write(fd int32, buf *byte, count uint) int
|
||||
|
||||
// char *getenv(const char *name);
|
||||
//export getenv
|
||||
func libc_getenv(name *byte) *byte
|
||||
|
|
50
src/syscall/syscall_libc_wasi.go
Обычный файл
50
src/syscall/syscall_libc_wasi.go
Обычный файл
|
@ -0,0 +1,50 @@
|
|||
// +build wasi
|
||||
|
||||
package syscall
|
||||
|
||||
// https://github.com/WebAssembly/wasi-libc/blob/main/expected/wasm32-wasi/predefined-macros.txt
|
||||
|
||||
type Signal int
|
||||
|
||||
const (
|
||||
SIGCHLD = 16
|
||||
SIGINT = 2
|
||||
SIGKILL = 9
|
||||
SIGTRAP = 5
|
||||
SIGQUIT = 3
|
||||
SIGTERM = 15
|
||||
)
|
||||
|
||||
const (
|
||||
Stdin = 0
|
||||
Stdout = 1
|
||||
Stderr = 2
|
||||
)
|
||||
|
||||
const (
|
||||
__WASI_OFLAGS_CREAT = 1
|
||||
__WASI_FDFLAGS_APPEND = 1
|
||||
__WASI_OFLAGS_EXCL = 4
|
||||
__WASI_OFLAGS_TRUNC = 8
|
||||
__WASI_FDFLAGS_SYNC = 16
|
||||
|
||||
O_RDONLY = 0x04000000
|
||||
O_WRONLY = 0x10000000
|
||||
O_RDWR = O_RDONLY | O_WRONLY
|
||||
|
||||
O_CREAT = __WASI_OFLAGS_CREAT << 12
|
||||
O_CREATE = O_CREAT
|
||||
O_TRUNC = __WASI_OFLAGS_TRUNC << 12
|
||||
O_APPEND = __WASI_FDFLAGS_APPEND
|
||||
O_EXCL = __WASI_OFLAGS_EXCL << 12
|
||||
O_SYNC = __WASI_FDFLAGS_SYNC
|
||||
|
||||
O_CLOEXEC = 0
|
||||
)
|
||||
|
||||
//go:extern errno
|
||||
var libcErrno uintptr
|
||||
|
||||
func getErrno() error {
|
||||
return Errno(libcErrno)
|
||||
}
|
14
testdata/libc/env.go
предоставленный
Обычный файл
14
testdata/libc/env.go
предоставленный
Обычный файл
|
@ -0,0 +1,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
println(os.Getenv("ENV1"))
|
||||
v, ok := os.LookupEnv("ENV2")
|
||||
if !ok {
|
||||
panic("ENV2 not found")
|
||||
}
|
||||
println(v)
|
||||
}
|
2
testdata/libc/env.txt
предоставленный
Обычный файл
2
testdata/libc/env.txt
предоставленный
Обычный файл
|
@ -0,0 +1,2 @@
|
|||
VALUE1
|
||||
VALUE2
|
Загрузка…
Создание таблицы
Сослаться в новой задаче