meson: fix build with lld on linux#183
Conversation
|
It looks to me like v15 built with clang correctly (see https://github.com/latchset/jose/actions/runs/27129994139 ) Is there some detail I'm missing about the clang build on which you're seeing this? |
|
Ahh yea, a bit too fast there. This is not the fault of clang itself, but rather using lld as the linker instead of bfd. Converting this to a draft as this is definetly not the correct solution. edit: |
|
Yea, so the issue seems to be exactly what the freebsd faced in #152. |
|
Now explicitly checks for lld instead of clang. |
sergio-correia
left a comment
There was a problem hiding this comment.
There's an operator precedence issue in the compound boolean that regresses version-script support on GNU ld. --undefined-version is an lld-only flag (introduced in LLD 16) and does not exist in GNU ld, so the second probe always fails with GNU ld, causing fallback to the coarser regex export. Splitting into nested if/else for lld vs non-lld (matching the FreeBSD branch pattern) should fix it.
Not in this diff, but related: lines 6 and 10 use build_machine.system() to choose linker flags, but host_machine.system() is correct here since the flags apply to the output binary, not the build host. meson.get_compiler('c') already returns the host compiler, so using build_machine for the platform check is inconsistent. The root meson.build already uses host_machine.system() for the FreeBSD licensedir check. This is pre-existing and could be addressed separately.
| if cc.get_linker_id() != 'ld.lld' and not cc.links( | ||
| code, | ||
| args: version_script_flags, | ||
| name: '-Wl,--version-script=...', | ||
| ) or not cc.links( | ||
| code, | ||
| args: version_script_flags + ',--undefined-version', | ||
| name: '-Wl,--version-script=...', | ||
| ) |
There was a problem hiding this comment.
In Meson, and binds tighter than or, so this condition parses as:
(cc.get_linker_id() != 'ld.lld' AND NOT cc.links(plain))
OR
(NOT cc.links(with_undefined_version))
The second clause applies to all linkers, not just lld. Since --undefined-version is an lld-only flag (introduced in LLD 16) and does not exist in GNU ld at all, the second probe will always fail on GNU ld, regressing version-script support on every GNU ld system.
Would it be better to split this into nested if/else for lld vs non-lld? That matches the FreeBSD branch pattern and avoids the precedence trap:
if cc.get_linker_id() == 'ld.lld'
if not cc.links(code, args: version_script_flags + ',--undefined-version',
name: '-Wl,--version-script=... (lld)')
flags = ['-export-symbols-regex=^jose_.*']
else
flags = [version_script_flags]
endif
else
if not cc.links(code, args: version_script_flags,
name: '-Wl,--version-script=...')
flags = ['-export-symbols-regex=^jose_.*']
else
flags = [version_script_flags]
endif
endif| if cc.get_linker_id() != 'ld.lld' and not cc.links( | ||
| code, | ||
| args: version_script_flags, | ||
| name: '-Wl,--version-script=...', |
There was a problem hiding this comment.
Both cc.links() calls use the same name: '-Wl,--version-script=...', so Meson's configure output doesn't distinguish which probe passed or failed. Maybe use different names like '-Wl,--version-script=... (plain)' and '-Wl,--version-script=... (--undefined-version)' to make build logs easier to read.
Currently, building on a system with clang fails with
clang: error: unknown argument: '-export-symbols-regex=^jose_.*'as they are not 1:1 compatible. This fixes this by explicitly checking for clang and falling back to the FreeBSD check, which also uses clang.
Not sure if this is the correct solution, but jose now successfully builds with both clang and gcc.