Arm IAR能否生成GCC可以链接的静态库?

Arm IAR能否生成GCC可以链接的静态库?,arm,interop,static-libraries,iar,gnu-toolchain,Arm,Interop,Static Libraries,Iar,Gnu Toolchain,有一个供应商的软件我想与之合作。他们有一个代码库,只能使用IAR Embedded Workbench编译(据我所知,他们的代码不使用GCC编译)。不幸的是,他们的硬件只能和他们的软件堆栈一起工作,所以我真的没有选择是否要使用它。他们将此代码作为为ARM Cortex-M4 CPU编译的.a静态库文件(以及附带的头文件)分发。(他们不想发布消息来源。)为了便于讨论,让我们将其称为evil\u sw\u stack.a 我想使用这段代码,但我没有IAR许可证,也没有IAR方面的专业知识。我想用GC

有一个供应商的软件我想与之合作。他们有一个代码库,只能使用IAR Embedded Workbench编译(据我所知,他们的代码不使用GCC编译)。不幸的是,他们的硬件只能和他们的软件堆栈一起工作,所以我真的没有选择是否要使用它。他们将此代码作为为ARM Cortex-M4 CPU编译的
.a
静态库文件(以及附带的头文件)分发。(他们不想发布消息来源。)为了便于讨论,让我们将其称为
evil\u sw\u stack.a

我想使用这段代码,但我没有IAR许可证,也没有IAR方面的专业知识。我想用GCC

有没有办法让IAR生成GCC可以链接的静态库?供应商需要使用哪种编译器选项来生成这样的二进制文件?
(我猜结果二进制文件的ABI可以以某种方式指定并设置为一个统计GCC的设置。)

GCC的示例用法 他们的默认软件堆栈非常GCC友好,这是他们产品中唯一一个不友好的。通常,如果我具备以下条件,我可以编译一段简单的示例代码:

  • 启动(devicename).S
    :特定于GCC的程序集文件
  • 系统(devicename).c
  • (devicename).ld
    :链接器脚本
  • 特定设备的某些头文件
例如,我可以编译一个简单的示例,如下所示:

$ arm-none-eabi-gcc helloworld.c startup_(devicename).S system_(devicename).c -T (devicename).ld -o helloworld -D(devicename) -I. -fno-builtin -ffunction-sections -fdata-sections -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mcpu=cortex-m4 -mthumb -mno-sched-prolog -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
到目前为止,一切顺利。没有警告,没有错误

如何尝试使用静态库 为了便于讨论,我们将其称为
邪恶的\u sw\u stack.a

以下是我尝试使用它的方式:

$ arm-none-eabi-gcc evil_sw_stack.a helloworld.c startup_(devicename).S system_(devicename).c -T (devicename).ld -o helloworld -D(devicename) -I. -fno-builtin -ffunction-sections -fdata-sections -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mcpu=cortex-m4 -mthumb -mno-sched-prolog -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
不幸的是,这会导致在
system(devicename.c
中定义了一系列函数的多个定义。也许他们不小心把它编译进了这个库?或者我就是这样编译的?现在,如果我试图从GCC命令行中删除
system_u2;(devicename).c
,并简单地链接到
.a
文件,我会得到以下错误:

/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: warning: thelibrary.a(startup_chipname.o) uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail
undefined reference to `__iar_program_start'
undefined reference to `CSTACK$$Limit'
undefined reference to `__iar_program_start'
readelf
戳这个文件不会让我有任何收获:

$ readelf -h evil_sw_stack.a 
readelf: Error: evil_sw_stack.a: did not find a valid archive header
但有趣的是,这似乎正在取得进展:

$ arm-none-eabi-ar x evil_sw_stack.a
现在我有了一堆对象文件,根据
readelf
,它们确实有ELF头,是的,它们确实将一个启动文件(它们的另一个设备的)编译到了库中。。。我想知道为什么,但我认为这是一个错误

这也适用于:

$ arm-none-eabi-objdump -t evil_sw_stack_objfile.o
现在的问题是,使用GCC将这些对象文件编译到我自己的应用程序中是否安全?根据,对象文件格式不兼容

我假设启动代码被错误地编译到库中。我可以删除它:

$ arm-none-eabi-ar d evil_sw_stack.a startup_(otherdevicename).o
$ arm-none-eabi-ar d evil_sw_stack.a system_(otherdevicename).o
现在我得到了一个
evil\u sw\u stack.a
,gcc可以毫无怨言地接受它作为输入

然而,有一件事仍然让我担心。当我使用对象文件而不是静态库时,会收到以下警告:

/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: warning: evil_objfile.o uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail
/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: warning: evil_objfile.o uses 32-bit enums yet the output is to use variable-size enums; use of enum values across objects may fail
因此,似乎
evil\u sw\u stack.a
是用(IAR等价物)
-fno short enum
-fshort wchar
编译的。当我在命令行中使用
evil\u sw\u stack.a
时,GCC不会抱怨这一点,但当我尝试使用从库中提取的任何对象文件时,GCC会抱怨。我应该担心这个吗

我在代码中不使用
wchar\t
,因此我相信这一点无关紧要,但我希望在代码和库之间传递枚举

更新 即使链接器没有抱怨,但当我实际从静态库调用某些函数时,它也不起作用。在这种情况下,请确保在调用链接器时按正确的顺序放置库。根据我们的观点,它们需要与依赖性的顺序相反。这样做之后,它仍然会漏掉一些IAR垃圾:

undefined reference to `__aeabi_memclr4'
undefined reference to `__aeabi_memclr'
undefined reference to `__aeabi_memmove'
undefined reference to `__aeabi_memset4'
undefined reference to `__aeabi_memset'
undefined reference to `__iar_vla_alloc2'
undefined reference to `__iar_vla_dealloc2'
undefined reference to `__aeabi_memclr4'
我发现
\uuu aeabi
函数是在
libgcc
中定义的,但即使我也链接到libgcc,
libgcc
中的定义对于
evil\u sw\u堆栈中的函数似乎不够好

编辑:在谷歌搜索之后,似乎
arm none eabi gcc
不支持这些特定的
\uu aeabi
功能。看一看

无论如何,在看了一下之后,丢失的
\uu aeabi
函数可以使用它们的标准C库等价物轻松实现。但我不太确定
\uu iar\u vla\u alloc2
\uu iar\u vla\u dealloc2
应该如何工作,因此无法在网上找到任何关于它们的文档。我唯一发现的是VLA的意思是“可变长度数组”

因此,除非芯片供应商能够以不使用这些符号的方式编译其静态库,否则这似乎永远不会起作用。是这样吗

免责声明
我不想透露谁是供应商,也不想透露我使用的产品。他们不为这东西不能正常工作而感到骄傲,并要求我不要这样做。我问这个问题是为了帮助他们,而不是诋毁他们。

一般来说,静态
.a
库是某种类型的或归档的(比如tar),包含一堆
.o
对象,这些对象可能是/可能不是elf(简短的研究表明ewarm是EABI elf)。您可以提取
.o
文件并逐个链接。看起来有一个
CSTACK$$Limit
\u iar\u program\u start
。第二个可能只是使用GNU工具启动。您必须研究这些符号,或者如果您可以补充问题
。o
您将避免使用这些符号。您可以尝试GNU
ar
程序,看看它是否理解静态
.a
ld
正在摸索。您还可以使用
nm
objdump
等。通常,这是可能的。然而,您似乎在链接启动代码,而启动代码几乎总是绑定在一起