Zig Version
0.17.0-dev.902+7255f3e72
Steps to Reproduce, Observed Behavior, and Expected Behavior
TL;DR: @export takes a pointer, but pointers to thread-locals are necessarily runtime-known, so it is impossible to use @export with thread-locals, and there is no other way to export a weak symbol.
export_weak_threadlocal.zig:
threadlocalvarweak_threadlocal:u32=1;comptime{@export(&weak_threadlocal,.{.linkage=.weak,.name="weak_threadlocal",});}
zig build-obj export_weak_threadlocal.zig
export_weak_threadlocal.zig:3:13: error: unable to resolve comptime value
@export(&weak_threadlocal, .{
^~~~~~~~~~~~~~~~~
export_weak_threadlocal.zig:3:13: note: export target must be comptime-known
Compare the awful C version:
#include <stdint.h>
__thread uint32_t __attribute__((weak)) weak_threadlocal = 1;
This is a bug in the language, because it assumes that all variables that can be exported can have their pointers taken at comptime. Naturally, this can't be the case for thread-locals, as there are multiple pointers at runtime.
Possible solutions include:
A: passing values to @export instead:
export_weak_threadlocal.zig:
threadlocalvarweak_threadlocal:u32=1;comptime{@export(weak_threadlocal,.{.linkage=.weak,.name="weak_threadlocal",});}
B: by adding export options to variable declarations, something like:
export(.{.linkage=.weak})threadlocalvarweak_threadlocal:u32=1;
I prefer A because it is established that builtins are "compiler magic" and it does not require syntax changes, also it meshes well with #30873.
### Zig Version
0.17.0-dev.902+7255f3e72
### Steps to Reproduce, Observed Behavior, and Expected Behavior
TL;DR: `@export` takes a pointer, but pointers to thread-locals are necessarily runtime-known, so it is impossible to use `@export` with thread-locals, and there is no other way to export a weak symbol.
`export_weak_threadlocal.zig`:
```zig
threadlocal var weak_threadlocal: u32 = 1;
comptime {
@export(&weak_threadlocal, .{
.linkage = .weak,
.name = "weak_threadlocal",
});
}
```
`zig build-obj export_weak_threadlocal.zig`
```
export_weak_threadlocal.zig:3:13: error: unable to resolve comptime value
@export(&weak_threadlocal, .{
^~~~~~~~~~~~~~~~~
export_weak_threadlocal.zig:3:13: note: export target must be comptime-known
```
Compare the awful C version:
```
#include <stdint.h>
__thread uint32_t __attribute__((weak)) weak_threadlocal = 1;
```
This is a bug in the language, because it assumes that all variables that can be exported can have their pointers taken at comptime. Naturally, this can't be the case for thread-locals, as there are multiple pointers at runtime.
Possible solutions include:
A: passing values to `@export` instead:
`export_weak_threadlocal.zig`:
```zig
threadlocal var weak_threadlocal: u32 = 1;
comptime {
@export(weak_threadlocal, .{
.linkage = .weak,
.name = "weak_threadlocal",
});
}
```
B: by adding export options to variable declarations, something like:
```zig
export(.{.linkage = .weak}) threadlocal var weak_threadlocal: u32 = 1;
```
I prefer A because it is established that builtins are "compiler magic" and it does not require syntax changes, also it meshes well with #30873.