1
0
mirror of https://github.com/golang/go synced 2024-11-18 22:44:48 -07:00

cmd/go: error out of linking package main if cgo is required but not enabled

Fixes #46330.
Fixes #62123.
Updates #31544.

Change-Id: I023aa2bdb5a24e126a0de5192a077e8cf1a0a67c
Reviewed-on: https://go-review.googlesource.com/c/go/+/522239
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Bryan C. Mills 2023-08-23 16:32:46 -04:00 committed by Gopher Robot
parent 2763146099
commit 079dfdcac0
4 changed files with 57 additions and 23 deletions

View File

@ -1920,7 +1920,12 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *
// The linker loads implicit dependencies.
if p.Name == "main" && !p.Internal.ForceLibrary {
for _, dep := range LinkerDeps(p) {
ldDeps, err := LinkerDeps(p)
if err != nil {
setError(err)
return
}
for _, dep := range ldDeps {
addImport(dep, false)
}
}
@ -2556,12 +2561,15 @@ func SafeArg(name string) bool {
}
// LinkerDeps returns the list of linker-induced dependencies for main package p.
func LinkerDeps(p *Package) []string {
func LinkerDeps(p *Package) ([]string, error) {
// Everything links runtime.
deps := []string{"runtime"}
// External linking mode forces an import of runtime/cgo.
if externalLinkingForced(p) && cfg.BuildContext.Compiler != "gccgo" {
if what := externalLinkingReason(p); what != "" && cfg.BuildContext.Compiler != "gccgo" {
if !cfg.BuildContext.CgoEnabled {
return nil, fmt.Errorf("%s requires external (cgo) linking, but cgo is not enabled", what)
}
deps = append(deps, "runtime/cgo")
}
// On ARM with GOARM=5, it forces an import of math, for soft floating point.
@ -2585,30 +2593,27 @@ func LinkerDeps(p *Package) []string {
deps = append(deps, "runtime/coverage")
}
return deps
return deps, nil
}
// externalLinkingForced reports whether external linking is being
// forced even for programs that do not use cgo.
func externalLinkingForced(p *Package) bool {
if !cfg.BuildContext.CgoEnabled {
return false
}
// externalLinkingForced reports the reason external linking is required
// even for programs that do not use cgo, or the empty string if external
// linking is not required.
func externalLinkingReason(p *Package) (what string) {
// Some targets must use external linking even inside GOROOT.
if platform.MustLinkExternal(cfg.BuildContext.GOOS, cfg.BuildContext.GOARCH, false) {
return true
if platform.MustLinkExternal(cfg.Goos, cfg.Goarch, false) {
return cfg.Goos + "/" + cfg.Goarch
}
// Some build modes always require external linking.
switch cfg.BuildBuildmode {
case "c-shared", "plugin":
return true
return "-buildmode=" + cfg.BuildBuildmode
}
// Using -linkshared always requires external linking.
if cfg.BuildLinkshared {
return true
return "-linkshared"
}
// Decide whether we are building a PIE,
@ -2623,27 +2628,29 @@ func externalLinkingForced(p *Package) bool {
// that does not support PIE with internal linking mode,
// then we must use external linking.
if isPIE && !platform.InternalLinkPIESupported(cfg.BuildContext.GOOS, cfg.BuildContext.GOARCH) {
return true
if cfg.BuildBuildmode == "pie" {
return "-buildmode=pie"
}
return "default PIE binary"
}
// Using -ldflags=-linkmode=external forces external linking.
// If there are multiple -linkmode options, the last one wins.
linkmodeExternal := false
if p != nil {
ldflags := BuildLdflags.For(p)
for i := len(ldflags) - 1; i >= 0; i-- {
a := ldflags[i]
if a == "-linkmode=external" ||
a == "-linkmode" && i+1 < len(ldflags) && ldflags[i+1] == "external" {
linkmodeExternal = true
break
return a
} else if a == "-linkmode=internal" ||
a == "-linkmode" && i+1 < len(ldflags) && ldflags[i+1] == "internal" {
break
return ""
}
}
}
return linkmodeExternal
return ""
}
// mkAbs rewrites list, which must be paths relative to p.Dir,

View File

@ -298,7 +298,11 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p
// Also the linker introduces implicit dependencies reported by LinkerDeps.
stk.Push("testmain")
deps := TestMainDeps // cap==len, so safe for append
for _, d := range LinkerDeps(p) {
ldDeps, err := LinkerDeps(p)
if err != nil && pmain.Error == nil {
pmain.Error = &PackageError{Err: err}
}
for _, d := range ldDeps {
deps = append(deps, d)
}
for _, dep := range deps {

View File

@ -853,7 +853,11 @@ func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Ac
// The linker step still needs all the usual linker deps.
// (For example, the linker always opens runtime.a.)
for _, dep := range load.LinkerDeps(nil) {
ldDeps, err := load.LinkerDeps(nil)
if err != nil {
base.Error(err)
}
for _, dep := range ldDeps {
add(a, dep, true)
}
}

View File

@ -0,0 +1,19 @@
env GOOS=android GOARCH=amd64 CGO_ENABLED=0
! go build -o $devnull cmd/buildid
stderr 'android/amd64 requires external \(cgo\) linking, but cgo is not enabled'
! stderr 'cannot find runtime/cgo'
! go test -c -o $devnull os
stderr '# os\nandroid/amd64 requires external \(cgo\) linking, but cgo is not enabled'
! stderr 'cannot find runtime/cgo'
env GOOS=ios GOARCH=arm64 CGO_ENABLED=0
! go build -o $devnull cmd/buildid
stderr 'ios/arm64 requires external \(cgo\) linking, but cgo is not enabled'
! stderr 'cannot find runtime/cgo'
! go test -c -o $devnull os
stderr '# os\nios/arm64 requires external \(cgo\) linking, but cgo is not enabled'
! stderr 'cannot find runtime/cgo'