Sunday, April 15, 2012

How to solve the "undefined reference to '__sync_sub_and_fetch_4'" compilation problem

If you ran into the following compilation problems:
undefined reference to '__sync_sub_and_fetch_4' problem
or with any of the following functions:
__sync_fetch_and_add, __sync_fetch_and_sub, __sync_fetch_and_or, __sync_fetch_and_and, __sync_fetch_and_xor, __sync_fetch_and_nand,
 __sync_add_and_fetch, __sync_sub_and_fetch, __sync_sub_or_fetch, __sync_and_and_fetch, __sync_xor_and_fetch, __sync_nand_and_fetch
__sync_val_compare_and_swap, 
__sync_bool_compare_and_swap, 
__sync_lock_test_and_set,
__sync_lock_release

Chances are that you are trying to compile for ARM (or an exotic architecture) and your GCC version is too old compared to the source code you are trying to compile!
There is an Easy fix: upgrade your GCC.

If you can't upgrade your GCC for any reason (for example you are on an embedded hardware you don't have full control on), follow the steps below!

1. Find the source code file that's right for the architecture you are trying to compile on
You are going to find it inside a GCC source tarball.
To find it, go into your gcc source gcc/config and do
grep '__sync_fetch' */*
to find the right file.
For ARM, it is:
gcc/config/arm/linux-atomic.c

2. Compile the source code file and link in to the program you are compiling
libtool --tag=CC -mode=compile gcc -g -O2 -MT linux-atomic.lo -MD -MP -MF linux-atomic.Tpo -c -o linux-atmoic.lo linux-atmoic.c
libtool --tag=CC -mode=link gcc -g -O2 -o liblinux-atmoic.la linux-atmoic.lo
And add liblinux-atomic.la in the Makefile so it is linked to the other .la files (into a .so or a program).

3. Example to compile libtorrent 13.1 and rtorrent 0.9.1 for ARM with GCC 4.2.3
If you wonder, this is to compile rtorrent for my Iomega ix4-200d storcenter NAS.

Compile libtorrent:
PATH=$PATH:/opt/bin
wget http://libtorrent.rakshasa.no/downloads/libtorrent-0.13.1.tar.gz
tar -xvf libtorrent-0.13.1.tar.gz
cd libtorrent-0.13.1
vi configure
OPENSSL_CFLAGS='-I/opt/include/'
OPENSSL_LIBS='-L/opt/lib/ -lssl'
STUFF_LIBS='-L/opt/lib/ -lsigc-2.0'
STUFF_CFLAGS='-I/opt/usr/include/sigc++-2.0/ -I/opt/usr/lib/sigc++-2.0/include'

./configure --prefix=/opt/

Add linux-atomic:
cd src
wget http://dl.dropbox.com/u/50398581/rtorrent-0.9.1/linux_atomic.c
libtool --tag=CC --mode=compile gcc -g -O2 -MT linux_atomic.lo -MD -MP -MF linux_atomic.Tpo -c -o linux_atomic.lo linux_atomic.c
vi /opt/bin/libtool

And if necessary, modify libtool for the follwoing entries:
AR="ar"
RANLIB="ranlib"
CC="g++"

libtool --tag=CC   --mode=link gcc  -g -O2  -o liblinux_atomic.la linux_atomic.lo
vi Makefile

add
liblinux_atomic.la
at the end of libtorrent_la_LIBADD

cd ..
make
strip .libs/libtorrent.so
make install


Compile rtorrent:
wget http://libtorrent.rakshasa.no/downloads/rtorrent-0.9.1.tar.gz
tar -xvf rtorrent-0.9.1.tar.gz
cd rtorrent-0.9.1
vi configure
And add:
sigc_LIBS='-L/opt/lib/ -lsigc-2.0 -L/lib/'
sigc_CFLAGS='-I/opt/usr/include/sigc++-2.0/ -I/opt/usr/lib/sigc++-2.0/include -I/opt/include/ncurses'
libcurl_LIBS='-L/opt/lib/ -lcurl'
libcurl_CFLAGS='-I/opt/include/'
libtorrent_LIBS='-L/opt/lib/ -ltorrent'
libtorrent_CFLAGS='-I/opt/include/'

Then:
./configure --prefix=/opt/ --with-xmlrpc-c=/opt/bin/xmlrpc-c-config  --with-ncurses=yes LDFLAGS='-L/opt/lib/' CPPFLAGS='-I/opt/include -I/opt/include/ncurses/' 
cd src
cp ../../libtorrent-0.13.1/.libs/liblinux_atomic.a .
vi Makefile
at the end of rtorrent_LDADD, add
liblinux_atomic.a

Then:
make
strip rtorrent
cd ..
make install

You are done!

3 comments:

  1. Thanks! Exactly what I was looking for. :)

    ReplyDelete
  2. There is a typo
    "atmoic" in few lines

    ReplyDelete
  3. Hi
    I'm facing such a kind of problem on a mips platform.
    Unfortunately MIPS gcc doesn't provide any linux-atomic.c file under the directory gcc/mips/configs.
    Any idea to fix the same problem on a MIPS architecture?
    Any suggestion will be appreciated
    with regards
    fabio

    ReplyDelete