【问题标题】:How to include syscalls.c from a separate library file?如何从单独的库文件中包含 syscalls.c?
【发布时间】:2014-09-15 15:05:29
【问题描述】:

我的代码包括对 _write()_sbrk() 等函数的间接调用。在项目中,我有一个名为 syscalls.c 的文件,它定义了我对这些函数的自定义实现,编译器/链接器找到了这个文件,并在我运行 make 时正确链接到这些函数。 make 创建的编译行如下所示:

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 项目中,因此它们应该包含在我编译 hardware_drivers 时创建的 libharware_drivers.a 文件中,并包含在上面的 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,并且我正在为 AT91SAM7A1 芯片编译它,如果这有任何相关性的话。

当链接器位于单独的库文件中时,您需要做一些特殊的事情来将链接器指向系统调用吗?

【问题讨论】:

    标签: c gcc linker arm system-calls


    【解决方案1】:

    你用,

    1. -nostartfiles
    2. 您在 libhardware_drivers.a 中创建了一个带有 _fstat 的文件
    3. 您使用一些代码与 _fstat_r 调用 ../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o)

    这是错误信息,

    ../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o):在函数“_fstat_r”中: fstatr.c:(.text._fstat_r+0x1c): 对'_fstat'的未定义引用

    您可以尝试从地图文件或-nodefaultlibs-nostdlibs 中找到使用_fstat_r 的代码。问题是库是按从头到尾的顺序解决的。在链接器列表的末尾有一个隐含的-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 在您的 syscall.o 中对 _fstat 的引用。另一种方法是在另一个目标文件(如 Main.o)中强制一些合成引用。宏可以强制链接,

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

    您的静态库中很可能有循环引用。即,hardware_driversframeworklibc(而 libc 指回 hardware_drivers 让事情发挥作用)。克服这个问题的方法是在命令行上多次列出库,或者重组你的代码,这可能是长期更好的选择。

    重组就像一个单独的libsyscall.a一样简单,在-lc之后列出。

    【讨论】:

    • 哇,解决了!非常感谢:)
    猜你喜欢
    • 2019-08-04
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    • 2012-05-24
    • 2020-03-16
    • 2011-12-25
    • 2010-10-30
    相关资源
    最近更新 更多