1
2
3
4
5 package ld
6
7 import (
8 "fmt"
9 "internal/buildcfg"
10 "internal/platform"
11 )
12
13
14
15
16
17 type BuildMode uint8
18
19 const (
20 BuildModeUnset BuildMode = iota
21 BuildModeExe
22 BuildModePIE
23 BuildModeCArchive
24 BuildModeCShared
25 BuildModeShared
26 BuildModePlugin
27 )
28
29
30
31 func (mode *BuildMode) Set(s string) error {
32 switch s {
33 default:
34 return fmt.Errorf("invalid buildmode: %q", s)
35 case "exe":
36 switch buildcfg.GOOS + "/" + buildcfg.GOARCH {
37 case "darwin/arm64", "windows/arm", "windows/arm64":
38 *mode = BuildModePIE
39 default:
40 *mode = BuildModeExe
41 }
42 case "pie":
43 *mode = BuildModePIE
44 case "c-archive":
45 *mode = BuildModeCArchive
46 case "c-shared":
47 *mode = BuildModeCShared
48 case "shared":
49 *mode = BuildModeShared
50 case "plugin":
51 *mode = BuildModePlugin
52 }
53
54 if !platform.BuildModeSupported("gc", s, buildcfg.GOOS, buildcfg.GOARCH) {
55 return fmt.Errorf("buildmode %s not supported on %s/%s", s, buildcfg.GOOS, buildcfg.GOARCH)
56 }
57
58 return nil
59 }
60
61 func (mode BuildMode) String() string {
62 switch mode {
63 case BuildModeUnset:
64 return ""
65 case BuildModeExe:
66 return "exe"
67 case BuildModePIE:
68 return "pie"
69 case BuildModeCArchive:
70 return "c-archive"
71 case BuildModeCShared:
72 return "c-shared"
73 case BuildModeShared:
74 return "shared"
75 case BuildModePlugin:
76 return "plugin"
77 }
78 return fmt.Sprintf("BuildMode(%d)", uint8(mode))
79 }
80
81
82 type LinkMode uint8
83
84 const (
85 LinkAuto LinkMode = iota
86 LinkInternal
87 LinkExternal
88 )
89
90 func (mode *LinkMode) Set(s string) error {
91 switch s {
92 default:
93 return fmt.Errorf("invalid linkmode: %q", s)
94 case "auto":
95 *mode = LinkAuto
96 case "internal":
97 *mode = LinkInternal
98 case "external":
99 *mode = LinkExternal
100 }
101 return nil
102 }
103
104 func (mode *LinkMode) String() string {
105 switch *mode {
106 case LinkAuto:
107 return "auto"
108 case LinkInternal:
109 return "internal"
110 case LinkExternal:
111 return "external"
112 }
113 return fmt.Sprintf("LinkMode(%d)", uint8(*mode))
114 }
115
116
117
118 func mustLinkExternal(ctxt *Link) (res bool, reason string) {
119 if ctxt.Debugvlog > 1 {
120 defer func() {
121 if res {
122 ctxt.Logf("external linking is forced by: %s\n", reason)
123 }
124 }()
125 }
126
127 if platform.MustLinkExternal(buildcfg.GOOS, buildcfg.GOARCH, false) {
128 return true, fmt.Sprintf("%s/%s requires external linking", buildcfg.GOOS, buildcfg.GOARCH)
129 }
130
131 if *flagMsan {
132 return true, "msan"
133 }
134
135 if *flagAsan {
136 return true, "asan"
137 }
138
139 if iscgo && platform.MustLinkExternal(buildcfg.GOOS, buildcfg.GOARCH, true) {
140 return true, buildcfg.GOARCH + " does not support internal cgo"
141 }
142
143
144 switch ctxt.BuildMode {
145 case BuildModeCArchive:
146 return true, "buildmode=c-archive"
147 case BuildModeCShared:
148 return true, "buildmode=c-shared"
149 case BuildModePIE:
150 if !platform.InternalLinkPIESupported(buildcfg.GOOS, buildcfg.GOARCH) {
151
152 return true, "buildmode=pie"
153 }
154 case BuildModePlugin:
155 return true, "buildmode=plugin"
156 case BuildModeShared:
157 return true, "buildmode=shared"
158 }
159 if ctxt.linkShared {
160 return true, "dynamically linking with a shared library"
161 }
162
163 if unknownObjFormat {
164 return true, "some input objects have an unrecognized file format"
165 }
166
167 if len(dynimportfail) > 0 {
168
169
170
171
172
173 return true, fmt.Sprintf("some packages could not be built to support internal linking (%v)", dynimportfail)
174 }
175
176 return false, ""
177 }
178
179
180
181
182
183
184 func determineLinkMode(ctxt *Link) {
185 extNeeded, extReason := mustLinkExternal(ctxt)
186 via := ""
187
188 if ctxt.LinkMode == LinkAuto {
189
190
191
192
193 switch buildcfg.Getgoextlinkenabled() {
194 case "0":
195 ctxt.LinkMode = LinkInternal
196 via = "via GO_EXTLINK_ENABLED "
197 case "1":
198 ctxt.LinkMode = LinkExternal
199 via = "via GO_EXTLINK_ENABLED "
200 default:
201 preferExternal := len(preferlinkext) != 0
202 if preferExternal && ctxt.Debugvlog > 0 {
203 ctxt.Logf("external linking prefer list is %v\n", preferlinkext)
204 }
205 if extNeeded || (iscgo && (externalobj || preferExternal)) {
206 ctxt.LinkMode = LinkExternal
207 } else {
208 ctxt.LinkMode = LinkInternal
209 }
210 }
211 }
212
213 switch ctxt.LinkMode {
214 case LinkInternal:
215 if extNeeded {
216 Exitf("internal linking requested %sbut external linking required: %s", via, extReason)
217 }
218 case LinkExternal:
219 switch {
220 case buildcfg.GOARCH == "ppc64" && buildcfg.GOOS == "linux":
221 Exitf("external linking not supported for %s/ppc64", buildcfg.GOOS)
222 }
223 }
224 }
225
View as plain text