Erreur de Linker sur un projet C en utilisant Eclipse

je veux créer un projet pour le microcontrôleur STM32F217IG.

puis J'ai installé Eclipse et le GNU ARM intégré GCC le compilateur croisé. Je ne pense pas que c'est le Code Sourcery. Je l'ai utilisé, parce qu'il supporte la virgule flottante et Code Sourcery ne l'est pas.

une fois que je l'ai fait j'ai essayé de créer un projet vraiment petit avec seulement deux fichiers sources: test.c et main.c avec seulement écrit en deux:

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

int main (void)
{
    printf("Hello, World!");
    return 0;
}

j'ai changé la ligne commande dans la propriété du projet de remplacer GCC par arm-none-EABI-gcc et a ensuite essayé de compiler le projet.

Je n'ai pas créé de fichier make moi-même; J'ai utilisé la création automatique dans Eclipse.

Le bâtiment semble être bien, mais quand il s'agit de l'éditeur de liens, j'ai les erreurs suivantes dans la console:

make all
'Building target: test3'
'Invoking: Cross GCC Linker'
arm-none-eabi-gcc  -o"test3"  ./main.o ./test3.o

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text._write_r+0x20): undefined reference to `_write'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0x18): undefined reference to `_close'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0x18): undefined reference to `_isatty'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x20): undefined reference to `_lseek'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x20): undefined reference to `_read'

collect2: ld returned 1 exit status

make: *** [test3] Erreur 1

j'ai regardé sur Internet et j'ai trouvé qu'il peut être un syscall problème. Mais je ne sais pas comment ajouter cette bibliothèque à mon projet sur Linux.

Est-il vraiment? Si oui, comment puis-je résoudre ce problème? Et si non, d'où cela vient-il?

comme quelqu'un l'a suggéré, j'ai essayé de "lier" la bibliothèque C runtime. Sur Eclipse, il semble que j'ai deux solutions pour le faire:

d'Abord sur les propriétés du projet → C / C++ConstruireParamètresCroix de l'éditeur de liensbibliothèques. Je viens d'ajouter la lettre c et puis l'erreur ne change pas, mais il n'y a -lc à la fin de la ligne de commande:

 make all
'Building target: test3'
'Invoking: Cross GCC Linker'
arm-none-eabi-gcc  -o"test3"  ./main.o ./test3.o   -lc

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text._write_r+0x20): undefined reference to `_write'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0x18): undefined reference to `_close'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0x18): undefined reference to `_isatty'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x20): undefined reference to `_lseek'

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/liblibc.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x20): undefined reference to `_read'

collect2: ld returned 1 exit status
make: *** [test3] Erreur 1

mais je ne sais pas si c'est vraiment le moyen d'ajouter la bibliothèque d'exécution ctime.

Secundo, j'ai ajouté la libc.une bibliothèque dans les propriétés du projet → C/C++ général chemin et symbolesBibliothèques et voici ce que j'obtiens (totalement différent):

make all
'Building target: test3'
'Invoking: Cross GCC Linker'
arm-none-eabi-gcc  -o"test3"  ./main.o ./test3.o   -l"C:/Program Files/GNU Tools ARM Embedded/4.6 2012q4/arm-none-eabi/lib/armv7-m/libc.a"

c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/bin/ld.exe: cannot find -lC:/Program Files/GNU Tools ARM Embedded/4.6 2012q4/arm-none-eabi/lib/armv7-m/libc.a

collect2: ld returned 1 exit status
make: *** [test3] Erreur 1

alors ça ne marche toujours pas, mais est-ce la bonne façon de chercher?

Oh et un très fait intéressant:

j'ai les erreurs seulement en mode debug. Si je suis en mode release, tout va bien, et je n'ai pas d'erreurs (sauf si j'ajoute la libc.alors je pense que ce n'est pas la bonne chose à faire). Est-ce que cela signifie que le problème est le .elfe de la création d'un fichier?

24
demandé sur Peter Mortensen 2012-11-05 19:59:36

5 réponses

j'ai regardé la boîte à outils que vous avez liée, juste pour lire ce qui suit dans le readme.txt:

cette chaîne d'outils est construite et optimisée pour le développement du métal nu Cortex-R/M.

en d'autres termes, cette chaîne d'outils est spécifiquement configurée pour les systèmes embarqués, peut-être sans aucun système d'exploitation. Dans ce cas, il n'y a pas de système pour fournir par exemple une sortie standard où printf() est censé écrire, il n'y a pas de système de fichiers, etc. - vous vous devez établir un lien avec une bibliothèque qui fournit ces services de base, si vous voulez les utiliser.

cela dit, votre boîte à outils fournit librdimon.a bibliothèque qui fournit tous ces services de base. Cette bibliothèque est en fait une partie de libgloss compilation. Si vous souhaitez lier à l'encontre de cela, essayez la commande suivante:

arm-none-eabi-gcc --specs=rdimon.specs   -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group -o test test.c

Ceci est un lien très bien sur mon PC, mais si c'est ce que vous voulez vraiment est une autre histoire (où vous attendez-vous à voir printf() sortie, de toute façon?).

pour votre puce, vous devriez probablement chercher une bibliothèque qui redirige la sortie standard vers le port série ou fournit une sortie de débogage sur JTAG. Vous pouvez aussi utiliser votre fonction personnalisée, par exemple envoyer la sortie de débogage à la console série au lieu de printf() - c'est à vous. Si vous décidez d'utiliser printf() je suggère la lecture de libgloss documentation.

aussi, je suggère de chercher une chaîne d'outils qui est spécialement fournie pour la famille STM32. Correctement configurer tous ces trucs de base (bibliothèque C, script de linker, etc.) nécessite un peu d'expérience.

Edit: de nombreux systèmes embarqués n'utilisent pas vraiment la bibliothèque standard C, en partant de zéro. Si vous voulez aller de cette façon, vous devriez passer -nostdlib pour votre gcc invocation. Bien sûr, vous n'aurez plus les choses comme printf() disponible.

Edit 2: une autre façon est d'utiliser la bibliothèque standard (newlib, je veux dire) sans libgloss et fournir des talons appropriés pour les choses dont vous n'avez pas besoin. Vous pouvez suivre ce tutoriel, où _read et _write est implémenté sur le port série, et tout le reste est bouché. C'est probablement ce que vous voulez vraiment.

26
répondu Code Painters 2012-11-07 10:01:42

je sais que c'est une vieille question, mais je suis tombé sur cela aujourd'hui en essayant de construire pour un conseil STM32. Le projet que j'ai a quelques scripts de linker (spécifiquement libs.ld). Ajout d'une entrée pour libnosys.a dans ce satisfait le linker et j'ai été en mesure de continuer.

libs.ld:

 GROUP(
   libgcc.a
   libg.a
   libc.a
   libm.a
   libnosys.a
 )
7
répondu Shane 2014-02-15 06:32:08

sauvegarder votre programme C en tant que " myprint.c", je le compilerai comme suit:

arm-none-EABI-gcc myprint.C-lc-specs=nosys.specs

aucune erreur et la sortie est correcte.

6
répondu Peter Teoh 2015-02-12 02:42:23

Il y avait aussi un problème avec malloc() et free() appels de fonction dans le projet Eclipse. J'ai écrit le firmware d'un microcontrôleur STM32 en utilisant Eclipse + GNU pour le compilateur croisé GCC embarqué ARM + STM32CubeMX pour l'initialisation de la périphérie du microcontrôleur et la création de scripts de linker.

quand j'ai ajouté des chaînes manquantes libg.a ( * ) et libnosys.a ( * ) jeter article de .ld script, mon projet a été construit avec succès.

3
répondu Sergey Starovoitov 2018-05-11 21:13:32

j'ai créé un projet RTOS en utilisant CubeMX et j'ai ajouté un printf et j'ai eu le même problème sur les liens, tout en déboguant en utilisant OpenOCD.

j'ai remplacé le printf ("Hello ARM World!") avec trace_puts("Bonjour les BRAS de Monde!"); et a fait apparaître les messages dans la console de débogage.

0
répondu Laguna Thangarajah 2018-05-11 21:14:20