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