Skip to content

Commit 1aa2af7

Browse files
committed
Fix linker error if go_library with cgo references unresolved symbol
Before this commit, if a go_library referenced an unresolved C symbol, the build would fail with an error about an undefined symbol since compilepkg.go tries to link all object files into an executable to be consumed by cgo's -dynimport argument. Since this library is never used for any purpose other than having its symbols parsed by the cgo command, retry with additional linker flags intended to make the linker ignore unresolved symbols. If they remain missing in the real link step, they will still be reported as unresolved there. Fixes golang/go#25832 for rules_go.
1 parent e43a3bc commit 1aa2af7

File tree

4 files changed

+66
-1
lines changed

4 files changed

+66
-1
lines changed

go/tools/builders/cgo2.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,30 @@ func cgo2(goenv *env, goSrcs, cgoSrcs, cSrcs, cxxSrcs, objcSrcs, objcxxSrcs, sSr
197197
args = append([]string{cc, "-o", mainBin, mainObj}, cObjs...)
198198
args = append(args, combinedLdFlags...)
199199
if err := goenv.runCommand(args); err != nil {
200-
return "", nil, nil, err
200+
// If linking the binary for cgo fails, this is usually because the
201+
// object files reference external symbols that can't be resolved yet.
202+
// Since the binary is only produced to have its symbols read by the cgo
203+
// command, there is no harm in trying to build it allowing unresolved
204+
// symbols - the real link that happens at the end will fail if they
205+
// rightfully can't be resolved.
206+
var allowUnresolvedSymbolsLdFlag string
207+
switch os.Getenv("GOOS") {
208+
case "windows":
209+
// MinGW's linker doesn't seem to support --unresolved-symbols
210+
// and MSVC isn't supported at all.
211+
return "", nil, nil, err
212+
case "darwin", "ios":
213+
allowUnresolvedSymbolsLdFlag = "-Wl,-undefined,dynamic_lookup"
214+
default:
215+
allowUnresolvedSymbolsLdFlag = "-Wl,--unresolved-symbols=ignore-all"
216+
}
217+
if err2 := goenv.runCommand(append(args, allowUnresolvedSymbolsLdFlag)); err2 != nil {
218+
// Return the original error if we can't link the binary with the
219+
// additional linker flags as they may simply be incorrect for the
220+
// particular compiler/linker pair and would obscure the true reason
221+
// for the failure of the original command.
222+
return "", nil, nil, err
223+
}
201224
}
202225

203226
cgoImportsGo := filepath.Join(workDir, "_cgo_imports.go")

tests/core/cgo/BUILD.bazel

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,23 @@ go_bazel_test(
414414
name = "external_includes_test",
415415
srcs = ["external_includes_test.go"],
416416
)
417+
418+
go_library(
419+
name = "use_external_symbol",
420+
srcs = ["use_external_symbol.go"],
421+
cgo = True,
422+
importpath = "github.com/bazelbuild/rules_go/tests/core/cgo/use_external_symbol",
423+
tags = ["manual"],
424+
)
425+
426+
go_binary(
427+
name = "provide_external_symbol",
428+
srcs = ["provide_external_symbol.go"],
429+
cgo = True,
430+
target_compatible_with = select({
431+
"@platforms//os:osx": [],
432+
"@platforms//os:linux": [],
433+
"//conditions:default": ["@platforms//:incompatible"],
434+
}),
435+
deps = [":use_external_symbol"],
436+
)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package main
2+
3+
import "C"
4+
5+
import "github.com/bazelbuild/rules_go/tests/core/cgo/use_external_symbol"
6+
7+
//export external_symbol
8+
func external_symbol() {}
9+
10+
func main() {
11+
use_external_symbol.UseExternalSymbol()
12+
}

tests/core/cgo/use_external_symbol.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package use_external_symbol
2+
3+
/*
4+
void external_symbol();
5+
*/
6+
import "C"
7+
8+
func UseExternalSymbol() {
9+
C.external_symbol()
10+
}

0 commit comments

Comments
 (0)