Undefined reference to printf when using GCC cross compiler

pwaring picture pwaring · May 3, 2015 · Viewed 34.3k times · Source

I'm trying to get the following simple 'Hello World' program to compile using a cross compiler (GCC 4.9.2) targeting mips:

#include <stdio.h>

int main()
{
  int x = 5;
  printf("x = %d\n", x);
}

The x variable is there to stop GCC changing printf to puts, which it seems to do automatically for a simple newline-terminated string.

I've built a cross compiler under ${HOME}/xc and am executing it using the following command:

${HOME}/xc/bin/mips-gcc -v hello.c

However, I'm getting the following error:

/tmp/ccW5mHJu.o: In function `main':
(.text+0x24): undefined reference to `printf'
collect2: error: ld returned 1 exit status

I'm assuming this is a problem with the linker, as I'd expect the process to fail earlier if for example stdio.h couldn't be found on the search path. I can compile a simpler program which simply returns zero, so it's not the case that the entire toolchain is broken, presumably just the standard library linking (I'm using newlib 2.2.0-1).

I get the same error regardless of whether I run the cross compiler under Linux (Ubuntu 14.10) or Cygwin (Windows 8).

The full output from GCC is:

Using built-in specs.
COLLECT_GCC=/home/paul/xc/bin/mips-gcc
COLLECT_LTO_WRAPPER=/home/paul/xc/libexec/gcc/mips/4.9.2/lto-wrapper
Target: mips
Configured with: /home/paul/xc/mips/tmp/gcc-4.9.2/configure --prefix=/home/paul/xc --target=mips --enable-languages=c --with-newlib --without-isl --without-cloogs --disable-threads --disable-libssp --disable-libgomp --disable-libmudflap
Thread model: single
gcc version 4.9.2 (GCC) 
COLLECT_GCC_OPTIONS='-v'
 /home/paul/xc/libexec/gcc/mips/4.9.2/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -auxbase hello -version -o /tmp/ccCpAajQ.s
GNU C (GCC) version 4.9.2 (mips)
    compiled by GNU C version 4.9.1, GMP version 6.0.0, MPFR version 3.1.2, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/sys-include"
#include "..." search starts here:
#include <...> search starts here:
 /home/paul/xc/lib/gcc/mips/4.9.2/include
 /home/paul/xc/lib/gcc/mips/4.9.2/include-fixed
 /home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/include
End of search list.
GNU C (GCC) version 4.9.2 (mips)
    compiled by GNU C version 4.9.1, GMP version 6.0.0, MPFR version 3.1.2, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: cffaaedf0b24662e67a5d97387fc5b17
COLLECT_GCC_OPTIONS='-v'
 /home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/as -EB -O1 -no-mdebug -mabi=32 -o /tmp/ccW5mHJu.o /tmp/ccCpAajQ.s
COMPILER_PATH=/home/paul/xc/libexec/gcc/mips/4.9.2/:/home/paul/xc/libexec/gcc/mips/4.9.2/:/home/paul/xc/libexec/gcc/mips/:/home/paul/xc/lib/gcc/mips/4.9.2/:/home/paul/xc/lib/gcc/mips/:/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/
LIBRARY_PATH=/home/paul/xc/lib/gcc/mips/4.9.2/:/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/lib/
COLLECT_GCC_OPTIONS='-v'
 /home/paul/xc/libexec/gcc/mips/4.9.2/collect2 -plugin /home/paul/xc/libexec/gcc/mips/4.9.2/liblto_plugin.so -plugin-opt=/home/paul/xc/libexec/gcc/mips/4.9.2/lto-wrapper -plugin-opt=-fresolution=/tmp/cc8TAJb9.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc -EB /home/paul/xc/lib/gcc/mips/4.9.2/crti.o /home/paul/xc/lib/gcc/mips/4.9.2/crtbegin.o -L/home/paul/xc/lib/gcc/mips/4.9.2 -L/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/lib /tmp/ccW5mHJu.o -lgcc -lgcc /home/paul/xc/lib/gcc/mips/4.9.2/crtend.o /home/paul/xc/lib/gcc/mips/4.9.2/crtn.o
/home/paul/xc/lib/gcc/mips/4.9.2/../../../../mips/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400050
/tmp/ccW5mHJu.o: In function `main':
(.text+0x24): undefined reference to `printf'
collect2: error: ld returned 1 exit status

The build script I'm using is here (I wrote it based on half a dozen tutorials which all suggested slightly different things):

https://github.com/UoMCS/mips-cross-compile

Basically it does the following steps:

  1. Build binutils.
  2. Build GCC (stage 1).
  3. Build newlib.
  4. Build GCC (stage 2).

I'm aware that there are other tools such as crosstool-ng and builtroot, however the person I'm building this toolchain for wants to edit parts of binutils before setting off the build process, and the toolchain also has to work under Cygwin (crosstool-ng won't for various reasons, including case-sensitive file paths).

I think this is probably going to be something obvious, but I've been messing around with this for a week and can't see what it could be. Any help would be greatly appreciated!

Answer

Peter picture Peter · May 3, 2015

It is necessary to build libraries to go with your cross compiler. In particular, you need to have a cross-compiled version of glibc or some other implementation of the standard library, to get a version of printf().

Have a look at this link for an example of the type of things you need to consider to get all the things you need - the cross-compiler, the headers, and libraries.