gccclangcross-compilingtoolchainnewlib

Clang for newlib produces undefined symbols in libc.a


I am trying to build newlib with clang mostly following this script: https://github.com/jpbonn/Newlib-build-scripts I have removed all the compatibility issues in newlib between clang and gcc, following this thread: https://sourceware.org/ml/newlib/2015/msg00788.html

The library is finely built. However, I cannot use the libc.a to compile a simple Hello-World program simple.c. I get the following errors in the linker:

./bin/clang -nostdlib -fno-builtin -nostdlibinc -m32 simple.c $LIBC/lib/crt0.o -o simple -static -v -L $LIBC/lib -I $LIBC/include -lc -Wl,--verbose,-nostdlib

/lib/libc.a(lib_a-printf.o): In function `_printf_r':
newlib-1.18.0/newlib/libc/stdio/printf.c:35: undefined reference to `_vfprintf_r'
/lib/libc.a(lib_a-signal.o): In function `_init_signal_r':
/newlib-1.18.0/newlib/libc/signal/signal.c:110: undefined reference to `_malloc_r'
/lib/libc.a(lib_a-reent.o): In function `cleanup_glue':
newlib-1.18.0/newlib/libc/reent/reent.c:41: undefined reference to `_free_r'

However, when I am compiling newlib with a cross-compiled gcc, it compiles and produces the correct libc.a. I have checked with nm. clang-compiled libc.a doesn't have the symbol the symbols defined while cross-compiled-gcc-compiled libc.a does have those symbols:

cross-compiled-gcc-compiled libc.a with _vfprintf_r symbols

lib/libc.a:lib_a-fprintf.o:         U _vfprintf_r
lib/libc.a:lib_a-printf.o:         U _vfprintf_r
lib/libc.a:lib_a-vfprintf.o:00000000 T _vfprintf_r
lib/libc.a:lib_a-vprintf.o:         U _vfprintf_r

clang-compiled libc.a with _vfprintf_r symbols

lib/libc.a:lib_a-fprintf.o:         U _vfprintf_r
lib/libc.a:lib_a-printf.o:         U _vfprintf_r
lib/libc.a:lib_a-vprintf.o:         U _vfprintf_r

Point to note is that my clang is not cross-compiled for my custom platform. However, as clang is by definition a cross-compiler. Therefore, I am not building clang again. I am just providing appropriate parameter to clang. In my case I edit the makefile for newlib with the following CC_FOR_TARGET:

CC_FOR_TARGET="clang-5.0 -ffreestanding -m32 -save-temps"

I don't understand why clang is not able to produce same cross-compiled-gcc's similar libc.a. clang's libc.a is larger than cross-compiled-gcc's one though.

Is it because of the macro definitions that have provided to gcc? But in that case those definitions should have passed to the new CC_FOR_TARGET with clang as well. I am clueless after trying this for almost a week.


Solution

  • I figured out the problem. The problem is in the CFLAG -save-temps and with parallel make. I was running make -j25 or make -j30. It turns out that make is pretty lame in recognizing dependence over different recipes. Therefore, for the same .c file with different macros (-DSOMETHING1 and -DSOMETHING2), it was overwriting temporary files (.bc, .i, .s) in parallel run. Therefore, one symbol was omitted in the process while the other being added.