]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: use --no-gc-sections if available
authorMotiejus Jakštys <motiejus@jakstys.lt>
Wed, 25 May 2022 02:55:34 +0000 (02:55 +0000)
committerIan Lance Taylor <iant@google.com>
Thu, 26 May 2022 00:50:00 +0000 (00:50 +0000)
zig cc passes `--gc-sections` to the underlying linker, which then
causes undefined symbol errors when compiling with cgo but without C
code. Add `-Wl,--no-gc-sections` to make it work with zig cc. Minimal
example:

**main.go**

    package main
    import _ "runtime/cgo"
    func main() {}

Run (works after the patch, doesn't work before):

    CC="zig cc" go build main.go

Among the existing code, `src/runtime/testdata/testprognet` fails to
build:

    src/runtime/testdata/testprognet$ CC="zig cc" go build .
    net(.text): relocation target __errno_location not defined
    net(.text): relocation target getaddrinfo not defined
    net(.text): relocation target freeaddrinfo not defined
    net(.text): relocation target gai_strerror not defined
    runtime/cgo(.text): relocation target stderr not defined
    runtime/cgo(.text): relocation target fwrite not defined
    runtime/cgo(.text): relocation target vfprintf not defined
    runtime/cgo(.text): relocation target fputc not defined
    runtime/cgo(.text): relocation target abort not defined
    runtime/cgo(.text): relocation target pthread_create not defined
    runtime/cgo(.text): relocation target nanosleep not defined
    runtime/cgo(.text): relocation target pthread_detach not defined
    runtime/cgo(.text): relocation target stderr not defined
    runtime/cgo(.text): relocation target strerror not defined
    runtime/cgo(.text): relocation target fprintf not defined
    runtime/cgo(.text): relocation target abort not defined
    runtime/cgo(.text): relocation target pthread_mutex_lock not defined
    runtime/cgo(.text): relocation target pthread_cond_wait not defined
    runtime/cgo(.text): relocation target pthread_mutex_unlock not defined
    runtime/cgo(.text): relocation target pthread_cond_broadcast not defined
    runtime/cgo(.text): relocation target malloc not defined

With the patch both examples build as expected.

@ianlancetaylor suggested:

> It would be fine with me if somebody wants to send a cgo patch that
passes -Wl,--no-gc-sections, with a fallback if that option is not
supported.

... and this is what we are doing. Tested with zig
0.10.0-dev.2252+a4369918b

This is a continuation of CL 405414: the original one broke AIX and iOS
builds. To fix that, added `unknown option` to the list of strings
under lookup.

Fixes #52690

Change-Id: Id6743e1e759a02627b0fc6d2ac89bb69b706d04c
GitHub-Last-Rev: 86f227a14e9f326f1b461b641e4865bc4dc70780
GitHub-Pull-Request: golang/go#53028
Reviewed-on: https://go-review.googlesource.com/c/go/+/407814
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>

src/cmd/go/internal/work/exec.go

index 15b9e1ef45ca41391d7d2196193e904312f45d5e..2becc6d9460edb22b8210aadcdd4d333f8e0f0b4 100644 (file)
@@ -2528,6 +2528,13 @@ func (b *Builder) compilerCmd(compiler []string, incdir, workdir string) []strin
                a = append(a, "-Qunused-arguments")
        }
 
+       // zig cc passes --gc-sections to the underlying linker, which then causes
+       // undefined symbol errors when compiling with cgo but without C code.
+       // https://github.com/golang/go/issues/52690
+       if b.gccSupportsFlag(compiler, "-Wl,--no-gc-sections") {
+               a = append(a, "-Wl,--no-gc-sections")
+       }
+
        // disable word wrapping in error messages
        a = append(a, "-fmessage-length=0")
 
@@ -2584,7 +2591,12 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
        }
 
        tmp := os.DevNull
-       if runtime.GOOS == "windows" {
+
+       // On the iOS builder the command
+       //   $CC -Wl,--no-gc-sections -x c - -o /dev/null < /dev/null
+       // is failing with:
+       //   Unable to remove existing file: Invalid argument
+       if runtime.GOOS == "windows" || runtime.GOOS == "ios" {
                f, err := os.CreateTemp(b.WorkDir, "")
                if err != nil {
                        return false
@@ -2594,13 +2606,21 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
                defer os.Remove(tmp)
        }
 
-       // We used to write an empty C file, but that gets complicated with
-       // go build -n. We tried using a file that does not exist, but that
-       // fails on systems with GCC version 4.2.1; that is the last GPLv2
-       // version of GCC, so some systems have frozen on it.
-       // Now we pass an empty file on stdin, which should work at least for
-       // GCC and clang.
-       cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", tmp)
+       // We used to write an empty C file, but that gets complicated with go
+       // build -n. We tried using a file that does not exist, but that fails on
+       // systems with GCC version 4.2.1; that is the last GPLv2 version of GCC,
+       // so some systems have frozen on it. Now we pass an empty file on stdin,
+       // which should work at least for GCC and clang.
+       //
+       // If the argument is "-Wl,", then it's testing the linker. In that case,
+       // skip "-c". If it's not "-Wl,", then we are testing the compiler and
+       // can emit the linking step with "-c".
+       cmdArgs := str.StringList(compiler, flag)
+       if !strings.HasPrefix(flag, "-Wl,") /* linker flag */ {
+               cmdArgs = append(cmdArgs, "-c")
+       }
+       cmdArgs = append(cmdArgs, "-x", "c", "-", "-o", tmp)
+
        if cfg.BuildN || cfg.BuildX {
                b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs))
                if cfg.BuildN {
@@ -2613,12 +2633,16 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
        out, _ := cmd.CombinedOutput()
        // GCC says "unrecognized command line option".
        // clang says "unknown argument".
+       // tcc says "unsupported"
+       // AIX says "not recognized"
        // Older versions of GCC say "unrecognised debug output level".
        // For -fsplit-stack GCC says "'-fsplit-stack' is not supported".
        supported := !bytes.Contains(out, []byte("unrecognized")) &&
                !bytes.Contains(out, []byte("unknown")) &&
                !bytes.Contains(out, []byte("unrecognised")) &&
-               !bytes.Contains(out, []byte("is not supported"))
+               !bytes.Contains(out, []byte("is not supported")) &&
+               !bytes.Contains(out, []byte("not recognized")) &&
+               !bytes.Contains(out, []byte("unsupported"))
        b.flagCache[key] = supported
        return supported
 }