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  }