]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: error out of linking package main if cgo is required but not enabled
authorBryan C. Mills <bcmills@google.com>
Wed, 23 Aug 2023 20:32:46 +0000 (16:32 -0400)
committerGopher Robot <gobot@golang.org>
Wed, 23 Aug 2023 21:55:28 +0000 (21:55 +0000)
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>

src/cmd/go/internal/load/pkg.go
src/cmd/go/internal/load/test.go
src/cmd/go/internal/work/action.go
src/cmd/go/testdata/script/test_android_issue62123.txt [new file with mode: 0644]

index 0abc09186dee5b585ff2089f248479a265bd4a72..1adc9220ba5e3137fd3dfcd808e1c62110763bb5 100644 (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,
index e9ed0d332bc64e1723f010f75841fbeb3695167a..de2caa312808512f9ff71886e5a8e962eded16f6 100644 (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 {
index d4d0a71e750e7173c2e86f7de4b65616ea41a97b..7bde857bcc8e5ccb340cafa471c93ec10256474b 100644 (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)
                        }
                }
diff --git a/src/cmd/go/testdata/script/test_android_issue62123.txt b/src/cmd/go/testdata/script/test_android_issue62123.txt
new file mode 100644 (file)
index 0000000..2f46a6b
--- /dev/null
@@ -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'