[zig ld] --gc-sections workaround + tests
`zig cc` emits `--gc-sections` for the linker, which is incompatbile with what CGo thinks about linking. This commit adds a workaround: it will add `--no-gc-sections` to the linking step if the command is not specified (falling back to the default behavior of gcc/clang). Related: https://github.com/golang/go/issues/52690
This commit is contained in:
parent
4cc8a7b551
commit
9ce21b5276
44
README.md
44
README.md
@ -270,7 +270,12 @@ used, run:
|
|||||||
$ bazel query @zig_sdk//toolchain/...
|
$ bazel query @zig_sdk//toolchain/...
|
||||||
```
|
```
|
||||||
|
|
||||||
# Note: UBSAN and "SIGILL: Illegal Instruction"
|
# Incompatibilities with clang and gcc
|
||||||
|
|
||||||
|
`zig cc` is *almost* a drop-in replacement for clang/gcc. This section lists
|
||||||
|
some of the discovered differences and ways to live with them.
|
||||||
|
|
||||||
|
## UBSAN and "SIGILL: Illegal Instruction"
|
||||||
|
|
||||||
`zig cc` differs from "mainstream" compilers by [enabling UBSAN by
|
`zig cc` differs from "mainstream" compilers by [enabling UBSAN by
|
||||||
default][ubsan1]. Which means your program may compile successfully and crash
|
default][ubsan1]. Which means your program may compile successfully and crash
|
||||||
@ -280,9 +285,14 @@ with:
|
|||||||
SIGILL: illegal instruction
|
SIGILL: illegal instruction
|
||||||
```
|
```
|
||||||
|
|
||||||
This is by design: it encourages program authors to fix the undefined behavior.
|
This flag encourages program authors to fix the undefined behavior. There are
|
||||||
There are [many ways][ubsan2] to find the undefined behavior.
|
[many ways][ubsan2] to find the undefined behavior.
|
||||||
|
|
||||||
|
## Use of `--gc-sections` by default
|
||||||
|
|
||||||
|
`zig cc` passes `--gc-sections` to the ld.lld linker by default, this causes
|
||||||
|
problems for CGo. See
|
||||||
|
[below][#go-linker-does-not-put-libc-onto-the-linker-line].
|
||||||
|
|
||||||
# Known Issues In bazel-zig-cc
|
# Known Issues In bazel-zig-cc
|
||||||
|
|
||||||
@ -313,6 +323,34 @@ currently targets the lowest version, without ability to change it.
|
|||||||
This section lists issues that I've stumbled into when using `zig cc`, and is
|
This section lists issues that I've stumbled into when using `zig cc`, and is
|
||||||
outside of bazel-zig-cc's control.
|
outside of bazel-zig-cc's control.
|
||||||
|
|
||||||
|
## Go linker does not put libc onto the linker line
|
||||||
|
|
||||||
|
**Severity: Low**
|
||||||
|
|
||||||
|
Task: [golang/go #52690 Go linker does not put libc onto the linker line, causing undefined symbol errors](https://github.com/golang/go/issues/52690)
|
||||||
|
|
||||||
|
Background: when linking CGo programs that do not have C code by itself,
|
||||||
|
the Golang linker does not link the C library, causing undefined symbols and
|
||||||
|
a message similar to this:
|
||||||
|
|
||||||
|
```
|
||||||
|
runtime/race(.text): relocation target getuid not defined
|
||||||
|
runtime/race(.text): relocation target pthread_self not defined
|
||||||
|
```
|
||||||
|
|
||||||
|
This is because `zig cc` emits `--gc-sections` for the linker, which is
|
||||||
|
incompatbile with what CGo thinks about linking.
|
||||||
|
|
||||||
|
A workaround until [#52690](https://github.com/golang/go/issues/52690) is
|
||||||
|
resolved: add `--no-gc-sections` to the link step. So the resulting command to
|
||||||
|
compile CGo code on Linux is:
|
||||||
|
|
||||||
|
```
|
||||||
|
CGO_ENABLED=1 CC="zig cc -Wl,--no-gc-sections" go build main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
This is done automatically in bazel-zig-cc.
|
||||||
|
|
||||||
## using glibc 2.27 or older
|
## using glibc 2.27 or older
|
||||||
|
|
||||||
**Severity: Low**
|
**Severity: Low**
|
||||||
|
@ -3,29 +3,29 @@ load("//rules:rules_go.bzl", "go_binary")
|
|||||||
load("@bazel-zig-cc//rules:platform.bzl", "platform_binary", "platform_test")
|
load("@bazel-zig-cc//rules:platform.bzl", "platform_binary", "platform_test")
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_lib",
|
name = "cgo_lib",
|
||||||
srcs = ["hello.go"],
|
srcs = ["cgo.go"],
|
||||||
cgo = True,
|
cgo = True,
|
||||||
importpath = "git.sr.ht/~motiejus/bazel-zig-cc/test/go",
|
importpath = "git.sr.ht/~motiejus/bazel-zig-cc/test/cgo",
|
||||||
visibility = ["//visibility:private"],
|
visibility = ["//visibility:private"],
|
||||||
)
|
)
|
||||||
|
|
||||||
go_binary(
|
go_test(
|
||||||
name = "go",
|
name = "cgo_test",
|
||||||
embed = [":go_lib"],
|
srcs = ["cgo_test.go"],
|
||||||
visibility = ["//visibility:public"],
|
embed = [":cgo_lib"],
|
||||||
)
|
)
|
||||||
|
|
||||||
go_test(
|
go_binary(
|
||||||
name = "go_test",
|
name = "cgo",
|
||||||
srcs = ["hello_test.go"],
|
embed = [":cgo_lib"],
|
||||||
embed = [":go_lib"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
[
|
[
|
||||||
platform_binary(
|
platform_binary(
|
||||||
name = "go_{}".format(name),
|
name = "cgo_{}".format(name),
|
||||||
src = "go",
|
src = "cgo",
|
||||||
platform = platform,
|
platform = platform,
|
||||||
)
|
)
|
||||||
for name, platform in [
|
for name, platform in [
|
||||||
@ -39,8 +39,8 @@ go_test(
|
|||||||
|
|
||||||
[
|
[
|
||||||
platform_test(
|
platform_test(
|
||||||
name = "go_test_{}".format(name),
|
name = "cgo_test_{}".format(name),
|
||||||
src = "go_test",
|
src = "cgo_test",
|
||||||
platform = platform,
|
platform = platform,
|
||||||
)
|
)
|
||||||
for name, platform in [
|
for name, platform in [
|
24
test/gorace/BUILD
Normal file
24
test/gorace/BUILD
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||||
|
load("//rules:rules_go.bzl", "go_binary")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "gorace_lib",
|
||||||
|
srcs = ["main.go"],
|
||||||
|
# keep
|
||||||
|
cgo = True,
|
||||||
|
importpath = "git.sr.ht/~motiejus/bazel-zig-cc/test/gorace",
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "gorace",
|
||||||
|
embed = [":gorace_lib"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "gorace_test",
|
||||||
|
srcs = ["main_test.go"],
|
||||||
|
embed = [":gorace_lib"],
|
||||||
|
race = "on",
|
||||||
|
)
|
13
test/gorace/main.go
Normal file
13
test/gorace/main.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Package main tests that Zig can compile race-enabled tests.
|
||||||
|
//
|
||||||
|
// As of writing, this fails:
|
||||||
|
// CGO_ENABLED=1 CC="zig cc" go test -race .
|
||||||
|
//
|
||||||
|
// More context: https://github.com/ziglang/zig/issues/11398
|
||||||
|
//
|
||||||
|
// This fails, because `zig cc` adds `--gc-sections` to the linker
|
||||||
|
// flag by default, which is incompatible with cgo. bazel-zig-cc
|
||||||
|
// adds a workaround for it.
|
||||||
|
package main
|
||||||
|
|
||||||
|
func main() {}
|
8
test/gorace/main_test.go
Normal file
8
test/gorace/main_test.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestFoo(t *testing.T) {
|
||||||
|
_ = t
|
||||||
|
main()
|
||||||
|
}
|
@ -78,7 +78,33 @@ fi
|
|||||||
export ZIG_LOCAL_CACHE_DIR="$_cache_prefix/bazel-zig-cc"
|
export ZIG_LOCAL_CACHE_DIR="$_cache_prefix/bazel-zig-cc"
|
||||||
export ZIG_GLOBAL_CACHE_DIR=$ZIG_LOCAL_CACHE_DIR
|
export ZIG_GLOBAL_CACHE_DIR=$ZIG_LOCAL_CACHE_DIR
|
||||||
|
|
||||||
exec "{zig}" "{zig_tool}" "$@"
|
lookup_args=()
|
||||||
|
add_arg=
|
||||||
|
case "{zig_tool}" in
|
||||||
|
cc|c++)
|
||||||
|
lookup_args=("-Wl,--gc-sections" "-Wl,--no-gc-sections")
|
||||||
|
add_arg="-Wl,--no-gc-sections"
|
||||||
|
;;
|
||||||
|
ld.lld)
|
||||||
|
lookup_args=("--gc-sections" "--no-gc-sections")
|
||||||
|
add_arg="--no-gc-sections"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
has_special_arg=0
|
||||||
|
for arg in "${{lookup_args[@]}}"; do
|
||||||
|
if [[ " ${{args[*]}} " == *" $arg "* ]]; then
|
||||||
|
has_special_arg=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
args=( "$@" )
|
||||||
|
if [[ "$has_special_arg" == 0 ]]; then
|
||||||
|
args+=( "$add_arg" )
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "{zig}" "{zig_tool}" "${{args[@]}}"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_ZIG_TOOLS = [
|
_ZIG_TOOLS = [
|
||||||
|
Loading…
Reference in New Issue
Block a user