Fix build on modern toolchains (GCC 10+/15 C23, Clang, -fno-common) - #82
Open
ptudor wants to merge 4 commits into
Open
Fix build on modern toolchains (GCC 10+/15 C23, Clang, -fno-common)#82ptudor wants to merge 4 commits into
ptudor wants to merge 4 commits into
Conversation
C23 (the GCC 15 default, -std=gnu23) removes support for old K&R function
definitions, so the K&R definition of aprx_cfmakeraw() no longer compiles:
ttyreader.c: error: old-style function definition
Convert it to a prototype. The second parameter was implicitly int under
K&R rules; spell that out as 'int f'.
In C23 'bool', 'true' and 'false' are keywords (no <stdbool.h> needed), so
the interface.c config parser's 'int bool;' locals are a syntax error under
the GCC 15 default of -std=gnu23:
interface.c: error: expected identifier or '(' before 'bool'
Rename the locals to 'boolval'.
Since GCC 10 (and Clang 11) the compiler defaults to -fno-common, so a
file-scope tentative definition emits a real symbol in every translation
unit that sees it, instead of being merged into one common symbol at link
time. aprx has three globals that relied on the old -fcommon merging:
* aprx.h defines the pthread globals 'aprsis_thread' and 'pthr_attrs'
without 'extern', so every .c that includes it gets its own copy;
netresolver.c also defines a second real 'pthr_attrs'.
* the wall-clock 'struct timeval now' is defined in both timercmp.c and
aprx-stat.c, which link together into aprx-stat.
Linking then fails with e.g.:
multiple definition of `aprsis_thread'; aprx.o: first defined here
multiple definition of `now'; aprx-stat.o: first defined here
Declare the shared globals 'extern' in aprx.h (as is already done for the
monotonic 'tick' clock) and keep exactly one real definition of each:
aprsis_thread and pthr_attrs in aprsis.c, now in timercmp.c (which is linked
into both programs). Behaviour is unchanged -- one shared object per symbol,
exactly as the merged common symbol used to be.
Makefile.in sets LD=@cc@ and links the programs with $(LD), so a default build links through the compiler driver. But build systems that set LD to the real linker on the make command line (OpenWrt, Buildroot, Yocto, ...) override that assignment, and the link then runs e.g. 'ld' directly: ld: unrecognized option '-pthread' -pthread (and -fuse-ld=...) are compiler-driver options, not linker options; a threaded C program must be linked via the compiler so the driver adds the C runtime and translates -pthread. Use $(CC) for the two final link rules, which is the portable, conventional form and a no-op for a default build where LD already expands to the compiler.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
aprx doesn't build out of the box on current C toolchains. This series fixes four independent issues so that a clean
./configure && makesucceeds on contemporary GCC, Clang, and cross-build systems. Each commit is one issue:aprx_cfmakeraw()— the K&R definition leaves the 2nd parameter implicit-int. GCC 14, GCC 15 and Clang 19 promote-Wimplicit-intto an error by default, and C23 (GCC 15's default-std=gnu23) removes K&R definitions outright.bool—bool/true/falseare keywords in C23, so the parser'sint bool;locals are a syntax error under GCC 15's default.-fno-commonmultiple definitions — GCC 10+ and Clang 11+ default to-fno-common.aprx.hdefines the pthread globalsaprsis_thread/pthr_attrswithoutextern(so every translation unit that includes it emits its own copy), andnowis defined in bothtimercmp.candaprx-stat.c. Linking then fails withmultiple definition of .... The fix declares the shared globalsexterninaprx.h— exactly as is already done for the monotonictickclock — and keeps a single owner for each. Behaviour is unchanged. This one bites every current compiler.$(CC)—Makefile.insetsLD=@CC@and links with$(LD), so a default build links through the compiler driver. Build systems that setLDto the real linker on the make command line (OpenWrt, Buildroot, Yocto, ...) override that, and the link then runslddirectly and fails withld: unrecognized option '-pthread'. Linking a threaded C program via the compiler driver is the portable, conventional form; it is a no-op for a default build whereLDalready expands to the compiler.Tested — pristine
mastervs this branchI built pristine
masterand then this branch on five platforms. "master build" = does upstreammastercompile+link as-is; "patched" = does this branch build and doesaprx -Vrun.masterbuild-VOK-VOK-VOK-VOK#3breaks every platform.#1breaks everything except GCC 12 (where implicit-intis still only a warning).#2fires only where the compiler defaults to C23 (GCC 15).#4fires only where the build system overridesLD(the OpenWrt cross build). Each commit is independent and can be taken on its own.Out of scope (kept downstream)
Building against a musl sysroot additionally needs the kernel-AX.25 path (
<netax25/ax25.h>) gated out, because musl ships no AX.25 headers. That is an environmental change — it would disable AX.25 on a normal glibc host that haslibax25— so it is kept in the downstream (OpenWrt) packaging rather than here. In the five builds above the AX.25 code path is exercised normally: the three glibc/Linux hosts have the AX.25 headers installed, and on FreeBSDPF_AX25is undefined so aprx compiles that path out on its own.