kimwalisch / primesieve

🚀 Fast prime number generator
BSD 2-Clause "Simplified" License
942 stars 123 forks source link

atomics detection is broken #141

Closed barracuda156 closed 8 months ago

barracuda156 commented 8 months ago
--->  Configuring primesieve
Executing:  cd "/opt/local/var/macports/build/_opt_PPCSnowLeopardPorts_math_primesieve/primesieve/work/build" && /opt/local/bin/cmake -G "CodeBlocks - Unix Makefiles" -DCMAKE_BUILD_TYPE=MacPorts -DCMAKE_INSTALL_PREFIX="/opt/local" -DCMAKE_INSTALL_NAME_DIR="/opt/local/lib" -DCMAKE_SYSTEM_PREFIX_PATH="/opt/local;/usr" -DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" -DCMAKE_OBJC_COMPILER="$CC" -DCMAKE_OBJCXX_COMPILER="$CXX" -DCMAKE_POLICY_DEFAULT_CMP0025=NEW -DCMAKE_POLICY_DEFAULT_CMP0060=NEW -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_COLOR_MAKEFILE=ON -DCMAKE_FIND_FRAMEWORK=LAST -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DCMAKE_MODULE_PATH="/opt/local/share/cmake/Modules" -DCMAKE_PREFIX_PATH="/opt/local/share/cmake/Modules" -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=OFF -DCMAKE_INSTALL_RPATH="/opt/local/lib" -Wno-dev -DBUILD_TESTS=ON -DCMAKE_OSX_ARCHITECTURES="ppc" -DCMAKE_OSX_DEPLOYMENT_TARGET="10.6" -DCMAKE_OSX_SYSROOT="/" /opt/local/var/macports/build/_opt_PPCSnowLeopardPorts_math_primesieve/primesieve/work/primesieve-11.1 
-- The CXX compiler identification is GNU 13.2.0
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /opt/local/bin/g++-mp-13 - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test atomic64
-- Performing Test atomic64 - Failed
-- Performing Test atomic32
-- Performing Test atomic32 - Success
CMake Error at cmake/libatomic.cmake:40 (message):
  Failed to find libatomic!
Call Stack (most recent call first):
  CMakeLists.txt:96 (include)

-- Configuring incomplete, errors occurred!

This is GCC, so obviously libatomic is there. The check is not looking for it at all however:

Performing C++ SOURCE FILE Test atomic64 failed with the following output:
Change Dir: /opt/local/var/macports/build/_opt_PPCSnowLeopardPorts_math_primesieve/primesieve/work/build/CMakeFiles/CMakeTmp

Run Build Command(s):/usr/bin/make -f Makefile cmTC_041cb/fast && /usr/bin/make  -f CMakeFiles/cmTC_041cb.dir/build.make CMakeFiles/cmTC_041cb.dir/build
Building CXX object CMakeFiles/cmTC_041cb.dir/src.cxx.o
/opt/local/bin/g++-mp-13 -Datomic64  -pipe -Os -DNDEBUG -I/opt/local/include -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++11 -arch ppc -mmacosx-version-min=10.6 -o CMakeFiles/cmTC_041cb.dir/src.cxx.o -c /opt/local/var/macports/build/_opt_PPCSnowLeopardPorts_math_primesieve/primesieve/work/build/CMakeFiles/CMakeTmp/src.cxx
Linking CXX executable cmTC_041cb
/opt/local/bin/cmake -E cmake_link_script CMakeFiles/cmTC_041cb.dir/link.txt --verbose=1
/opt/local/bin/g++-mp-13 -pipe -Os -DNDEBUG -I/opt/local/include -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++11 -arch ppc -mmacosx-version-min=10.6 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -L/opt/local/lib -Wl,-headerpad_max_install_names  CMakeFiles/cmTC_041cb.dir/src.cxx.o -o cmTC_041cb 
Undefined symbols:
  "___atomic_store_8", referenced from:
      _main in src.cxx.o
  "___atomic_fetch_sub_8", referenced from:
      _main in src.cxx.o
  "___atomic_load_8", referenced from:
      _main in src.cxx.o
ld: symbol(s) not found
collect2: error: ld returned 1 exit status
make[1]: *** [cmTC_041cb] Error 1
make: *** [cmTC_041cb/fast] Error 2

Source file was:

    #include <atomic>
    #include <stdint.h>
    int main() {
        std::atomic<int64_t> x;
        x = 1;
        x--;
        return (int) x;
    }

Of course it will not work without passing -latomic flag.

barracuda156 commented 8 months ago

Once -latomic flag is added, everything works and all tests pass:

--->  Testing primesieve
Executing:  cd "/opt/local/var/macports/build/_opt_PPCSnowLeopardPorts_math_primesieve/primesieve/work/build" && ctest 
Test project /opt/local/var/macports/build/_opt_PPCSnowLeopardPorts_math_primesieve/primesieve/work/build
      Start  1: calculator
 1/32 Test  #1: calculator .......................   Passed    0.01 sec
      Start  2: clear_primesieve_iterator1
 2/32 Test  #2: clear_primesieve_iterator1 .......   Passed    0.02 sec
      Start  3: clear_primesieve_iterator2
 3/32 Test  #3: clear_primesieve_iterator2 .......   Passed    0.01 sec
      Start  4: count_primes1
 4/32 Test  #4: count_primes1 ....................   Passed    0.81 sec
      Start  5: count_primes2
 5/32 Test  #5: count_primes2 ....................   Passed    7.45 sec
      Start  6: count_primes3
 6/32 Test  #6: count_primes3 ....................   Passed    6.34 sec
      Start  7: count_quadruplets
 7/32 Test  #7: count_quadruplets ................   Passed    0.41 sec
      Start  8: count_quintuplets
 8/32 Test  #8: count_quintuplets ................   Passed    0.41 sec
      Start  9: count_sextuplets
 9/32 Test  #9: count_sextuplets .................   Passed    0.43 sec
      Start 10: count_triplets
10/32 Test #10: count_triplets ...................   Passed    0.41 sec
      Start 11: count_twins
11/32 Test #11: count_twins ......................   Passed    0.39 sec
      Start 12: cpu_info
12/32 Test #12: cpu_info .........................   Passed    0.01 sec
      Start 13: floorPow2
13/32 Test #13: floorPow2 ........................   Passed    0.40 sec
      Start 14: generate_n_primes1
14/32 Test #14: generate_n_primes1 ...............   Passed   25.03 sec
      Start 15: generate_n_primes2
15/32 Test #15: generate_n_primes2 ...............   Passed    0.63 sec
      Start 16: generate_primes1
16/32 Test #16: generate_primes1 .................   Passed    0.21 sec
      Start 17: generate_primes2
17/32 Test #17: generate_primes2 .................   Passed   25.05 sec
      Start 18: ilog2
18/32 Test #18: ilog2 ............................   Passed    0.39 sec
      Start 19: isqrt
19/32 Test #19: isqrt ............................   Passed    0.39 sec
      Start 20: isqrt_constexpr
20/32 Test #20: isqrt_constexpr ..................   Passed    0.01 sec
      Start 21: move_primesieve_iterator
21/32 Test #21: move_primesieve_iterator .........   Passed    3.53 sec
      Start 22: next_prime1
22/32 Test #22: next_prime1 ......................   Passed    2.12 sec
      Start 23: next_prime2
23/32 Test #23: next_prime2 ......................   Passed   27.30 sec
      Start 24: nth_prime1
24/32 Test #24: nth_prime1 .......................   Passed    2.29 sec
      Start 25: nth_prime2
25/32 Test #25: nth_prime2 .......................   Passed    0.04 sec
      Start 26: nth_prime3
26/32 Test #26: nth_prime3 .......................   Passed    1.33 sec
      Start 27: number_of_bits
27/32 Test #27: number_of_bits ...................   Passed    0.01 sec
      Start 28: pod_vector
28/32 Test #28: pod_vector .......................   Passed    0.01 sec
      Start 29: prev_prime1
29/32 Test #29: prev_prime1 ......................   Passed   25.98 sec
      Start 30: prev_prime2
30/32 Test #30: prev_prime2 ......................   Passed    0.78 sec
      Start 31: skipto_next_prime
31/32 Test #31: skipto_next_prime ................   Passed   27.46 sec
      Start 32: skipto_prev_prime
32/32 Test #32: skipto_prev_prime ................   Passed    0.58 sec

100% tests passed, 0 tests failed out of 32
kimwalisch commented 8 months ago

The code below from CMakeLists.txt seems to be broken using the latest OSes, compilers, ...

find_library(ATOMIC NAMES atomic libatomic.so.1)

Ideally we would like to replace the code above and use a proper CMake module for libatomic. This did not exist a few years ago, but according to ChatGPT we could now potentially use:

# If atomic 64-bit code fails to compile then we
# need to add libatomic to the linker flags.
if(NOT atomic64)
    find_package(LibAtomic REQUIRED)
    set(LIBATOMIC ${LibAtomic_LIBRARIES})
    message(STATUS "Found libatomic: ${LIBATOMIC}")
endif()

instead of:

if(NOT atomic64)
    find_library(ATOMIC NAMES atomic libatomic.so.1)

    if(ATOMIC)
        set(LIBATOMIC ${ATOMIC})
        message(STATUS "Found libatomic: ${LIBATOMIC}")
    else()
        check_cxx_source_compiles("
            #include <atomic>
            #include <stdint.h>
            int main() {
                std::atomic<int32_t> x;
                x = 1;
                x--;
                return (int) x;
            }"
            atomic32)

        if(atomic32)
            message(FATAL_ERROR "Failed to find libatomic!")
        endif()
    endif()
endif()

I have not tested this yet, if it works there is a high risk that it will only work on newer OSes.

barracuda156 commented 8 months ago

I am pretty sure extension should not be added to a library name in the check. Also on Mac is will be dylib.

kimwalisch commented 8 months ago

Another option that would likely fix the problem and work well on old OSes is:

if(NOT atomic64)
    find_library(ATOMIC NAMES atomic libatomic.so.1)

    if(ATOMIC)
        set(LIBATOMIC ${ATOMIC})
        message(STATUS "Found libatomic: ${LIBATOMIC}")
    else()
        # Try -latomic as a fallback if our code fails to detect libatomic
        set(LIBATOMIC atomic)
        message(STATUS "Found libatomic: ${LIBATOMIC}")
    endif()
endif()
barracuda156 commented 8 months ago

@kimwalisch Something like this should work: https://github.com/pghysels/STRUMPACK/commit/be6d1f64314f7a66620a8f33c363919501dd30b4

See also: https://github.com/grpc/grpc/pull/21341/files https://github.com/potassco/clasp/issues/95 Etc., this is a recurring issue.

P. S. I should open an issue with CMake upstream, this has to be really implemented with CMake to begin with.

kimwalisch commented 8 months ago

@barracuda156 Can you please let me know where libatomic is located on your PC and how it is named?

I have found another code snippet online that I think is superior to the solutions I have seen so far: https://github.com/agroal/pgagroal/blob/master/cmake/FindLibatomic.cmake#L6. It is similar to the code used in primesieve but it includes hints to a list of paths where libatomic cloud potentially be located if the compiler/linker cannot find it in the default path.

kimwalisch commented 8 months ago

@barracuda156 Could you please try if the following fix works on your PC? Add libatomic.1.dylib to this line:

find_library(ATOMIC NAMES atomic atomic.so.1 libatomic.so.1 libatomic.1.dylib)

instead of:

find_library(ATOMIC NAMES atomic libatomic.so.1)

In the cmake/libatomic.cmake file.

kimwalisch commented 8 months ago

I was able to partially reproduce your issue on macOS 14.2 with homebrew GCC 13.2. I tried all of the potential solutions discussed in this thread, in the end the only solution that worked was adding -latomic to the linker options. So I have added this method as a fallback (https://github.com/kimwalisch/primesieve/blob/master/cmake/libatomic.cmake#L39) in case our other methods fail to find libatomic.

Could you please try if the latest code from the master branch works fine on your PC?

barracuda156 commented 8 months ago

@kimwalisch Sorry, it was a busy day, I am off the machine now. I can verify tomorrow, but passing -latomic must work, since that is exactly what we did to fix it in Macports locally: https://github.com/macports/macports-ports/commit/16d0102b8747fc8638706a73cdb792ed9695a083

kimwalisch commented 8 months ago

Closing, I assume I have fixed this.