2015-05-03 23 views
13

Sto cercando di ottenere il seguente programma semplice 'Ciao Mondo' per compilare utilizzando un cross-compilatore (GCC 4.9.2) mira mips:undefined reference to printf quando si usa GCC croce compilatore

#include <stdio.h> 

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

Il x variabile è lì per fermare GCC cambiando printf a puts, che sembra fare automaticamente per una semplice stringa terminata a capo.

Ho costruito un compilatore croce sotto ${HOME}/xc e sto eseguendo utilizzando il seguente comando:

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

Tuttavia, sto ottenendo il seguente errore:

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

Sto assumendo questo è un problema con il linker, poiché mi aspetto che il processo fallisca prima se non è stato possibile trovare ad esempio stdio.h nel percorso di ricerca. Posso compilare un programma più semplice che restituisce semplicemente zero, quindi non è il caso che l'intera toolchain sia rotta, presumibilmente solo il collegamento della libreria standard (sto usando newlib 2.2.0-1).

Ottengo lo stesso errore indipendentemente dal fatto che eseguo il cross compiler sotto Linux (Ubuntu 14.10) o Cygwin (Windows 8).

L'uscita completa dal GCC è:

sceneggiatura
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 

La build che sto utilizzando è qui (ho scritto basa su una mezza dozzina di tutorial che tutto ha suggerito cose leggermente diverse):

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

Fondamentalmente si fa le seguenti fasi:

  1. Corporatura Binu TILS.
  2. Build GCC (fase 1).
  3. Costruisci newlib.
  4. Build GCC (stage 2).

Sono consapevole del fatto che ci sono altri strumenti come CrossTool-ng e builtroot, tuttavia la persona che sto costruendo questo toolchain per vuole modificare parti del binutils prima di partire il processo di compilazione, e la toolchain anche deve lavorare sotto Cygwin (crosstool-ng non per vari motivi, compresi i percorsi dei file sensibili al maiuscolo/minuscolo).

Penso che questo probabilmente sarà qualcosa di ovvio, ma ci ho lavorato per una settimana e non riesco a vedere cosa potrebbe essere. Qualsiasi aiuto sarebbe molto apprezzato!

+1

Provare a scaricare l'elenco di simboli definiti da newlib –

+0

Come fare? – pwaring

+0

Solo per curiosità: 'int main (void) {};' compila? – alk

risposta

5

È necessario creare librerie da utilizzare con il cross compilatore. In particolare, per ottenere una versione di printf() è necessario disporre di una versione cross-compiled di glibc o un'altra implementazione della libreria standard.

Dai uno sguardo al this link per un esempio del tipo di cose che devi considerare per ottenere tutto ciò di cui hai bisogno: il cross-compiler, le intestazioni e le librerie.

+0

Ho usato le istruzioni nel collegamento che hai menzionato, ma non avrei mai potuto compilare glibc, motivo per cui sono passato a newlib (che è stato compilato con successo). – pwaring

+0

Questa è probabilmente la risposta più vicina all'eventuale soluzione: ho dovuto usare glibc e giocare con le varie opzioni di configurazione finché non ho trovato quelle che funzionavano ('--disable-werror' era importante). – pwaring

+0

@pwaring Hai quasi finito. '$ {HOME}/xc/bin/mips-gcc ciao.c -lc -lcfe -lc' dovrebbe produrre un' a.out'. newlib dovrebbe funzionare. Solo '_start' è ancora mancante per l'argv e chiama la funzione principale. – 4566976

0

Un file specs personalizzato potrebbe funzionare:

cd /home/paul/xc/lib/gcc/mips/4.9.2/ 
${HOME}/xc/bin/mips-gcc -dumpspecs > specs 

aggiungere al file specs:

*lib: 
-lc 

Nota che ci deve essere righe vuote prima e dopo *lib:-lc. Forse devi cambiare il nome della libreria con il nome della tua libreria newlib-c. Forse più deve essere aggiunto che solo -lc, ad es. la sezione *lib: su Linux sembra più complessa.


AGGIORNAMENTO: Le specifiche incorporate lib per le librerie predefinite vengono configurate:

Nel file di gcc-4.9.2/gcc/gcc.c linee 527-530:

/* config.h can define LIB_SPEC to override the default libraries. */ 
#ifndef LIB_SPEC 
#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" 
#endif 

Nel file di gcc-4.9.2/gcc/config/mips/elf.h linee 40-42:

/* Leave the linker script to choose the appropriate libraries. */ 
#undef LIB_SPEC 
#define LIB_SPEC "" 

Forse l'impostazione predefinita LIB_SPEC in gcc.c funziona per te commentando le righe 40-42 in elf.h. Forse è necessario modificare elf.h e sostituire lo LIB_SPEC vuoto con "-lc" o qualcosa di simile.


UPDATE: quando si è configurato gcc ti ha dato --target=mips. In gcc-4.9.2\gcc\config.gcc ci sono altri obiettivi di mips che sono più specifici, ad es. mips*-*-linux*, forse selezionando quello appropriato si ottiene il valore LIB_SPEC e il collegamento avrà esito positivo.


UPDATE: big endian bersaglio Linux: mips-unknown-linux-gnu Little Endian obiettivo Linux: mipsel-unknown-linux-gnu source


UPDATE: Usando il vostro script di build sono stato in grado di collegare il vostro programma di esempio con i seguenti modifiche:

Nel tuo config.sh:

export ISL_VERSION="0.12.2" 

Nel file di gcc-4.9.2/gcc/config/mips/elf.h linee 40-42:

/* Leave the linker script to choose the appropriate libraries. */ 
#undef LIB_SPEC 
#define LIB_SPEC "-lc -lcfe -lc" 

Se non si desidera che la modifica elf.h le librerie deve essere data quando si richiama mips-gcc.


UPDATE:

newlib doesn't work at all, GCC fails in the second stage with an error about not being able to find crti.o etc.

Strano, usando il vostro script di build crti.o è stato creato:

[[email protected] 4.9.2]$ pwd 
/home/osboxes/xc/lib/gcc/mips/4.9.2 
[[email protected] 4.9.2]$ ll 
total 6240 
-rw-r--r--. 1 osboxes osboxes 3248 May 16 19:49 crtbegin.o 
-rw-r--r--. 1 osboxes osboxes 1924 May 16 19:49 crtend.o 
-rw-r--r--. 1 osboxes osboxes 1040 May 16 19:49 crti.o 
-rw-r--r--. 1 osboxes osboxes 1056 May 16 19:49 crtn.o 
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 include 
drwxrwxr-x. 2 osboxes osboxes 4096 May 16 19:45 include-fixed 
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 install-tools 
-rw-r--r--. 1 osboxes osboxes 6289352 May 16 19:49 libgcc.a 
-rw-r--r--. 1 osboxes osboxes 56844 May 16 19:49 libgcov.a 
drwxrwxr-x. 3 osboxes osboxes 4096 May 16 19:49 plugin 
-rw-rw-r--. 1 osboxes osboxes 6215 May 18 18:45 specs 
-1

printf() è stato implementato in libc,

Abilita le c lib, come glibc, oh, il tuo è newlib.


  1. provare @ 4566976 's modo
  2. uso readelf -s di controllo è esiste una sezione printf in libc.solibc.a

(non sono sicuro il nome del file lib in newlib, il mio è glibc)

+0

Sono consapevole che 'printf' è definito in' libc', quello che voglio sapere è come correggere l'errore del linker. 'Controlla il tuo C lib' non è molto utile. – pwaring

0

Prova a collegare la libreria sulla riga di comando:

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

L'inclusione delle librerie std (lib e io) collega le implementazioni di default (libc.so o .a). Tuttavia, stai utilizzando un'implementazione definita dall'utente e potresti non collegare quella corretta.

Suggerisco il collegamento esplicito sulla riga di comando. Non sono sicuro della sintassi.

EDIT: o, meglio ancora, utilizzare un makefile per compilare con le seguenti righe, e specificando includere altre directory nel INCLUDE posto titolare:

CC = gcc 
CXX = g++ 
INCLUDES = 
CFLAGS = -g -Wall $(INCLUDES) 
CXXFLAGS = -g -Wall $(INCLUDES) 
LDFLAGS = -g 
hello: hello.o newlib.o 
hello.o: hello.c newlib.h 
newlib.o: newlib.c newlib.h 

newlib.h è il file di intestazione si includere nel newlib.c (implementazione/definizione) file sorgente (che dichiara le funzioni) e hello.c. Potrebbe essere denominato diversamente da stdio.h.

check this out, può aiutare:

Why do you have to link the math library in C?

e anche questo:

http://www.tldp.org/HOWTO/Glibc2-HOWTO-6.html

0

Il modo più conveniente per raggiungere questo obiettivo è quello di utilizzare putchar al posto di printf. Potrebbe essere necessario modificare parte del codice, oppure potrebbe essere necessario aggiungere macro/funzioni che possono essere eseguite come printf.

+1

Non funzionerà, 'putchar' fa parte della libreria standard, quindi se c'è un problema con il linker si romperà su' putchar' proprio come per 'printf'. – pwaring

Problemi correlati