Source file
src/cmd/link/cgo_test.go
1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "fmt"
10 "internal/testenv"
11 "os"
12 "os/exec"
13 "path/filepath"
14 "testing"
15 )
16
17
18 func TestCGOLTO(t *testing.T) {
19 testenv.MustHaveCGO(t)
20 testenv.MustHaveGoBuild(t)
21
22 t.Parallel()
23
24 for _, cc := range []string{"gcc", "clang"} {
25 for test := 0; test < 2; test++ {
26 t.Run(fmt.Sprintf("%s-%d", cc, test), func(t *testing.T) {
27 testCGOLTO(t, cc, test)
28 })
29 }
30 }
31 }
32
33 const test1_main = `
34 package main
35
36 /*
37 extern int myadd(int, int);
38 int c_add(int a, int b) {
39 return myadd(a, b);
40 }
41 */
42 import "C"
43
44 func main() {
45 println(C.c_add(1, 2))
46 }
47 `
48
49 const test1_add = `
50 package main
51
52 import "C"
53
54 /* test */
55
56 //export myadd
57 func myadd(a C.int, b C.int) C.int {
58 return a + b
59 }
60 `
61
62 const test2_main = `
63 package main
64
65 import "fmt"
66
67 /*
68 #include <stdio.h>
69
70 void hello(void) {
71 printf("hello\n");
72 }
73 */
74 import "C"
75
76 func main() {
77 hello := C.hello
78 fmt.Printf("%v\n", hello)
79 }
80 `
81
82 func testCGOLTO(t *testing.T, cc string, test int) {
83 t.Parallel()
84
85 if _, err := exec.LookPath(cc); err != nil {
86 t.Skipf("no %s compiler", cc)
87 }
88
89 dir := t.TempDir()
90
91 writeTempFile := func(name, contents string) {
92 if err := os.WriteFile(filepath.Join(dir, name), []byte(contents), 0644); err != nil {
93 t.Fatal(err)
94 }
95 }
96
97 writeTempFile("go.mod", "module cgolto\n")
98
99 switch test {
100 case 0:
101 writeTempFile("main.go", test1_main)
102 writeTempFile("add.go", test1_add)
103 case 1:
104 writeTempFile("main.go", test2_main)
105 default:
106 t.Fatalf("bad case %d", test)
107 }
108
109 cmd := exec.Command(testenv.GoToolPath(t), "build")
110 cmd.Dir = dir
111 cmd.Env = append(os.Environ(),
112 "CC="+cc,
113 "CGO_CFLAGS=-flto",
114 )
115
116 t.Log("go build")
117 out, err := cmd.CombinedOutput()
118 t.Logf("%s", out)
119
120 if err != nil {
121 t.Logf("go build failed: %v", err)
122
123
124
125 var noLTO = []string{
126 `unrecognized command line option "-flto"`,
127 "unable to pass LLVM bit-code files to linker",
128 "file not recognized: File format not recognized",
129 "LTO support has not been enabled",
130 "linker command failed with exit code",
131 "gcc: can't load library",
132 }
133 for _, msg := range noLTO {
134 if bytes.Contains(out, []byte(msg)) {
135 t.Skipf("C compiler %v does not support LTO", cc)
136 }
137 }
138
139 t.Error("failed")
140 }
141 }
142
View as plain text