Search code examples
c++gcclinker-errorsredhatstdatomic

Red Hat: using <atomic> compiles fine but linker can't find __atomic_store_16; what library?


I'm using atomic<> for the first time, and just as using <thread> requires you to link a thread library, it seems like using <atomic> wants you to do... something. What?

> uname -a
Linux sdclxd00239 3.10.0-693.11.6.el7.x86_64 #1 SMP Thu Dec 28 14:23:39 EST 2017 x86_64 x86_64 x86_64 GNU/Linu

> g++ Foo.cxx -g -o MsgQueueNoLock -pthread
/tmp/ccnGOKUG.o: In function `std::atomic<Ptr_T>::store(Ptr_T, std::memory_order)':
/opt/rh/devtoolset-7/root/usr/include/c++/7/atomic:239: undefined reference to `__atomic_store_16'
/tmp/ccnGOKUG.o: In function `std::atomic<Ptr_T>::load(std::memory_order) const':
/opt/rh/devtoolset-7/root/usr/include/c++/7/atomic:250: undefined reference to `__atomic_load_16'
collect2: error: ld returned 1 exit status>

g++ Foo.cxx -g -o Foo -pthread
/tmp/ccnGOKUG.o: In function `std::atomic<Ptr_T>::store(Ptr_T, std::memory_order)':
/opt/rh/devtoolset-7/root/usr/include/c++/7/atomic:239: undefined reference to `__atomic_store_16'
/tmp/ccnGOKUG.o: In function `std::atomic<Ptr_T>::load(std::memory_order) const':
/opt/rh/devtoolset-7/root/usr/include/c++/7/atomic:250: undefined reference to `__atomic_load_16'
collect2: error: ld returned 1 exit status

UPDATE: I need to use -latomic . Fair enough! However I can't find one I can actually use.

First I look under /usr/lib, and I see I have a simlink under gcc/.../4.8.2 pointing to gcc/.../4.8.5 ?!!? I've never in my life seen an old version depend on a new version though the timestamp causes me to suspect either manual intervention by someone in the past, or a complicated history.

> l `find /usr/lib -name '*atomic*'`
-rw-r--r--. 2 root root 1379 Jul 13  2017 /usr/lib/python2.7/site-packages/sos/plugins/atomichost.pyo
-rw-r--r--. 2 root root 1379 Jul 13  2017 /usr/lib/python2.7/site-packages/sos/plugins/atomichost.pyc
-rw-r--r--. 1 root root 1672 Jul 13  2017 /usr/lib/python2.7/site-packages/sos/plugins/atomichost.py
-rw-r--r--  1 root root   40 Sep 22  2017 /usr/lib/gcc/x86_64-redhat-linux/4.8.2/libatomic.so
-rw-r--r--  1 root root   38 Sep 22  2017 /usr/lib/gcc/x86_64-redhat-linux/4.8.2/32/libatomic.so
lrwxrwxrwx  1 root root   44 Jul  3  2018 /usr/lib/gcc/x86_64-redhat-linux/4.8.2/32/libatomic.a -> ../../../i686-redhat-linux/4.8.5/libatomic.a

Something on the 'net suggested I might find joy under /usr/local/lib but in fact joy is not to be found:

> find /usr/local/lib -name '*atomic*'
>

The gcc actually installed is old (4.8.5) and I'm running 7.2.1 via the scl utility, which puts /opt/rh/devtoolset-7/root/usr/bin/gcc into the path. Anticipating that the requisite lib was probably delivered with the gcc, I look at /opt/rh/devtoolset-7 ... and like a bad dream the libatomic.a again is a symlink to a non-existent file.

> l `find /opt/rh/devtoolset-7/ -name '*atomic*'`
    :
    (headers elided)
    :
-rw-r--r-- 1 root root 40975 Aug 31  2017 /opt/rh/devtoolset-7/root/usr/include/c++/7/atomic
-rw-r--r-- 1 root root    80 Aug 31  2017 /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/32/libatomic.so
-rw-r--r-- 1 root root  1553 Oct  6  2017 /opt/rh/devtoolset-7/root/usr/share/systemtap/tapset/linux/atomic.stp
lrwxrwxrwx 1 root root    40 Jul  3  2018 /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/32/libatomic.a -> ../../../i686-redhat-linux/7/libatomic.a

So using -L options with every path I can think of based on what find found, here's all the errors:

> g++ MsgQueueNoLock.cxx -g -o MsgQueueNoLock -pthread -latomic
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: cannot find -latomic
collect2: error: ld returned 1 exit status
> g++ MsgQueueNoLock.cxx -g -o MsgQueueNoLock -pthread -L/usr/lib/gcc/x86_64-redhat-linux/4.8.2 -latomic
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: cannot find /usr/lib64/libatomic.so.1.0.0
collect2: error: ld returned 1 exit status
> g++ MsgQueueNoLock.cxx -g -o MsgQueueNoLock -pthread -L/usr/lib/gcc/x86_64-redhat-linux/4.8.2/32 -latomic
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: cannot find /usr/lib/libatomic.so.1.0.0
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: skipping incompatible /usr/lib/gcc/x86_64-redhat-linux/4.8.2/32/libstdc++.so when searching for -lstdc++
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: skipping incompatible /usr/lib/gcc/x86_64-redhat-linux/4.8.2/32/libgcc_s.so when searching for -lgcc_s
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: skipping incompatible /usr/lib/gcc/x86_64-redhat-linux/4.8.2/32/libgcc.a when searching for libgcc.a
collect2: error: ld returned 1 exit status
> g++ MsgQueueNoLock.cxx -g -o MsgQueueNoLock -pthread -L/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/32 -latomic
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: skipping incompatible /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/32/libatomic.so when searching for -latomic
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: cannot find -latomic
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: skipping incompatible /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/32/libstdc++.so when searching for -lstdc++
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: skipping incompatible /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/32/libgcc_s.so when searching for -lgcc_s
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: skipping incompatible /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/32/libgcc.a when searching for libgcc.a
collect2: error: ld returned 1 exit status

Solution

  • There is a sample libatomic.c implementation here: https://gcc.gnu.org/wiki/Atomic/GCCMM?action=AttachFile&do=view&target=libatomic.c Its compilation produces several warnings but ultimately produces an object file.

    > gcc -c -o libatomic.o libatomic.c
    libatomic.c:475:1: warning: conflicting types for built-in function '__atomic_compare_exchange_1' [-Wbuiltin-declaration-mismatch]
     __atomic_compare_exchange_ ## SIZE   (I ## SIZE *mem, I ## SIZE *expect, I ## SIZE desired, int success, int failure)    \
     ^
    libatomic.c:524:1: note: in expansion of macro 'ATOMIC_COMPARE_EXCHANGE'
     ATOMIC_COMPARE_EXCHANGE (1)
     ^~~~~~~~~~~~~~~~~~~~~~~
    libatomic.c:475:1: warning: conflicting types for built-in function '__atomic_compare_exchange_2' [-Wbuiltin-declaration-mismatch]
     __atomic_compare_exchange_ ## SIZE   (I ## SIZE *mem, I ## SIZE *expect, I ## SIZE desired, int success, int failure)    \
     ^
    libatomic.c:537:1: note: in expansion of macro 'ATOMIC_COMPARE_EXCHANGE'
     ATOMIC_COMPARE_EXCHANGE (2)
     ^~~~~~~~~~~~~~~~~~~~~~~
    libatomic.c:475:1: warning: conflicting types for built-in function '__atomic_compare_exchange_4' [-Wbuiltin-declaration-mismatch]
     __atomic_compare_exchange_ ## SIZE   (I ## SIZE *mem, I ## SIZE *expect, I ## SIZE desired, int success, int failure)    \
     ^
    libatomic.c:551:1: note: in expansion of macro 'ATOMIC_COMPARE_EXCHANGE'
     ATOMIC_COMPARE_EXCHANGE (4)
     ^~~~~~~~~~~~~~~~~~~~~~~
    libatomic.c:475:1: warning: conflicting types for built-in function '__atomic_compare_exchange_8' [-Wbuiltin-declaration-mismatch]
     __atomic_compare_exchange_ ## SIZE   (I ## SIZE *mem, I ## SIZE *expect, I ## SIZE desired, int success, int failure)    \
     ^
    libatomic.c:565:1: note: in expansion of macro 'ATOMIC_COMPARE_EXCHANGE'
     ATOMIC_COMPARE_EXCHANGE (8)
     ^~~~~~~~~~~~~~~~~~~~~~~
    libatomic.c:475:1: warning: conflicting types for built-in function '__atomic_compare_exchange_16' [-Wbuiltin-declaration-mismatch]
     __atomic_compare_exchange_ ## SIZE   (I ## SIZE *mem, I ## SIZE *expect, I ## SIZE desired, int success, int failure)    \
     ^
    libatomic.c:579:1: note: in expansion of macro 'ATOMIC_COMPARE_EXCHANGE'
     ATOMIC_COMPARE_EXCHANGE (16)
     ^~~~~~~~~~~~~~~~~~~~~~~
    > ar rcs libatomic.a libatomic.o
    
    > g++ Foo.cxx -g -o Foo-pthread -L. -latomic
    

    Linking success: binary is created without error. My application is too partially-written to judge whether it actually works though.

    Even if this works, it's pretty clearly "not what you're supposed to have to do to get it to work." So I'm not marking this as "the" answer, just leaving it for future reference.