diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:25:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:25:22 +0000 |
commit | f6ad4dcef54c5ce997a4bad5a6d86de229015700 (patch) | |
tree | 7cfa4e31ace5c2bd95c72b154d15af494b2bcbef /src/cmd/cgo/internal/testso | |
parent | Initial commit. (diff) | |
download | golang-1.22-f6ad4dcef54c5ce997a4bad5a6d86de229015700.tar.xz golang-1.22-f6ad4dcef54c5ce997a4bad5a6d86de229015700.zip |
Adding upstream version 1.22.1.upstream/1.22.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/cmd/cgo/internal/testso')
-rw-r--r-- | src/cmd/cgo/internal/testso/so_test.go | 137 | ||||
-rw-r--r-- | src/cmd/cgo/internal/testso/testdata/so/cgoso.c | 14 | ||||
-rw-r--r-- | src/cmd/cgo/internal/testso/testdata/so/cgoso.go | 32 | ||||
-rw-r--r-- | src/cmd/cgo/internal/testso/testdata/so/cgoso_c.c | 39 | ||||
-rw-r--r-- | src/cmd/cgo/internal/testso/testdata/so/cgoso_unix.go | 20 | ||||
-rw-r--r-- | src/cmd/cgo/internal/testso/testdata/so/main.go | 13 | ||||
-rw-r--r-- | src/cmd/cgo/internal/testso/testdata/sovar/cgoso.go | 44 | ||||
-rw-r--r-- | src/cmd/cgo/internal/testso/testdata/sovar/cgoso_c.c | 7 | ||||
-rw-r--r-- | src/cmd/cgo/internal/testso/testdata/sovar/cgoso_c.h | 17 | ||||
-rw-r--r-- | src/cmd/cgo/internal/testso/testdata/sovar/main.go | 13 |
10 files changed, 336 insertions, 0 deletions
diff --git a/src/cmd/cgo/internal/testso/so_test.go b/src/cmd/cgo/internal/testso/so_test.go new file mode 100644 index 0000000..e011167 --- /dev/null +++ b/src/cmd/cgo/internal/testso/so_test.go @@ -0,0 +1,137 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package so_test + +import ( + "cmd/cgo/internal/cgotest" + "internal/testenv" + "log" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" +) + +func TestSO(t *testing.T) { + testSO(t, "so") +} + +func TestSOVar(t *testing.T) { + testSO(t, "sovar") +} + +func testSO(t *testing.T, dir string) { + if runtime.GOOS == "ios" { + t.Skip("iOS disallows dynamic loading of user libraries") + } + testenv.MustHaveGoBuild(t) + testenv.MustHaveExec(t) + testenv.MustHaveCGO(t) + + GOPATH, err := os.MkdirTemp("", "cgosotest") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(GOPATH) + + modRoot := filepath.Join(GOPATH, "src", "cgosotest") + if err := cgotest.OverlayDir(modRoot, filepath.Join("testdata", dir)); err != nil { + log.Panic(err) + } + if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil { + log.Panic(err) + } + + cmd := exec.Command("go", "env", "CC", "GOGCCFLAGS") + cmd.Dir = modRoot + cmd.Stderr = new(strings.Builder) + cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) + out, err := cmd.Output() + if err != nil { + t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) + } + lines := strings.Split(string(out), "\n") + if len(lines) != 3 || lines[2] != "" { + t.Fatalf("Unexpected output from %s:\n%s", strings.Join(cmd.Args, " "), lines) + } + + cc := lines[0] + if cc == "" { + t.Fatal("CC environment variable (go env CC) cannot be empty") + } + gogccflags := strings.Split(lines[1], " ") + + // build shared object + ext := "so" + args := append(gogccflags, "-shared") + switch runtime.GOOS { + case "darwin", "ios": + ext = "dylib" + args = append(args, "-undefined", "suppress", "-flat_namespace") + case "windows": + ext = "dll" + args = append(args, "-DEXPORT_DLL") + // At least in mingw-clang it is not permitted to just name a .dll + // on the command line. You must name the corresponding import + // library instead, even though the dll is used when the executable is run. + args = append(args, "-Wl,-out-implib,libcgosotest.a") + case "aix": + ext = "so.1" + } + sofname := "libcgosotest." + ext + args = append(args, "-o", sofname, "cgoso_c.c") + + cmd = exec.Command(cc, args...) + cmd.Dir = modRoot + cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) + out, err = cmd.CombinedOutput() + if err != nil { + t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) + } + t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) + + if runtime.GOOS == "aix" { + // Shared object must be wrapped by an archive + cmd = exec.Command("ar", "-X64", "-q", "libcgosotest.a", "libcgosotest.so.1") + cmd.Dir = modRoot + out, err = cmd.CombinedOutput() + if err != nil { + t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) + } + } + + cmd = exec.Command("go", "build", "-o", "main.exe", "main.go") + cmd.Dir = modRoot + cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) + out, err = cmd.CombinedOutput() + if err != nil { + t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) + } + t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) + + cmd = exec.Command("./main.exe") + cmd.Dir = modRoot + cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) + if runtime.GOOS != "windows" { + s := "LD_LIBRARY_PATH" + if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { + s = "DYLD_LIBRARY_PATH" + } + cmd.Env = append(os.Environ(), s+"=.") + + // On FreeBSD 64-bit architectures, the 32-bit linker looks for + // different environment variables. + if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" { + cmd.Env = append(cmd.Env, "LD_32_LIBRARY_PATH=.") + } + } + out, err = cmd.CombinedOutput() + if err != nil { + t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) + } + t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) +} diff --git a/src/cmd/cgo/internal/testso/testdata/so/cgoso.c b/src/cmd/cgo/internal/testso/testdata/so/cgoso.c new file mode 100644 index 0000000..612e5d3 --- /dev/null +++ b/src/cmd/cgo/internal/testso/testdata/so/cgoso.c @@ -0,0 +1,14 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "_cgo_export.h" + +#if defined(WIN32) || defined(_AIX) +extern void setCallback(void *); +void init() { + setCallback(goCallback); +} +#else +void init() {} +#endif diff --git a/src/cmd/cgo/internal/testso/testdata/so/cgoso.go b/src/cmd/cgo/internal/testso/testdata/so/cgoso.go new file mode 100644 index 0000000..b59b2a8 --- /dev/null +++ b/src/cmd/cgo/internal/testso/testdata/so/cgoso.go @@ -0,0 +1,32 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgosotest + +/* +// intentionally write the same LDFLAGS differently +// to test correct handling of LDFLAGS. +#cgo linux LDFLAGS: -L. -lcgosotest +#cgo dragonfly LDFLAGS: -L. -l cgosotest +#cgo freebsd LDFLAGS: -L. -l cgosotest +#cgo openbsd LDFLAGS: -L. -l cgosotest +#cgo solaris LDFLAGS: -L. -lcgosotest +#cgo netbsd LDFLAGS: -L. libcgosotest.so +#cgo darwin LDFLAGS: -L. libcgosotest.dylib +#cgo windows LDFLAGS: -L. libcgosotest.a +#cgo aix LDFLAGS: -L. -l cgosotest + +void init(void); +void sofunc(void); +*/ +import "C" + +func Test() { + C.init() + C.sofunc() +} + +//export goCallback +func goCallback() { +} diff --git a/src/cmd/cgo/internal/testso/testdata/so/cgoso_c.c b/src/cmd/cgo/internal/testso/testdata/so/cgoso_c.c new file mode 100644 index 0000000..d5fb559 --- /dev/null +++ b/src/cmd/cgo/internal/testso/testdata/so/cgoso_c.c @@ -0,0 +1,39 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +#ifdef WIN32 +// A Windows DLL is unable to call an arbitrary function in +// the main executable. Work around that by making the main +// executable pass the callback function pointer to us. +void (*goCallback)(void); +__declspec(dllexport) void setCallback(void *f) +{ + goCallback = (void (*)())f; +} +__declspec(dllexport) void sofunc(void); +#elif defined(_AIX) +// AIX doesn't allow the creation of a shared object with an +// undefined symbol. It's possible to bypass this problem by +// using -Wl,-G and -Wl,-brtl option which allows run-time linking. +// However, that's not how most of AIX shared object works. +// Therefore, it's better to consider goCallback as a pointer and +// to set up during an init function. +void (*goCallback)(void); +void setCallback(void *f) { goCallback = f; } +#else +extern void goCallback(void); +void setCallback(void *f) { (void)f; } +#endif + +// OpenBSD and older Darwin lack TLS support +#if !defined(__OpenBSD__) && !defined(__APPLE__) +__thread int tlsvar = 12345; +#endif + +void sofunc(void) +{ + goCallback(); +} diff --git a/src/cmd/cgo/internal/testso/testdata/so/cgoso_unix.go b/src/cmd/cgo/internal/testso/testdata/so/cgoso_unix.go new file mode 100644 index 0000000..ea9cb0a --- /dev/null +++ b/src/cmd/cgo/internal/testso/testdata/so/cgoso_unix.go @@ -0,0 +1,20 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || dragonfly || freebsd || linux || netbsd || solaris + +package cgosotest + +/* +extern int __thread tlsvar; +int *getTLS() { return &tlsvar; } +*/ +import "C" + +func init() { + if v := *C.getTLS(); v != 12345 { + println("got", v) + panic("BAD TLS value") + } +} diff --git a/src/cmd/cgo/internal/testso/testdata/so/main.go b/src/cmd/cgo/internal/testso/testdata/so/main.go new file mode 100644 index 0000000..84382f7 --- /dev/null +++ b/src/cmd/cgo/internal/testso/testdata/so/main.go @@ -0,0 +1,13 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +package main + +import "cgosotest" + +func main() { + cgosotest.Test() +} diff --git a/src/cmd/cgo/internal/testso/testdata/sovar/cgoso.go b/src/cmd/cgo/internal/testso/testdata/sovar/cgoso.go new file mode 100644 index 0000000..d9deb55 --- /dev/null +++ b/src/cmd/cgo/internal/testso/testdata/sovar/cgoso.go @@ -0,0 +1,44 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgosotest + +// This test verifies that Go can access C variables +// in shared object file via cgo. + +/* +// intentionally write the same LDFLAGS differently +// to test correct handling of LDFLAGS. +#cgo windows CFLAGS: -DIMPORT_DLL +#cgo linux LDFLAGS: -L. -lcgosotest +#cgo dragonfly LDFLAGS: -L. -l cgosotest +#cgo freebsd LDFLAGS: -L. -l cgosotest +#cgo openbsd LDFLAGS: -L. -l cgosotest +#cgo solaris LDFLAGS: -L. -lcgosotest +#cgo netbsd LDFLAGS: -L. libcgosotest.so +#cgo darwin LDFLAGS: -L. libcgosotest.dylib +#cgo windows LDFLAGS: -L. libcgosotest.a +#cgo aix LDFLAGS: -L. -l cgosotest + +#include "cgoso_c.h" + +const char* getVar() { + return exported_var; +} +*/ +import "C" + +import "fmt" + +func Test() { + const want = "Hello world" + got := C.GoString(C.getVar()) + if got != want { + panic(fmt.Sprintf("testExportedVar: got %q, but want %q", got, want)) + } + got = C.GoString(C.exported_var) + if got != want { + panic(fmt.Sprintf("testExportedVar: got %q, but want %q", got, want)) + } +} diff --git a/src/cmd/cgo/internal/testso/testdata/sovar/cgoso_c.c b/src/cmd/cgo/internal/testso/testdata/sovar/cgoso_c.c new file mode 100644 index 0000000..36f4d57 --- /dev/null +++ b/src/cmd/cgo/internal/testso/testdata/sovar/cgoso_c.c @@ -0,0 +1,7 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +const char *exported_var = "Hello world"; diff --git a/src/cmd/cgo/internal/testso/testdata/sovar/cgoso_c.h b/src/cmd/cgo/internal/testso/testdata/sovar/cgoso_c.h new file mode 100644 index 0000000..eccd8c0 --- /dev/null +++ b/src/cmd/cgo/internal/testso/testdata/sovar/cgoso_c.h @@ -0,0 +1,17 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +#ifdef WIN32 +#if defined(EXPORT_DLL) +# define VAR __declspec(dllexport) +#elif defined(IMPORT_DLL) +# define VAR __declspec(dllimport) +#endif +#else +# define VAR extern +#endif + +VAR const char *exported_var; diff --git a/src/cmd/cgo/internal/testso/testdata/sovar/main.go b/src/cmd/cgo/internal/testso/testdata/sovar/main.go new file mode 100644 index 0000000..018b835 --- /dev/null +++ b/src/cmd/cgo/internal/testso/testdata/sovar/main.go @@ -0,0 +1,13 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +package main + +import "cgosotest" + +func main() { + cgosotest.Test() +} |