web-dev-qa-db-fra.com

Référence non définie à printf lors de l'utilisation du compilateur croisé GCC

J'essaie de compiler le programme 'Hello World' suivant à l'aide d'un compilateur croisé (GCC 4.9.2) ciblant mips:

#include <stdio.h>

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

La variable x permet d'empêcher GCC de modifier printf en puts, ce qui semble être le cas automatiquement pour une chaîne simple terminée par une nouvelle ligne.

J'ai construit un compilateur croisé sous ${HOME}/xc et je l'exécute à l'aide de la commande suivante:

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

Cependant, j'obtiens l'erreur suivante:

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

Je suppose que c'est un problème avec l'éditeur de liens car je m'attendrais à ce que le processus échoue plus tôt si, par exemple, stdio.h est introuvable dans le chemin de recherche. Je peux compiler un programme plus simple qui renvoie simplement zéro. Ainsi, l'ensemble de la chaîne d'outils n'est pas défectueux, il s'agit probablement de la liaison de bibliothèque standard (j'utilise newlib 2.2.0-1).

Je reçois la même erreur, que je lance le compilateur croisé sous Linux (Ubuntu 14.10) ou Cygwin (Windows 8).

La sortie complète de GCC est:

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

Le script de construction que j'utilise est ici (je l'ai écrit à partir d'une demi-douzaine de tutoriels suggérant des choses légèrement différentes):

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

Fondamentalement, il effectue les étapes suivantes:

  1. Construisez des binutils.
  2. Construire GCC (étape 1).
  3. Construisez newlib.
  4. Construire GCC (étape 2).

Je suis conscient qu'il existe d'autres outils tels que crosstool-ng et builtroot. Cependant, la personne sur laquelle je construis cette chaîne d'outils veut éditer des parties de binutils avant de lancer le processus de construction. Cette chaîne d'outils doit également fonctionner sous Cygwin ( crosstool-ng ne le fera pas pour diverses raisons, y compris les chemins de fichiers sensibles à la casse).

Je pense que cela va probablement être une chose évidente, mais cela fait une semaine que je déconne ça et je ne vois pas ce que cela pourrait être. Toute aide serait grandement appréciée!

13
pwaring

Il est nécessaire de construire des bibliothèques pour accompagner votre compilateur croisé. En particulier, vous devez disposer d'une version de glibc compilée de façon croisée ou d'une autre implémentation de la bibliothèque standard pour obtenir une version de printf().

Jetez un coup d'œil à ce lien pour obtenir un exemple du type d'éléments dont vous devez tenir compte pour obtenir tout ce dont vous avez besoin - le compilateur croisé, les en-têtes et les bibliothèques.

5
Peter

Essayez de relier la bibliothèque sur la ligne de commande:

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

L'inclusion de l'en-tête des bibliothèques std (lib et io) lie les implémentations par défaut (libc.so ou .a). Cependant, vous utilisez une implémentation "définie par l'utilisateur" et vous ne liez peut-être pas la bonne.

Je suggère un lien explicite sur la ligne de commande. Je ne suis pas certain de la syntaxe.

EDIT: Ou, mieux encore, utilisez un fichier makefile pour compiler avec les lignes suivantes et spécifiez d'autres répertoires include dans l'espace réservé INCLUDES:

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 est le fichier d'en-tête que vous allez inclure dans le fichier source newlib.c (implémentation/définition) (qui déclare les fonctions) et hello.c. Il peut être nommé différemment de stdio.h

Regardez ça, ça peut aider:

Pourquoi devez-vous lier la bibliothèque de mathématiques en C?

et cela aussi:

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

0
paxmemento

Le moyen le plus pratique d'y parvenir est d'utiliser putchar à la place de printf. Vous devrez peut-être modifier une partie de votre code ou vous devrez ajouter des macros/fonctions pouvant fonctionner comme printf.

0
totten

Un fichier de spécifications personnalisé pourrait fonctionner:

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

Ajouter au fichier de spécifications:

*lib:
-lc

Notez qu'il doit y avoir des lignes vides avant *lib: et après -lc. Peut-être devrez-vous remplacer le nom de la bibliothèque par le nom de votre bibliothèque newlib-c. Peut-être faut-il ajouter plus que seulement -lc, par exemple. La section *lib:- sur mon Linux est plus complexe.


UPDATE: Les spécifications intégrées lib pour les bibliothèques par défaut sont configurées ici:

Dans le fichier gcc-4.9.2/gcc/gcc.c lignes 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

Dans le fichier gcc-4.9.2/gcc/config/mips/elf.h lignes 40 à 42:

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

Peut-être que le LIB_SPEC par défaut dans gcc.c fonctionnera pour vous en commentant les lignes 40 à 42 dans elf.h. Vous devez peut-être modifier elf.h et remplacer le LIB_SPEC vide par "-lc" ou quelque chose de similaire.


UPDATE: Lorsque vous avez configuré gcc, vous avez donné --target=mips. Dans gcc-4.9.2\gcc\config.gcc, il existe d'autres cibles mips qui sont plus spécifiques, par exemple .mips*-*-linux*, peut-être que sélectionner celui qui convient donne le bon LIB_SPEC et que la liaison aboutira.


UPDATE: cible Linux big endian: mips-unknown-linux-gnu cible Linux peu endian: mipsel-unknown-linux-gnusource


UPDATE: À l'aide de votre script de construction, j'ai pu lier votre exemple de programme avec les modifications suivantes:

Dans votre config.sh:

export ISL_VERSION="0.12.2"

Dans le fichier gcc-4.9.2/gcc/config/mips/elf.h lignes 40 à 42:

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

Si vous ne voulez pas que la modification soit apportée à elf.h, les bibliothèques doivent être fournies lors de l'appel de mips-gcc.


METTRE &AGRAVE; JOUR:

newlib ne fonctionne pas du tout, GCC échoue à la deuxième étape avec une erreur sur l'impossibilité de trouver crti.o etc.

Étrange, en utilisant votre script de compilation, crti.o a été créé:

[osboxes@osboxes 4.9.2]$ pwd
/home/osboxes/xc/lib/gcc/mips/4.9.2
[osboxes@osboxes 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
0
4566976