azure-devopslinkerg++build-agent

g++ cannot link libatomic library on Microsoft user-agent


I have a very simple dummy program call main.c as below:

#include <stdlib.h>
#include <stdio.h>

#define TEST __atomic_compare_exchange

void test() {
    __int128 unsigned a = 1, b = 2, c = 3;
    __atomic_compare_exchange_16(&a, &b, c, 1, 1, 1);
printf("hello");
}

When compile using the following command, it works fine on my local Linux machine (Debian gcc version 6):

g++ --shared -o libmain.so -latomic main.c -Wl,--no-as-needed

However when using Microsoft hosted agent ubuntu-18.04, it fails regardless of whatever command I tried. Below is a list of commands that I have tried:

g++ --shared -o libmain.so -latomic main.c -Wl,--no-as-needed
g++ --shared -o libmain.so /usr/lib/x86_64-linux-gnu/libatomic.so.1 main.c -Wl,--no-as-needed
g++ --shared -o libmain.so -L/usr/lib/x86_64-linux-gnu/ -l:libatomic.so.1 main.c -Wl,--no-as-needed

When run ldd libmain.so not libatomic is showed in the list:

linux-vdso.so.1 (0x00007ffc3c5b6000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f889324e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8892eb0000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f8892c98000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f88928a7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f889385d000)

When run readelf -W -s libatomic.so, the __atomic_compare_exchange_16 shows as undefined without any suffix @... indicating the libatomic libary to look for.

Symbol table '.dynsym' contains 14 entries:
Num:    Value          Size Type    Bind   Vis      Ndx Name
  0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
  1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)
  2: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (2)
  3: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __atomic_compare_exchange_16
  4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@GLIBC_2.4 (3)
  5: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
  6: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
  7: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
  8: 0000000000201038     0 NOTYPE  GLOBAL DEFAULT   22 _edata
  9: 0000000000201040     0 NOTYPE  GLOBAL DEFAULT   23 _end
 10: 000000000000070a   150 FUNC    GLOBAL DEFAULT   12 _Z4testv
 11: 00000000000005c0     0 FUNC    GLOBAL DEFAULT    9 _init
 12: 0000000000201038     0 NOTYPE  GLOBAL DEFAULT   23 __bss_start
 13: 00000000000007a0     0 FUNC    GLOBAL DEFAULT   13 _fini

I have also check the g++ --print-search-dirs and the libraries search dirs look all correct to me.

Is Microsoft Hosted Agent environment just different or am I missing any obvious linker option?

Update This is a fundamental concept to linker symbol search order that I have missed. Usually, linker searches for symbols from left to right, but for some modern linkers, all libraries are searched regardless of order. I have tested this on one my other ubuntu VM and changing the order does work as expected.

Will update once I have tested with the Microsoft hosted user-agent.

Update 2 I can confirm that it is the difference between gcc linker in Ubuntu and my local machine Debian.


Solution

  • To answer my own question.

    The difference that I found is that on the Ubuntu machine, the gcc linker appear to search symbols in left to right order. Thus placing '-latomic' before the source file cause the reference to not be found and the library is not linked.

    On my local Debian machine, the linker search in both directions so the library is linked regardless of location of the '-l' option in the command.