github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/misc/cgo/testso/so_test.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build cgo 6 7 package so_test 8 9 import ( 10 "io/ioutil" 11 "log" 12 "os" 13 "os/exec" 14 "path/filepath" 15 "runtime" 16 "strings" 17 "testing" 18 ) 19 20 func requireTestSOSupported(t *testing.T) { 21 t.Helper() 22 switch runtime.GOARCH { 23 case "arm", "arm64": 24 if runtime.GOOS == "darwin" { 25 t.Skip("No exec facility on iOS.") 26 } 27 case "ppc64": 28 if runtime.GOOS == "linux" { 29 t.Skip("External linking not implemented on aix/ppc64 (issue #8912).") 30 } 31 case "mips64le", "mips64": 32 t.Skip("External linking not implemented on mips64.") 33 } 34 if runtime.GOOS == "android" { 35 t.Skip("No exec facility on Android.") 36 } 37 } 38 39 func TestSO(t *testing.T) { 40 requireTestSOSupported(t) 41 42 GOPATH, err := ioutil.TempDir("", "cgosotest") 43 if err != nil { 44 log.Fatal(err) 45 } 46 defer os.RemoveAll(GOPATH) 47 48 modRoot := filepath.Join(GOPATH, "src", "cgosotest") 49 if err := overlayDir(modRoot, "testdata"); err != nil { 50 log.Panic(err) 51 } 52 if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil { 53 log.Panic(err) 54 } 55 56 cmd := exec.Command("go", "env", "CC", "GOGCCFLAGS") 57 cmd.Dir = modRoot 58 cmd.Stderr = new(strings.Builder) 59 cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) 60 out, err := cmd.Output() 61 if err != nil { 62 t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) 63 } 64 lines := strings.Split(string(out), "\n") 65 if len(lines) != 3 || lines[2] != "" { 66 t.Fatalf("Unexpected output from %s:\n%s", strings.Join(cmd.Args, " "), lines) 67 } 68 69 cc := lines[0] 70 if cc == "" { 71 t.Fatal("CC environment variable (go env CC) cannot be empty") 72 } 73 gogccflags := strings.Split(lines[1], " ") 74 75 // build shared object 76 ext := "so" 77 args := append(gogccflags, "-shared") 78 switch runtime.GOOS { 79 case "darwin": 80 ext = "dylib" 81 args = append(args, "-undefined", "suppress", "-flat_namespace") 82 case "windows": 83 ext = "dll" 84 args = append(args, "-DEXPORT_DLL") 85 case "aix": 86 ext = "so.1" 87 } 88 sofname := "libcgosotest." + ext 89 args = append(args, "-o", sofname, "cgoso_c.c") 90 91 cmd = exec.Command(cc, args...) 92 cmd.Dir = modRoot 93 cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) 94 out, err = cmd.CombinedOutput() 95 if err != nil { 96 t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) 97 } 98 t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) 99 100 if runtime.GOOS == "aix" { 101 // Shared object must be wrapped by an archive 102 cmd = exec.Command("ar", "-X64", "-q", "libcgosotest.a", "libcgosotest.so.1") 103 cmd.Dir = modRoot 104 out, err = cmd.CombinedOutput() 105 if err != nil { 106 t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) 107 } 108 } 109 110 cmd = exec.Command("go", "build", "-o", "main.exe", "main.go") 111 cmd.Dir = modRoot 112 cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) 113 out, err = cmd.CombinedOutput() 114 if err != nil { 115 t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) 116 } 117 t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) 118 119 cmd = exec.Command("./main.exe") 120 cmd.Dir = modRoot 121 cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) 122 if runtime.GOOS != "windows" { 123 s := "LD_LIBRARY_PATH" 124 if runtime.GOOS == "darwin" { 125 s = "DYLD_LIBRARY_PATH" 126 } 127 cmd.Env = append(os.Environ(), s+"=.") 128 129 // On FreeBSD 64-bit architectures, the 32-bit linker looks for 130 // different environment variables. 131 if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" { 132 cmd.Env = append(cmd.Env, "LD_32_LIBRARY_PATH=.") 133 } 134 } 135 out, err = cmd.CombinedOutput() 136 if err != nil { 137 t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) 138 } 139 t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) 140 }