Skip to content

Commit

Permalink
cmd/go: import runtime/cgo when externally linking
Browse files Browse the repository at this point in the history
Restore CL 477195, which was reverted in CL 477795.
This version includes CL 477397, which fixes the test problems
with CL 477195. CL 477397 was not submitted because it had an
unrelated failure on darwin-amd64. That failure is fixed by CL 477736.

Fixes #31544

Change-Id: I3a2258cd0ca295cede3511ab212e56fd0114f94a
Reviewed-on: https://go-review.googlesource.com/c/go/+/477839
Reviewed-by: Bryan Mills <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
Run-TryBot: Ian Lance Taylor <[email protected]>
Auto-Submit: Ian Lance Taylor <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
  • Loading branch information
ianlancetaylor authored and gopherbot committed Mar 20, 2023
1 parent 86ad2d5 commit c7f5b35
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 4 deletions.
29 changes: 25 additions & 4 deletions src/cmd/go/internal/load/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
Expand Down
44 changes: 44 additions & 0 deletions src/cmd/go/testdata/script/build_static.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[short] skip 'links and runs binaries'

# This test requires external linking. Assume that if cgo is supported
# then external linking works.
[!cgo] skip 'requires a C linker'

# Only run on Unix systems.
[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

# Some targets don't support -static
[GOOS:darwin] skip 'no static linking on Darwin'
[GOOS:solaris] skip 'no static linking on Solaris'

# 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")
}

0 comments on commit c7f5b35

Please sign in to comment.