github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/cmd/link/internal/ld/config.go (about) 1 // Copyright 2016 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 package ld 6 7 import ( 8 "cmd/internal/obj" 9 "cmd/internal/sys" 10 "fmt" 11 "log" 12 ) 13 14 var ( 15 Linkmode LinkMode 16 Buildmode BuildMode 17 ) 18 19 // A BuildMode indicates the sort of object we are building. 20 // 21 // Possible build modes are the same as those for the -buildmode flag 22 // in cmd/go, and are documented in 'go help buildmode'. 23 type BuildMode uint8 24 25 const ( 26 BuildmodeUnset BuildMode = iota 27 BuildmodeExe 28 BuildmodePIE 29 BuildmodeCArchive 30 BuildmodeCShared 31 BuildmodeShared 32 BuildmodePlugin 33 ) 34 35 func (mode *BuildMode) Set(s string) error { 36 badmode := func() error { 37 return fmt.Errorf("buildmode %s not supported on %s/%s", s, obj.GOOS, obj.GOARCH) 38 } 39 switch s { 40 default: 41 return fmt.Errorf("invalid buildmode: %q", s) 42 case "exe": 43 *mode = BuildmodeExe 44 case "pie": 45 switch obj.GOOS { 46 case "android", "linux": 47 default: 48 return badmode() 49 } 50 *mode = BuildmodePIE 51 case "c-archive": 52 switch obj.GOOS { 53 case "darwin", "linux": 54 case "windows": 55 switch obj.GOARCH { 56 case "amd64", "386": 57 default: 58 return badmode() 59 } 60 default: 61 return badmode() 62 } 63 *mode = BuildmodeCArchive 64 case "c-shared": 65 switch obj.GOARCH { 66 case "386", "amd64", "arm", "arm64": 67 default: 68 return badmode() 69 } 70 *mode = BuildmodeCShared 71 case "shared": 72 switch obj.GOOS { 73 case "linux": 74 switch obj.GOARCH { 75 case "386", "amd64", "arm", "arm64", "ppc64le", "s390x": 76 default: 77 return badmode() 78 } 79 default: 80 return badmode() 81 } 82 *mode = BuildmodeShared 83 case "plugin": 84 switch obj.GOOS { 85 case "linux": 86 switch obj.GOARCH { 87 case "386", "amd64", "arm", "arm64": 88 default: 89 return badmode() 90 } 91 case "darwin": 92 switch obj.GOARCH { 93 case "amd64": 94 default: 95 return badmode() 96 } 97 default: 98 return badmode() 99 } 100 *mode = BuildmodePlugin 101 } 102 return nil 103 } 104 105 func (mode *BuildMode) String() string { 106 switch *mode { 107 case BuildmodeUnset: 108 return "" // avoid showing a default in usage message 109 case BuildmodeExe: 110 return "exe" 111 case BuildmodePIE: 112 return "pie" 113 case BuildmodeCArchive: 114 return "c-archive" 115 case BuildmodeCShared: 116 return "c-shared" 117 case BuildmodeShared: 118 return "shared" 119 case BuildmodePlugin: 120 return "plugin" 121 } 122 return fmt.Sprintf("BuildMode(%d)", uint8(*mode)) 123 } 124 125 // LinkMode indicates whether an external linker is used for the final link. 126 type LinkMode uint8 127 128 const ( 129 LinkAuto LinkMode = iota 130 LinkInternal 131 LinkExternal 132 ) 133 134 func (mode *LinkMode) Set(s string) error { 135 switch s { 136 default: 137 return fmt.Errorf("invalid linkmode: %q", s) 138 case "auto": 139 *mode = LinkAuto 140 case "internal": 141 *mode = LinkInternal 142 case "external": 143 *mode = LinkExternal 144 } 145 return nil 146 } 147 148 func (mode *LinkMode) String() string { 149 switch *mode { 150 case LinkAuto: 151 return "auto" 152 case LinkInternal: 153 return "internal" 154 case LinkExternal: 155 return "external" 156 } 157 return fmt.Sprintf("LinkMode(%d)", uint8(*mode)) 158 } 159 160 // mustLinkExternal reports whether the program being linked requires 161 // the external linker be used to complete the link. 162 func mustLinkExternal(ctxt *Link) (res bool, reason string) { 163 if ctxt.Debugvlog > 1 { 164 defer func() { 165 if res { 166 log.Printf("external linking is forced by: %s\n", reason) 167 } 168 }() 169 } 170 171 switch obj.GOOS { 172 case "android": 173 return true, "android" 174 case "darwin": 175 if SysArch.InFamily(sys.ARM, sys.ARM64) { 176 return true, "iOS" 177 } 178 } 179 180 if *flagMsan { 181 return true, "msan" 182 } 183 184 // Internally linking cgo is incomplete on some architectures. 185 // https://golang.org/issue/10373 186 // https://golang.org/issue/14449 187 if iscgo && SysArch.InFamily(sys.ARM64, sys.MIPS64) { 188 return true, obj.GOARCH + " does not support internal cgo" 189 } 190 191 // Some build modes require work the internal linker cannot do (yet). 192 switch Buildmode { 193 case BuildmodeCArchive: 194 return true, "buildmode=c-archive" 195 case BuildmodeCShared: 196 return true, "buildmode=c-shared" 197 case BuildmodePIE: 198 switch obj.GOOS + "/" + obj.GOARCH { 199 case "linux/amd64": 200 default: 201 // Internal linking does not support TLS_IE. 202 return true, "buildmode=pie" 203 } 204 case BuildmodePlugin: 205 return true, "buildmode=plugin" 206 case BuildmodeShared: 207 return true, "buildmode=shared" 208 } 209 if *FlagLinkshared { 210 return true, "dynamically linking with a shared library" 211 } 212 213 return false, "" 214 } 215 216 // determineLinkMode sets Linkmode. 217 // 218 // It is called after flags are processed and inputs are processed, 219 // so the Linkmode variable has an initial value from the -linkmode 220 // flag and the iscgo externalobj variables are set. 221 func determineLinkMode(ctxt *Link) { 222 switch Linkmode { 223 case LinkAuto: 224 // The environment variable GO_EXTLINK_ENABLED controls the 225 // default value of -linkmode. If it is not set when the 226 // linker is called we take the value it was set to when 227 // cmd/link was compiled. (See make.bash.) 228 switch obj.Getgoextlinkenabled() { 229 case "0": 230 if needed, reason := mustLinkExternal(ctxt); needed { 231 Exitf("internal linking requested via GO_EXTLINK_ENABLED, but external linking required: %s", reason) 232 } 233 Linkmode = LinkInternal 234 case "1": 235 Linkmode = LinkExternal 236 default: 237 if needed, _ := mustLinkExternal(ctxt); needed { 238 Linkmode = LinkExternal 239 } else if iscgo && externalobj { 240 Linkmode = LinkExternal 241 } else { 242 Linkmode = LinkInternal 243 } 244 } 245 case LinkInternal: 246 if needed, reason := mustLinkExternal(ctxt); needed { 247 Exitf("internal linking requested but external linking required: %s", reason) 248 } 249 } 250 }