Skip to content

Commit 6f23aa8

Browse files
committed
cmake: Detect whether or not atomic is needed
It turns out that GCC requires explicitly linking to a library `atomic` in order to support c11/atomics. gcc spec file will not handle it directly at least not on the following Debian archs: armel, m68k, mipsel, powerpc, sh4, sparc64 and riscv64. Introduce a new cmake module to detect usage of gcc/atomic and add missing library to the link step. For reference: * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104248 Fixes #1003
1 parent 6bc3405 commit 6f23aa8

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

CMakeLists.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ set(LIBRARY_SOVERSION ${hwy_VERSION_MAJOR})
2727

2828
set(CMAKE_CXX_EXTENSIONS OFF)
2929

30+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
31+
# Search for Atomics implementation:
32+
find_package(Atomics REQUIRED)
33+
3034
# Enabled PIE binaries by default if supported.
3135
include(CheckPIESupported OPTIONAL RESULT_VARIABLE CHECK_PIE_SUPPORTED)
3236
if(CHECK_PIE_SUPPORTED)
@@ -281,11 +285,9 @@ target_include_directories(hwy PUBLIC
281285
target_compile_features(hwy PUBLIC cxx_std_11)
282286
set_target_properties(hwy PROPERTIES
283287
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/hwy/hwy.version)
288+
# For GCC __atomic_store_8, see #887
289+
target_link_libraries(hwy PRIVATE ${ATOMICS_LIBRARIES})
284290
if(UNIX AND NOT APPLE)
285-
# For GCC __atomic_store_8, see #887
286-
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT HWY_EMSCRIPTEN)
287-
target_link_libraries(hwy atomic)
288-
endif()
289291
# not supported by MSVC/Clang, safe to skip (we use DLLEXPORT annotations)
290292
set_property(TARGET hwy APPEND_STRING PROPERTY
291293
LINK_FLAGS " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/hwy/hwy.version")

cmake/FindAtomics.cmake

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Original issue:
2+
# * https://gitlab.kitware.com/cmake/cmake/-/issues/23021#note_1098733
3+
#
4+
# For reference:
5+
# * https://gcc.gnu.org/wiki/Atomic/GCCMM
6+
#
7+
# riscv64 specific:
8+
# * https://lists.debian.org/debian-riscv/2022/01/msg00009.html
9+
#
10+
# ATOMICS_FOUND - system has c++ atomics
11+
# ATOMICS_LIBRARIES - libraries needed to use c++ atomics
12+
13+
include(CheckCXXSourceCompiles)
14+
15+
# RISC-V only has 32-bit and 64-bit atomic instructions. GCC is supposed
16+
# to convert smaller atomics to those larger ones via masking and
17+
# shifting like LLVM, but it’s a known bug that it does not. This means
18+
# anything that wants to use atomics on 1-byte or 2-byte types needs
19+
# -latomic, but not 4-byte or 8-byte (though it does no harm).
20+
set(atomic_code
21+
"
22+
#include <atomic>
23+
#include <cstdint>
24+
std::atomic<uint8_t> n8 (0); // riscv64
25+
std::atomic<uint64_t> n64 (0); // armel, mipsel, powerpc
26+
int main() {
27+
++n8;
28+
++n64;
29+
return 0;
30+
}")
31+
32+
# https://gitlab.kitware.com/cmake/cmake/-/issues/24063
33+
set(CMAKE_CXX_STANDARD 11)
34+
check_cxx_source_compiles("${atomic_code}" ATOMICS_LOCK_FREE_INSTRUCTIONS)
35+
36+
if(ATOMICS_LOCK_FREE_INSTRUCTIONS)
37+
set(ATOMICS_FOUND TRUE)
38+
set(ATOMICS_LIBRARIES)
39+
else()
40+
set(CMAKE_REQUIRED_LIBRARIES "-latomic")
41+
check_cxx_source_compiles("${atomic_code}" ATOMICS_IN_LIBRARY)
42+
set(CMAKE_REQUIRED_LIBRARIES)
43+
if(ATOMICS_IN_LIBRARY)
44+
set(ATOMICS_LIBRARY atomic)
45+
include(FindPackageHandleStandardArgs)
46+
find_package_handle_standard_args(Atomics DEFAULT_MSG ATOMICS_LIBRARY)
47+
set(ATOMICS_LIBRARIES ${ATOMICS_LIBRARY})
48+
unset(ATOMICS_LIBRARY)
49+
else()
50+
if(Atomics_FIND_REQUIRED)
51+
message(FATAL_ERROR "Neither lock free instructions nor -latomic found.")
52+
endif()
53+
endif()
54+
endif()
55+
unset(atomic_code)
56+
unset(CMAKE_CXX_STANDARD)

0 commit comments

Comments
 (0)