Skip to content

build: fix stale soname symlink after a library version bump#4180

Open
grandixximo wants to merge 1 commit into
LinuxCNC:masterfrom
grandixximo:fix/stale-soname-symlink
Open

build: fix stale soname symlink after a library version bump#4180
grandixximo wants to merge 1 commit into
LinuxCNC:masterfrom
grandixximo:fix/stale-soname-symlink

Conversation

@grandixximo

Copy link
Copy Markdown
Contributor

When a library soname is bumped (here liblinuxcncini.so.0 to .so.1), an incremental tree keeps the old .so.0 on disk, and the dev symlink ../lib/liblinuxcncini.so gets repointed at the stale lib: the generic ../lib/%.so pattern rules in src/Makefile match both %.so.0 and %.so.1, and the .so.0 rule is listed first so it wins. Everything then links against the old library and fails with undefined symbols (IniFile::mapLinearUnits), breaking the python linuxcnc module, linuxcnc_check_ini and startup.

Clean builds are immune, so CI never sees it; only people building incrementally across the bump are hit. make clean does not help either, because .so.0 is no longer in $(TARGETS) so rm -f $(TARGETS) leaves it behind.

Fixes:

  • the liblinuxcncini.so.1 rule removes any leftover .so.[0-9]* sibling.
  • an explicit liblinuxcncini.so to .so.1 symlink rule, which overrides the ambiguous pattern pair so the symlink repoints to the current soname in a single build pass (the rm alone only self-heals on a second make).
  • genclean also removes ../lib/*.so.[0-9]* so stale versioned libraries no longer survive make clean.

@BsAtHome flagging you as reviewer. AndyPugh, myself, and Peter Wallace from Mesa all fell into this same trap; I walked Peter through it on Discord. A general fix for everyone seems nicer than the git clean -dxf we keep recommending, and it avoids that step entirely. Any reason not to do it?

When a shared library's soname is bumped (e.g. liblinuxcncini.so.0 ->
.so.1), incremental trees keep the old .so.0 on disk. The generic
../lib/%.so symlink has two pattern rules in src/Makefile (matching
%.so.0 and %.so.1, .so.0 listed first), so make repoints the dev symlink
at the stale .so.0. Everything then links against the old library and
fails with undefined symbols (e.g. IniFile::mapLinearUnits), breaking the
python module, linuxcnc_check_ini and startup. Clean builds are immune,
so CI never sees it; only incremental builders across the bump are hit.
make clean did not help either: .so.0 is no longer in TARGETS, so
rm -f $(TARGETS) leaves it behind.

Fixes:
- liblinuxcncini.so.1 rule removes any leftover .so.[0-9]* sibling.
- Add an explicit liblinuxcncini.so -> .so.1 symlink rule. Explicit rules
  override the ambiguous pattern pair, so the symlink repoints to the
  current soname in a single build pass (the rm alone self-heals only on
  a second make).
- genclean also removes ../lib/*.so.[0-9]* so stale versioned libraries
  no longer survive make clean.
@grandixximo grandixximo requested a review from BsAtHome June 20, 2026 01:34
@BsAtHome

Copy link
Copy Markdown
Contributor

Should there also be a matching fixup in 2.9 to ensure .so.0?

@grandixximo

Copy link
Copy Markdown
Contributor Author

liblinuxcncini is the only lib that differs across branches (.so.0 in 2.9, .so.1 in 2.10), so the only one a shared RIP tree holds in both versions. 2.9 => 2.10 is the breaking direction this PR fixes; the reverse is safe since 2.9 only has the %.so: %.so.0 rule and rebuilds .so.0 on checkout, so a stray .so.1 is never picked up. No 2.9 correctness fix needed.

A fully general fix (auto-handling any future bump) is not really feasible without routing every lib through one build macro, since sonames are written inline per-Submakefile. The genclean glob here is the general part (covers all libs); the explicit symlink + sibling-rm is just the cheap per-bump recipe. I backported the genclean glob to 2.9 for tidiness: #4188.

@BsAtHome

Copy link
Copy Markdown
Contributor

Check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants