From c0aacdcf8a75fbe78688583ea3b344a7ef50a95d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 16 Mar 2023 17:45:02 -0700 Subject: [PATCH] cmd/go: import runtime/cgo when externally linking Fixes #31544 Change-Id: Ic99875ad227876eb741e93653589310327c9c0ca Reviewed-on: https://go-review.googlesource.com/c/go/+/477195 TryBot-Result: Gopher Robot Run-TryBot: Ian Lance Taylor Reviewed-by: Bryan Mills Auto-Submit: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor --- src/cmd/go/internal/load/pkg.go | 29 +++++++++++++--- src/cmd/go/testdata/script/build_static.txt | 38 +++++++++++++++++++++ 2 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 src/cmd/go/testdata/script/build_static.txt diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 40278dda4d..922dc99e69 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -684,6 +684,15 @@ const ( // GetTestDeps is for download (part of "go get") and indicates // that test dependencies should be fetched too. GetTestDeps + + // The remainder are internal modes for calls to loadImport. + + // cmdlinePkg is for a package mentioned on the command line. + cmdlinePkg + + // cmdlinePkgLiteral is for a package mentioned on the command line + // without using any wildcards or meta-patterns. + cmdlinePkgLiteral ) // LoadImport scans the directory named by path, which must be an import path, @@ -738,18 +747,30 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi return p } + setCmdline := func(p *Package) { + if mode&cmdlinePkg != 0 { + p.Internal.CmdlinePkg = true + } + if mode&cmdlinePkgLiteral != 0 { + p.Internal.CmdlinePkgLiteral = true + } + } + importPath := bp.ImportPath p := packageCache[importPath] if p != nil { stk.Push(path) p = reusePackage(p, stk) stk.Pop() + setCmdline(p) } else { p = new(Package) p.Internal.Local = build.IsLocalImport(path) p.ImportPath = importPath packageCache[importPath] = p + setCmdline(p) + // Load package. // loadPackageData may return bp != nil even if an error occurs, // in order to return partial information. @@ -2849,15 +2870,15 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) if pkg == "" { panic(fmt.Sprintf("ImportPaths returned empty package for pattern %s", m.Pattern())) } - p := loadImport(ctx, opts, pre, pkg, base.Cwd(), nil, &stk, nil, 0) - p.Match = append(p.Match, m.Pattern()) - p.Internal.CmdlinePkg = true + mode := cmdlinePkg if m.IsLiteral() { // Note: do not set = m.IsLiteral unconditionally // because maybe we'll see p matching both // a literal and also a non-literal pattern. - p.Internal.CmdlinePkgLiteral = true + mode |= cmdlinePkgLiteral } + p := loadImport(ctx, opts, pre, pkg, base.Cwd(), nil, &stk, nil, mode) + p.Match = append(p.Match, m.Pattern()) if seenPkg[p] { continue } diff --git a/src/cmd/go/testdata/script/build_static.txt b/src/cmd/go/testdata/script/build_static.txt new file mode 100644 index 0000000000..611d94db4d --- /dev/null +++ b/src/cmd/go/testdata/script/build_static.txt @@ -0,0 +1,38 @@ +# This test requires external linking. Assume that if cgo is supported +# then external linking works. +[!cgo] skip 'links and runs binaries' + +# Only run on Unix systems that support -static. +[GOOS:windows] skip +[GOOS:plan9] skip + +# Ordinary build should work. +go build +exec ./hello +stdout Hello + +# Building with -linkmode=external should not say anything about +# runtime/cgo (issue #31544). +go build -ldflags=-linkmode=external +! stderr runtime/cgo +exec ./hello +stdout Hello + +# Building with -linkmode=external -extldflags=-static should work. +go build -ldflags='-linkmode=external -extldflags=-static' +! stderr runtime/cgo +exec ./hello +stdout Hello + +-- go.mod -- +module hello + +go 1.20 +-- hello.go -- +package main + +import "fmt" + +func main() { + fmt.Println("Hello, world") +} -- 2.50.0