mirror of
https://github.com/golang/go
synced 2024-11-14 23:40:35 -07:00
cmd/cgo, cmd/go: add cgo -ldflags option, use it in cmd/go
This will automatically use a response file if ldflags is long, avoiding "argument list too long" errors with a very large CGO_LDFLAGS. Fixes #66456 Change-Id: I5f9ee86e03b4e6d6430f7f9d8357ef37a9c22465 Reviewed-on: https://go-review.googlesource.com/c/go/+/584655 Reviewed-by: Michael Matloob <matloob@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Commit-Queue: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
f4494522dc
commit
a32e94d43e
@ -529,6 +529,9 @@ The following options are available when running cgo directly:
|
||||
Write out input file in Go syntax replacing C package
|
||||
names with real values. Used to generate files in the
|
||||
syscall package when bootstrapping a new target.
|
||||
-ldflags flags
|
||||
Flags to pass to the C linker. The cmd/go tool uses
|
||||
this to pass in the flags in the CGO_LDFLAGS variable.
|
||||
-objdir directory
|
||||
Put all generated files in directory.
|
||||
-srcdir directory
|
||||
|
@ -242,6 +242,8 @@ var objDir = flag.String("objdir", "", "object directory")
|
||||
var importPath = flag.String("importpath", "", "import path of package being built (for comments in generated files)")
|
||||
var exportHeader = flag.String("exportheader", "", "where to write export header if any exported functions")
|
||||
|
||||
var ldflags = flag.String("ldflags", "", "flags to pass to C linker")
|
||||
|
||||
var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
|
||||
var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
|
||||
var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo")
|
||||
@ -328,11 +330,11 @@ func main() {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// Record CGO_LDFLAGS from the environment for external linking.
|
||||
if ldflags := os.Getenv("CGO_LDFLAGS"); ldflags != "" {
|
||||
args, err := splitQuoted(ldflags)
|
||||
// Record linker flags for external linking.
|
||||
if *ldflags != "" {
|
||||
args, err := splitQuoted(*ldflags)
|
||||
if err != nil {
|
||||
fatalf("bad CGO_LDFLAGS: %q (%s)", ldflags, err)
|
||||
fatalf("bad -ldflags option: %q (%s)", *ldflags, err)
|
||||
}
|
||||
p.addToFlag("LDFLAGS", args)
|
||||
}
|
||||
|
@ -2812,7 +2812,10 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
|
||||
cgoflags = append(cgoflags, "-import_syscall=false")
|
||||
}
|
||||
|
||||
// Update $CGO_LDFLAGS with p.CgoLDFLAGS.
|
||||
// cgoLDFLAGS, which includes p.CgoLDFLAGS, can be very long.
|
||||
// Pass it to cgo on the command line, so that we use a
|
||||
// response file if necessary.
|
||||
//
|
||||
// These flags are recorded in the generated _cgo_gotypes.go file
|
||||
// using //go:cgo_ldflag directives, the compiler records them in the
|
||||
// object file for the package, and then the Go linker passes them
|
||||
@ -2820,12 +2823,16 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
|
||||
// consists of the original $CGO_LDFLAGS (unchecked) and all the
|
||||
// flags put together from source code (checked).
|
||||
cgoenv := b.cCompilerEnv()
|
||||
var ldflagsOption []string
|
||||
if len(cgoLDFLAGS) > 0 {
|
||||
flags := make([]string, len(cgoLDFLAGS))
|
||||
for i, f := range cgoLDFLAGS {
|
||||
flags[i] = strconv.Quote(f)
|
||||
}
|
||||
cgoenv = append(cgoenv, "CGO_LDFLAGS="+strings.Join(flags, " "))
|
||||
ldflagsOption = []string{"-ldflags=" + strings.Join(flags, " ")}
|
||||
|
||||
// Remove CGO_LDFLAGS from the environment.
|
||||
cgoenv = append(cgoenv, "CGO_LDFLAGS=")
|
||||
}
|
||||
|
||||
if cfg.BuildToolchainName == "gccgo" {
|
||||
@ -2863,7 +2870,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
|
||||
cgoflags = append(cgoflags, "-trimpath", strings.Join(trimpath, ";"))
|
||||
}
|
||||
|
||||
if err := sh.run(p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
|
||||
if err := sh.run(p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, ldflagsOption, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
outGo = append(outGo, gofiles...)
|
||||
|
46
src/cmd/go/testdata/script/cgo_long_cmd.txt
vendored
Normal file
46
src/cmd/go/testdata/script/cgo_long_cmd.txt
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
# Issue #66456
|
||||
|
||||
[!cgo] skip
|
||||
[GOOS:windows] skip
|
||||
[GOOS:plan9] skip
|
||||
|
||||
# Generate a file with a very long #cgo LDFLAGS line.
|
||||
# This used to cause "go build" to fail with "argument list too long".
|
||||
go generate
|
||||
|
||||
# Build with the generated file.
|
||||
go build
|
||||
|
||||
-- go.mod --
|
||||
module cgolongcmd
|
||||
|
||||
go 1.22
|
||||
-- generate.go --
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("package p\n")
|
||||
buf.WriteString("// #cgo LDFLAGS:")
|
||||
for i := range 10000 {
|
||||
fmt.Fprintf(&buf, " -Wl,-rpath,/nonexistentpath/%d", i)
|
||||
}
|
||||
buf.WriteString("\n")
|
||||
buf.WriteString(`import "C"`+"\n")
|
||||
if err := os.WriteFile("generated.go", buf.Bytes(), 0o644); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
-- gen.go --
|
||||
package p
|
||||
|
||||
//go:generate go run generate.go
|
Loading…
Reference in New Issue
Block a user