]> Cypherpunks.ru repositories - gostls13.git/blob - test/linkobj.go
[dev.ssa] Merge branch 'master' into dev.ssa
[gostls13.git] / test / linkobj.go
1 // +build !nacl
2 // run
3
4 // Copyright 2016 The Go Authors. All rights reserved.
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file.
7
8 // Test the compiler -linkobj flag.
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         // two rounds: once using normal objects, again using .a files (compile -pack).
69         for round := 0; round < 2; round++ {
70                 pkg := "-pack=" + fmt.Sprint(round)
71
72                 // The compiler expects the files being read to have the right suffix.
73                 o := "o"
74                 if round == 1 {
75                         o = "a"
76                 }
77
78                 // inlining is disabled to make sure that the link objects contain needed code.
79                 run("go", "tool", "compile", pkg, "-D", ".", "-I", ".", "-l", "-o", "p1."+o, "-linkobj", "p1.lo", "p1.go")
80                 run("go", "tool", "compile", pkg, "-D", ".", "-I", ".", "-l", "-o", "p2."+o, "-linkobj", "p2.lo", "p2.go")
81                 run("go", "tool", "compile", pkg, "-D", ".", "-I", ".", "-l", "-o", "p3."+o, "-linkobj", "p3.lo", "p3.go")
82
83                 cp("p1."+o, "p1.oo")
84                 cp("p2."+o, "p2.oo")
85                 cp("p3."+o, "p3.oo")
86                 cp("p1.lo", "p1."+o)
87                 cp("p2.lo", "p2."+o)
88                 cp("p3.lo", "p3."+o)
89                 out := runFail("go", "tool", "link", "p2."+o)
90                 if !strings.Contains(out, "not package main") {
91                         fatalf("link p2.o failed but not for package main:\n%s", out)
92                 }
93
94                 run("go", "tool", "link", "-L", ".", "-o", "a.out.exe", "p3."+o)
95                 out = run("./a.out.exe")
96                 if !strings.Contains(out, "hello from p1\nhello from p2\nhello from main\n") {
97                         fatalf("running main, incorrect output:\n%s", out)
98                 }
99
100                 // ensure that mistaken future round can't use these
101                 os.Remove("p1.o")
102                 os.Remove("a.out.exe")
103         }
104
105         cleanup()
106 }
107
108 func run(args ...string) string {
109         out, err := exec.Command(args[0], args[1:]...).CombinedOutput()
110         if err != nil {
111                 fatalf("run %v: %s\n%s", args, err, out)
112         }
113         return string(out)
114 }
115
116 func runFail(args ...string) string {
117         out, err := exec.Command(args[0], args[1:]...).CombinedOutput()
118         if err == nil {
119                 fatalf("runFail %v: unexpected success!\n%s", args, err, out)
120         }
121         return string(out)
122 }
123
124 func cp(src, dst string) {
125         data, err := ioutil.ReadFile(src)
126         if err != nil {
127                 fatalf("%v", err)
128         }
129         err = ioutil.WriteFile(dst, data, 0666)
130         if err != nil {
131                 fatalf("%v", err)
132         }
133 }
134
135 func writeFile(name, data string) {
136         err := ioutil.WriteFile(name, []byte(data), 0666)
137         if err != nil {
138                 fatalf("%v", err)
139         }
140 }
141
142 func cleanup() {
143         const debug = false
144         if debug {
145                 println("TMPDIR:", tmpdir)
146                 return
147         }
148         os.Chdir(pwd) // get out of tmpdir before removing it
149         os.RemoveAll(tmpdir)
150 }
151
152 func fatalf(format string, args ...interface{}) {
153         cleanup()
154         log.Fatalf(format, args...)
155 }