2014-09-15 4 views
3

Мой код включает косвенные вызовы функций, таких как _write() и _sbrk(). В рамках проекта у меня есть файл с именем syscalls.c, который определяет мои пользовательские реализации этих функций, а компилятор/компоновщик находит этот файл и правильно ссылается на функции при запуске make. Сетка компиляции создает выглядит примерно так:Как включить syscalls.c из отдельного файла библиотеки?

arm-none-eabi-gcc -nostartfiles -mcpu=arm7tdmi -Wl,--gc-sections -Wl,--cref -L../hardware_drivers/lib -L../framework/lib -T../linker-script.lds -Wl,-Map,./build/bin/Mapfile.map -o build/bin/Elffile.elf ./build/obj/Main.o ./build/obj/SomeCode.o ./build/obj/syscalls.o -Wl,--start-group -lhardware_drivers -lframework -Wl,--end-group 

Это работает отлично. Однако я хочу переместить syscalls.c в проект hardware_drivers, который у меня есть, поэтому они должны быть включены в файл libharware_drivers.a, который создается при компиляции hardware_drivers и включается в gcc-строку выше. Перемещение файла и перекомпиляция всех моих проектов включает мой syscalls.c в файле .a (показано с помощью arm-none-eabi-ar). Однако, когда речь идет о компиляции моего проекта верхнего уровня, я получаю эту ошибку:

../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o): In function `_fstat_r': 
fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat' 

Я использую arm-none-eabi-gcc v4.8 от кода Sourcery и я компилировать его для чипа AT91SAM7A1, если это имеет какое-либо актуальность.

Есть ли что-то особенное, что нужно сделать, чтобы указать компоновщик на системные вызовы, когда он находится в отдельном файле библиотеки?

ответ

3

используется,

  1. -nostartfiles
  2. Вы создаете файл с _fstat в libhardware_drivers.a
  3. Вы можете использовать код с _fstat_r вызова ../../arm-none-eabi /lib/libc.a(lib_a-fstatr.o)

Вот сообщение об ошибке,

../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o): In function '_fstat_r': fstatr.c:(.text._fstat_r+0x1c): undefined reference to '_fstat'

Вы можете попытаться найти код, который использует _fstat_r из файла карты или с -nodefaultlibs или -nostdlibs. Проблема в том, что библиотеки разрешены в порядке от первого до последнего. У вас есть неявный -lc в конце списка ваших линкеров. Если вы собираетесь использовать библиотеку 'C', то вы должны изменить команду компоновщика на позицию libhardware_drivers.a позже в ссылке.

Например,

arm-none-eabi-gcc -nostartfiles -mcpu=arm7tdmi -Wl,--gc-sections -Wl,--cref\ 
-L../hardware_drivers/lib -L../framework/lib -T../linker-script.lds \ 
-Wl,-Map,./build/bin/Mapfile.map -o build/bin/Elffile.elf ./build/obj/Main.o\ 
./build/obj/SomeCode.o ./build/obj/syscalls.o \ 
-Wl,--start-group -lc -lhardware_drivers -lframework -Wl,--end-group 

Здесь, -lc помещается перед -lhardware_drivers. Это позволит компоновщику разрешить ссылку lib_a-fstatr.o на _fstat в вашем syscall.o. Другим способом является принудительная синтетическая ссылка ранее в другом объектном файле (например, Main.o). Макрос может заставить ссылку,

#define FORCE_LINK(x) void* __ ## x ## _force_link =(void*)&x 
FORCE_LINK(fstat); 

Скорее всего, у вас есть круглые ссылки в ваших статических библиотеках.Т.е., hardware_drivers относится к рамках относится к LibcLibc ссылается на hardware_drivers делать работу). Методы для преодоления этого - перечислить библиотеки несколько раз в командной строке или перестроить ваш код, который, вероятно, будет более долгосрочным.

Реконструкция такая же простая, как отдельная libsyscall.a, которая указана после -lc.

+0

Вау, это исправлено! Большое спасибо :) –

Смежные вопросы