Source file
test/linkobj.go
1
2
3
4
5
6
7
8
9
10 package main
11
12 import (
13 "fmt"
14 "io/ioutil"
15 "log"
16 "os"
17 "os/exec"
18 "strings"
19 )
20
21 var pwd, tmpdir string
22
23 func main() {
24 dir, err := ioutil.TempDir("", "go-test-linkobj-")
25 if err != nil {
26 log.Fatal(err)
27 }
28 pwd, err = os.Getwd()
29 if err != nil {
30 log.Fatal(err)
31 }
32 if err := os.Chdir(dir); err != nil {
33 os.RemoveAll(dir)
34 log.Fatal(err)
35 }
36 tmpdir = dir
37
38 writeFile("p1.go", `
39 package p1
40
41 func F() {
42 println("hello from p1")
43 }
44 `)
45 writeFile("p2.go", `
46 package p2
47
48 import "./p1"
49
50 func F() {
51 p1.F()
52 println("hello from p2")
53 }
54
55 func main() {}
56 `)
57 writeFile("p3.go", `
58 package main
59
60 import "./p2"
61
62 func main() {
63 p2.F()
64 println("hello from main")
65 }
66 `)
67
68 stdlibimportcfg, err := os.ReadFile(os.Getenv("STDLIB_IMPORTCFG"))
69 if err != nil {
70 fatalf("listing stdlib export files: %v", err)
71 }
72
73
74 for round := 0; round < 2; round++ {
75 pkg := "-pack=" + fmt.Sprint(round)
76
77
78 o := "o"
79 if round == 1 {
80 o = "a"
81 }
82
83 importcfg := string(stdlibimportcfg) + "\npackagefile p1=p1." + o + "\npackagefile p2=p2." + o
84 os.WriteFile("importcfg", []byte(importcfg), 0644)
85
86
87 run("go", "tool", "compile", "-p=p1", pkg, "-D", ".", "-importcfg=importcfg", "-l", "-o", "p1."+o, "-linkobj", "p1.lo", "p1.go")
88 run("go", "tool", "compile", "-p=p2", pkg, "-D", ".", "-importcfg=importcfg", "-l", "-o", "p2."+o, "-linkobj", "p2.lo", "p2.go")
89 run("go", "tool", "compile", "-p=main", pkg, "-D", ".", "-importcfg=importcfg", "-l", "-o", "p3."+o, "-linkobj", "p3.lo", "p3.go")
90
91 cp("p1."+o, "p1.oo")
92 cp("p2."+o, "p2.oo")
93 cp("p3."+o, "p3.oo")
94 cp("p1.lo", "p1."+o)
95 cp("p2.lo", "p2."+o)
96 cp("p3.lo", "p3."+o)
97 out := runFail("go", "tool", "link", "p2."+o)
98 if !strings.Contains(out, "not package main") {
99 fatalf("link p2.o failed but not for package main:\n%s", out)
100 }
101
102 run("go", "tool", "link", "-importcfg=importcfg", "-o", "a.out.exe", "p3."+o)
103 out = run("./a.out.exe")
104 if !strings.Contains(out, "hello from p1\nhello from p2\nhello from main\n") {
105 fatalf("running main, incorrect output:\n%s", out)
106 }
107
108
109 os.Remove("p1.o")
110 os.Remove("a.out.exe")
111 }
112
113 cleanup()
114 }
115
116 func run(args ...string) string {
117 out, err := exec.Command(args[0], args[1:]...).CombinedOutput()
118 if err != nil {
119 fatalf("run %v: %s\n%s", args, err, out)
120 }
121 return string(out)
122 }
123
124 func runFail(args ...string) string {
125 out, err := exec.Command(args[0], args[1:]...).CombinedOutput()
126 if err == nil {
127 fatalf("runFail %v: unexpected success!\n%s", args, err, out)
128 }
129 return string(out)
130 }
131
132 func cp(src, dst string) {
133 data, err := ioutil.ReadFile(src)
134 if err != nil {
135 fatalf("%v", err)
136 }
137 err = ioutil.WriteFile(dst, data, 0666)
138 if err != nil {
139 fatalf("%v", err)
140 }
141 }
142
143 func writeFile(name, data string) {
144 err := ioutil.WriteFile(name, []byte(data), 0666)
145 if err != nil {
146 fatalf("%v", err)
147 }
148 }
149
150 func cleanup() {
151 const debug = false
152 if debug {
153 println("TMPDIR:", tmpdir)
154 return
155 }
156 os.Chdir(pwd)
157 os.RemoveAll(tmpdir)
158 }
159
160 func fatalf(format string, args ...interface{}) {
161 cleanup()
162 log.Fatalf(format, args...)
163 }
164
View as plain text