Skip to content

cmake: link libatomic on 32-bit targets where std::atomic<int64_t> needs it - #648

Merged
mrjimenez merged 1 commit into
amule-project:masterfrom
got3nks:fix/cmake-link-libatomic-on-32bit
May 17, 2026
Merged

cmake: link libatomic on 32-bit targets where std::atomic<int64_t> needs it#648
mrjimenez merged 1 commit into
amule-project:masterfrom
got3nks:fix/cmake-link-libatomic-on-32bit

Conversation

@got3nks

@got3nks got3nks commented May 17, 2026

Copy link
Copy Markdown
Contributor

Closes #643.

CDownloadBandwidthThrottler holds the shared byte budget as std::atomic<int64_t> (src/DownloadBandwidthThrottler.h). On 64-bit targets the compiler emits native 8-byte CAS / load / store instructions; on 32-bit targets that lack a hardware 8-byte atomic (PPC32, ARMv5/v6, MIPS32, some old x86 toolchains) the atomic operations expand to __atomic_{load,store,compare_exchange,fetch_add}_8 calls that live in libatomic. Without -latomic on the link line the build dies at link time with

Undefined symbols for architecture ppc:
  "___atomic_compare_exchange_8", referenced from: ...
  "___atomic_fetch_add_8",        referenced from: ...
  "___atomic_load_8",             referenced from: ...
  "___atomic_store_8",            referenced from: ...

@barracuda156's MacPorts ppc / 10.6 build hit this. As the issue notes, the bug is platform-agnostic — any 32-bit Linux/BSD with the same toolchain would see it too.

Fix

New cmake/atomic.cmake probes whether std::atomic<int64_t> links bare. If yes (the typical 64-bit case), LIBATOMIC stays empty and nothing changes. If the bare probe fails, retry with -latomic; if that succeeds, set LIBATOMIC=atomic. Hard-fail with an actionable install hint if neither works.

src/CMakeLists.txt links ${LIBATOMIC} PUBLIC to muleappcore so amule / amuled / amulegui inherit the dependency transitively. Empty on 64-bit, atomic on 32-bit.

…eds it (amule-project#643)

CDownloadBandwidthThrottler holds the shared byte budget as
std::atomic<int64_t>. On 64-bit targets the compiler emits native
8-byte CAS / load / store; on 32-bit targets that lack a hardware
8-byte atomic (PPC32, ARMv5/v6, MIPS32, some old x86 toolchains) the
atomic operations expand to __atomic_{load,store,compare_exchange,
fetch_add}_8 calls that live in libatomic. Without -latomic on the
link line the build dies with "Undefined symbols:
___atomic_compare_exchange_8" etc.

barracuda156's MacPorts ppc / 10.6 build hit this. The bug is
platform-agnostic -- any 32-bit Linux/BSD with the same toolchain
would see it too.

New cmake/atomic.cmake probes whether std::atomic<int64_t> links
bare. If yes (the typical 64-bit case), LIBATOMIC stays empty and
nothing changes. If the bare probe fails, retry with -latomic; if
that succeeds, set LIBATOMIC=atomic. Hard-fail with an actionable
install hint if neither works.

src/CMakeLists.txt links ${LIBATOMIC} PUBLIC to muleappcore so
amule / amuled / amulegui inherit the dependency transitively.
Empty on 64-bit, "atomic" on 32-bit.
@mrjimenez
mrjimenez merged commit a58cd69 into amule-project:master May 17, 2026
12 checks passed
mrjimenez pushed a commit that referenced this pull request May 20, 2026
PR #648's cmake/atomic.cmake uses check_cxx_source_compiles to decide
whether linking libatomic is required for std::atomic<int64_t>. The
probe runs a tiny main() that stores / loads / fetch_adds /
compare_exchanges a std::atomic<int64_t>, then links it. On 32-bit
targets the compiler can inline the entire lock-free expansion of
those operations end-to-end -- no __atomic_*_8 library-call symbols
are emitted, the link succeeds, and the probe reports 'native 64-bit
atomics work, no -latomic needed'.

The real codebase's atomics live in CDownloadBandwidthThrottler
member functions called across translation-unit boundaries. GCC
can't inline those, emits __atomic_compare_exchange_8 /
__atomic_load_8 / __atomic_store_8 / __atomic_fetch_add_8 references,
and the link fails with the original Undefined Symbols errors the
probe was supposed to detect. Reported by @barracuda156 on PPC32
MacPorts -- amule_HAVE_NATIVE_ATOMIC64 = Success at configure, link
failure at build.

The probe heuristic is fundamentally fragile (any in-TU inlining
hides the library-call references) so drop it. 32-bit CPUs lack a
hardware 8-byte CAS -- the answer is always 'libatomic required'.
Just look up the library with find_library(NAMES atomic) and link
it; 64-bit targets stay a no-op.

Move the new logic to the top of the root CMakeLists.txt where the
include statement used to be. cmake/atomic.cmake is deleted. The
hard-fail message preserves the per-distro install hint the
previous FATAL_ERROR carried.

Closes #643 properly.
@got3nks
got3nks deleted the fix/cmake-link-libatomic-on-32bit branch May 22, 2026 13:50
ngosang pushed a commit to ngosang/amule that referenced this pull request Jul 27, 2026
…es (amule-project#648)

Adds drag-to-resize columns (persisted per-table in localStorage) and a Reset-columns action to every data table, implemented once in the shared table.js (useTablePrefs + VirtualTable + ColumnPicker) and threaded through the Downloads, Shared, Search, Servers and Clients views. Resize uses Pointer Events with setPointerCapture (mouse + touch), commits only on an actual width change, and routes the live drag width through component state so an SSE-driven re-render mid-drag can't stomp it. Completes amule-project#361.
mrjimenez pushed a commit to mrjimenez/amule that referenced this pull request Jul 28, 2026
* feat(search): persist search history across restarts (amule-project#641)

The search field was a plain text control with no memory of past
searches. Swap it for a wxComboBox (a wxTextEntry, like wxTextCtrl,
so the existing GetValue()/Clear() call sites keep working via that
shared base) and persist submitted terms to wxConfig, most-recent
first, capped at 20 entries and deduplicated case-insensitively.

Right-clicking the field opens a small menu ("Remember search
history" checkbox + "Clear search history") so history can be paused
or wiped without a dedicated Preferences page.

i18n: ran scripts/update-po.sh to register the two new menu strings.

* style(search): separate the destructive Clear item from the toggle above

A separator between the checkbox and "Clear search history" keeps the
one-shot destructive action visually distinct from the persistent
on/off state, instead of reading as a second toggle in the same group.

* style(search): use nullptr instead of NULL for the new combo box

Fixes the modernize-use-nullptr clang-tidy finding on the changed
line; matches the nullptr convention already used a couple of
wxComboBox constructions below in the same file.

* feat(search): rework query history per amule-project#643 review — file, prefs toggle, edit menu

Addresses all four blocking points from got3nks's review, plus both
optional suggestions:

1. Edit context menu restored. Overriding the field's context menu no
   longer drops Cut/Copy/Paste/Select All -- same custom-Paste-ID idiom
   as CMuleTextCtrl::OnRightDown (wxMenu over-permits wxID_PASTE, so it
   gets a manual clipboard-content check), plus a separator, plus the
   history's own Clear action.

2. Persisted to a dedicated searchhistory.dat (via CTextFile, one term
   per line) instead of amule.conf -- mirrors eMule's AC_SearchStrings.dat.
   Query terms no longer bloat the main config or travel with config
   backups / the --amule-config-file push to amuleweb/amuleapi.

3. "Remember search history" moved into Preferences > General as an
   ordinary Cfg_Bool checkbox (IDC_SEARCHHISTORYENABLED), same
   NewCfgItem wiring as every other GUI-behavior toggle on that page.
   It's a client-side-only setting, so the one checkbox works unchanged
   in both amule and amuleGUI. The context menu keeps only Clear (a
   one-shot action, not a setting to toggle from a hidden menu).

4. Cap raised from 20 to 30, matching eMule's CCustomAutoComplete default.

Optional, done anyway:
- wxComboBox::AutoComplete() wired up (eMule's ACO_AUTOSUGGEST
  equivalent), re-armed after every load/record/clear so it always
  reflects the current entry set.
- Explicitly framed as *query* history throughout (comments, tooltip)
  to distinguish it from the separate, not-yet-implemented result
  persistence that's the rest of amule-project#641.

The dedup/move-to-front/cap logic that used to live inline in
CSearchDlg::RecordSearchHistory is extracted into a pure function,
ApplySearchHistoryEntry() (SearchHistory.h/.cpp), decoupled from
wxComboBox/wxConfig specifically so it's unit-testable without a wx
event loop -- new SearchHistoryTest covers empty-list insert, reorder
of an existing term, case-insensitive dedup, empty-term no-op, and
capping (including locking in the actual 30-entry constant).

Rebased onto current master; po/ catalogs regenerated as the final
step so the diff is just the new/changed strings in sync with the tree.

Verified for real: built and ran both amule and amulegui, plus the
full unit test suite (27/27 passing, including the new
SearchHistoryTest's 7 cases).

* fix(tests): link Format.cpp + strerror_r.c into SearchHistoryTest

Same Linux/mingw-only link failure as CMuleCollectionTest/MagnetURITest
already work around: muleunit's MuleDebug.cpp needs CFormat for its
glibc backtrace path, which isn't compiled in on macOS -- so the
target linked fine locally but failed on the Ubuntu/mingw CI builds
(and the clang-tidy jobs, which build the tree first).

* i18n: regenerate po/ catalogs after rebasing onto current master

Mechanical rebase to resolve the po/ catalog conflicts against master's
amule-project#648/amule-project#650/amule-project#651 (per got3nks's note on amule-project#643) -- no source changes here,
scripts/update-po.sh output only, so the diff is just the tree back in
sync with the current strings.

* fix(search): avoid an unnamed EReadTextFile bitmask cast in history load

txtIgnoreEmptyLines|txtStripWhitespace has no single named enumerator
to cast to -- clang-tidy Tier-1 flagged it (clang-analyzer-optin.core.
EnumCastOutOfRange), correctly: EReadTextFile isn't a flag enum, so a
synthesized OR'd value is genuinely out of its declared range even
though CTextFile::ReadLines treats it as bitflags at runtime.

txtReadDefault would dodge the cast but also drops '#'-led lines,
silently eating a legitimate search term that happens to start with
one. Read unfiltered (txtReadAll, a real enumerator) and do the
trim/empty-line-drop by hand instead -- same behavior, no cast, no
lost terms.

* i18n: regenerate po/ catalogs after rebasing onto current master

Mechanical rebase to resolve the po/ conflicts against master's amule-project#642
(just merged) -- no source changes here.
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.

32-git archs may beed linking to libatomic: Undefined symbols: "___atomic_compare_exchange_8" etc.

2 participants