Fix macOS build: rename Rugnux library, move in_worker TLS into a function

The Rugnux library and the rugnux executable differ only in case, so on a
case-insensitive filesystem (macOS, Windows) their CMakeFiles/<target>.dir
directories collide and the executable's build.make overwrites the library's
("No rule to make target rugnux/CMakeFiles/Rugnux.dir/depend"). The library is
renamed JFJochRugnux, in line with the other libraries.

Apple's linker rejects the TLS wrapper clang emits for the inline thread_local
static member WorkerPool::in_worker as a duplicate symbol once it is included
from several libraries. It is now a function-local thread_local.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Filip Leonarski
2026-09-26 17:51:50 +02:00
committed by Filip Leonarski
co-authored by Claude Opus 5.5
parent e9da892790
commit ba43cb4319
6 changed files with 16 additions and 12 deletions
+1 -1
View File
@@ -169,7 +169,7 @@ jobs:
cd build
# The "viewer" component is now jfjoch_viewer alone -- rugnux ships as its own artifact
# (build:rugnux-tgz) and the two CLI tools are no longer packaged at all. The full tree is
# still built because the viewer links the Rugnux library for its in-process jobs.
# still built because the viewer links the JFJochRugnux library for its in-process jobs.
ninja -j16
cpack
- name: Upload viewer tgz to release
+1 -1
View File
@@ -339,7 +339,7 @@ generated API model and internal types.
`JFJochImageAnalysis`):
- `jfjoch_broker` — online, real-time (FPGA + GPU).
- `jfjoch_viewer` — interactive Qt desktop (`viewer/`), results not persisted.
- `rugnux` (`rugnux/rugnux_cli.cpp`, built on the `Rugnux` library in the same directory) — offline
- `rugnux` (`rugnux/rugnux_cli.cpp`, built on the `JFJochRugnux` library in the same directory) — offline
batch over a stored HDF5, invoked as `rugnux {<options>} <input.h5>` (it has **no `--help`**; run
it with no arguments to print the usage, which is the authority on its flags). Rotation vs stills
is auto-detected from the goniometer axis. Merging is on by default (`--no-merge` to disable);
+9 -5
View File
@@ -41,7 +41,7 @@ namespace parallel_detail {
// True on a thread the pool owns. A parallel pass reached from inside one runs inline instead
// of queueing: the workers are already occupied by the outer pass, so waiting for one of them
// to pick up the inner work could wait forever.
static bool InWorker() { return in_worker; }
static bool InWorker() { return InWorkerFlag(); }
size_t WorkerCount() const { return workers.size(); }
@@ -58,7 +58,7 @@ namespace parallel_detail {
const unsigned hw = std::max(1u, std::thread::hardware_concurrency());
workers.reserve(hw - 1);
for (unsigned i = 0; i + 1 < hw; i++) // the submitting thread takes a share too
workers.emplace_back([this] { in_worker = true; Loop(); });
workers.emplace_back([this] { InWorkerFlag() = true; Loop(); });
}
~WorkerPool() {
@@ -89,10 +89,14 @@ namespace parallel_detail {
std::deque<std::function<void()> > queue;
std::vector<std::thread> workers;
bool stop = false;
static thread_local bool in_worker;
};
inline thread_local bool WorkerPool::in_worker = false;
// A function-local thread_local rather than an inline static member: Apple's linker rejects the
// TLS wrapper clang emits for the latter as a duplicate symbol once two libraries include this.
static bool &InWorkerFlag() {
static thread_local bool in_worker = false;
return in_worker;
}
};
// What the tasks of one pass share: the body to call, how many of them are still outstanding, and
// the first exception any of them threw.
+3 -3
View File
@@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
# SPDX-License-Identifier: GPL-3.0-only
ADD_LIBRARY(Rugnux STATIC
ADD_LIBRARY(JFJochRugnux STATIC
Rugnux.cpp
RugnuxDefaults.cpp
RugnuxDefaults.h
@@ -35,12 +35,12 @@ ADD_LIBRARY(Rugnux STATIC
WriteModel.h
)
TARGET_LINK_LIBRARIES(Rugnux JFJochReader JFJochImageAnalysis JFJochWriter JFJochPreview gemmi fftw3f)
TARGET_LINK_LIBRARIES(JFJochRugnux JFJochReader JFJochImageAnalysis JFJochWriter JFJochPreview gemmi fftw3f)
# rugnux is the single offline analysis CLI; --mode picks what it does: mx (the full pipeline, the
# default), azint, scale (re-scale/merge stored reflections) or calibration (powder-ring geometry).
ADD_EXECUTABLE(rugnux rugnux_cli.cpp)
TARGET_LINK_LIBRARIES(rugnux Rugnux JFJochReader JFJochImageAnalysis JFJochWriter)
TARGET_LINK_LIBRARIES(rugnux JFJochRugnux JFJochReader JFJochImageAnalysis JFJochWriter)
INSTALL(TARGETS rugnux RUNTIME COMPONENT rugnux)
# libcufft_static.a carries a relocatable-device-code object (separate_callback.o), so an executable
+1 -1
View File
@@ -126,7 +126,7 @@ ADD_EXECUTABLE(jfjoch_test
)
target_link_libraries(jfjoch_test Catch2WithMain JFJochBroker JFJochReceiver JFJochReader JFJochStreamWriter
Rugnux JFJochImageAnalysis JFJochCommon JFJochHLSSimulation JFJochPreview
JFJochRugnux JFJochImageAnalysis JFJochCommon JFJochHLSSimulation JFJochPreview
jfjoch_xds_plugin ZLIB::ZLIB)
target_include_directories(jfjoch_test PRIVATE .)
+1 -1
View File
@@ -119,7 +119,7 @@ ADD_EXECUTABLE(jfjoch_viewer jfjoch_viewer.cpp JFJochViewerWindow.cpp JFJochView
)
TARGET_LINK_LIBRARIES(jfjoch_viewer Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Charts Qt6::Concurrent
JFJochReader JFJochLogger JFJochCommon JFJochWriter JFJochImageAnalysis Rugnux
JFJochReader JFJochLogger JFJochCommon JFJochWriter JFJochImageAnalysis JFJochRugnux
fftw3f libcurl_static) # vendored static libcurl by concrete name, not the CURL::libcurl
# alias, which a system libcurl can shadow (see top-level CMakeLists)