1
2
3
4
5 package so_test
6
7 import (
8 "cmd/cgo/internal/cgotest"
9 "internal/testenv"
10 "log"
11 "os"
12 "os/exec"
13 "path/filepath"
14 "runtime"
15 "strings"
16 "testing"
17 )
18
19 func TestSO(t *testing.T) {
20 testSO(t, "so")
21 }
22
23 func TestSOVar(t *testing.T) {
24 testSO(t, "sovar")
25 }
26
27 func testSO(t *testing.T, dir string) {
28 if runtime.GOOS == "ios" {
29 t.Skip("iOS disallows dynamic loading of user libraries")
30 }
31 testenv.MustHaveGoBuild(t)
32 testenv.MustHaveExec(t)
33 testenv.MustHaveCGO(t)
34
35 GOPATH, err := os.MkdirTemp("", "cgosotest")
36 if err != nil {
37 log.Fatal(err)
38 }
39 defer os.RemoveAll(GOPATH)
40
41 modRoot := filepath.Join(GOPATH, "src", "cgosotest")
42 if err := cgotest.OverlayDir(modRoot, filepath.Join("testdata", dir)); err != nil {
43 log.Panic(err)
44 }
45 if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
46 log.Panic(err)
47 }
48
49 cmd := exec.Command("go", "env", "CC", "GOGCCFLAGS")
50 cmd.Dir = modRoot
51 cmd.Stderr = new(strings.Builder)
52 cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
53 out, err := cmd.Output()
54 if err != nil {
55 t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
56 }
57 lines := strings.Split(string(out), "\n")
58 if len(lines) != 3 || lines[2] != "" {
59 t.Fatalf("Unexpected output from %s:\n%s", strings.Join(cmd.Args, " "), lines)
60 }
61
62 cc := lines[0]
63 if cc == "" {
64 t.Fatal("CC environment variable (go env CC) cannot be empty")
65 }
66 gogccflags := strings.Split(lines[1], " ")
67
68
69 ext := "so"
70 args := append(gogccflags, "-shared")
71 switch runtime.GOOS {
72 case "darwin", "ios":
73 ext = "dylib"
74 args = append(args, "-undefined", "suppress", "-flat_namespace")
75 case "windows":
76 ext = "dll"
77 args = append(args, "-DEXPORT_DLL")
78
79
80
81 args = append(args, "-Wl,-out-implib,libcgosotest.a")
82 case "aix":
83 ext = "so.1"
84 }
85 sofname := "libcgosotest." + ext
86 args = append(args, "-o", sofname, "cgoso_c.c")
87
88 cmd = exec.Command(cc, args...)
89 cmd.Dir = modRoot
90 cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
91 out, err = cmd.CombinedOutput()
92 if err != nil {
93 t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
94 }
95 t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
96
97 if runtime.GOOS == "aix" {
98
99 cmd = exec.Command("ar", "-X64", "-q", "libcgosotest.a", "libcgosotest.so.1")
100 cmd.Dir = modRoot
101 out, err = cmd.CombinedOutput()
102 if err != nil {
103 t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
104 }
105 }
106
107 cmd = exec.Command("go", "build", "-o", "main.exe", "main.go")
108 cmd.Dir = modRoot
109 cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
110 out, err = cmd.CombinedOutput()
111 if err != nil {
112 t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
113 }
114 t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
115
116 cmd = exec.Command("./main.exe")
117 cmd.Dir = modRoot
118 cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
119 if runtime.GOOS != "windows" {
120 s := "LD_LIBRARY_PATH"
121 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
122 s = "DYLD_LIBRARY_PATH"
123 }
124 cmd.Env = append(os.Environ(), s+"=.")
125
126
127
128 if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" {
129 cmd.Env = append(cmd.Env, "LD_32_LIBRARY_PATH=.")
130 }
131 }
132 out, err = cmd.CombinedOutput()
133 if err != nil {
134 t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
135 }
136 t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
137 }
138
View as plain text