问题描述
我正在尝试使GNUK软件可以与PlatformIO系统一起构建。我已经将Makefile转换为platformio.ini
项目文件,所有源文件都可以很好地编译,但是对于在我的C源文件之一中定义的两个数组,链接器出现多个定义错误。我的源文件的相关部分是:
typedef void (*handler)(void);
handler vector[] __attribute__ ((section(".vectors"))) = {
(handler)&__ram_end__,reset,(handler)set_led,flash_unlock,(handler)flash_program_halfword,(handler)flash_erase_page,(handler)flash_check_blank,(handler)flash_write,(handler)flash_protect,(handler)flash_erase_all_and_exec,usb_lld_sys_init,usb_lld_sys_shutdown,nvic_system_reset,};
const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = {
3*2+2,/* bLength */
0x03,/* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE*/
/* sys version: "1.0" */
'1','.','0',};
我得到的错误是:
.pio\build\OLIMEX_STM32_H103\src\sys.o:(.sys.version+0x0): multiple deFinition of `sys_version'
.pio\build\OLIMEX_STM32_H103\src\sys.o:(.sys.version+0x0): first defined here
.pio\build\OLIMEX_STM32_H103\src\sys.o:(.vectors+0x0): multiple deFinition of `vector'
.pio\build\OLIMEX_STM32_H103\src\sys.o:(.vectors+0x0): first defined here
我坚持使用它,甚至不知道从哪里开始。如果我将新变量添加到该源文件中,我也会得到类似的链接器错误。似乎同一文件被链接了两次?
__main_stack_size__ = 0x0400;
__process_stack_size__ = 0x0200;
__stacks_total_size__ = __main_stack_size__ + __process_stack_size__;
MEMORY
{
flash0 : org = 0x08000000,len = 4k
flash : org = 0x08000000+0x1000,len = 128k - 4k
ram : org = 0x20000000,len = 20k
}
/* __flash_start__: flash ROM start address regardless of DFU_SUPPORT */
__flash_start__ = 0x08001000;
__flash_end__ = ORIGIN(flash) + LENGTH(flash);
__ram_start__ = ORIGIN(ram);
__ram_size__ = LENGTH(ram);
__ram_end__ = __ram_start__ + __ram_size__;
SECTIONS
{
. = 0;
.sys : ALIGN(16) SUBALIGN(16)
{
_sys = .;
KEEP(*(.vectors))
. = ALIGN(16);
*(.sys.version)
src\sys.o(.text)
src\sys.o(.text.*)
src\sys.o(.rodata)
src\sys.o(.rodata.*)
. = ALIGN(1024);
*(.sys.0)
*(.sys.1)
*(.sys.2)
} > flash0
.text : ALIGN(16) SUBALIGN(16)
{
_text = .;
KEEP(*(vectors))
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
*(.glue_7t)
*(.glue_7)
*(.gcc*)
} > flash
.ctors :
{
PROVIDE(_ctors_start_ = .);
KEEP(*(SORT(.ctors.*)))
KEEP(*(.ctors))
PROVIDE(_ctors_end_ = .);
} > flash
.dtors :
{
PROVIDE(_dtors_start_ = .);
KEEP(*(SORT(.dtors.*)))
KEEP(*(.dtors))
PROVIDE(_dtors_end_ = .);
} > flash
.ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)}
__exidx_start = .;
.ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > flash
__exidx_end = .;
.eh_frame_hdr : {*(.eh_frame_hdr)}
.eh_frame : ONLY_IF_RO {*(.eh_frame)}
. = ALIGN(4);
_etext = .;
_textdata = _etext;
.data :
{
_data = .;
*(.data)
. = ALIGN(4);
*(.data.*)
. = ALIGN(4);
*(.ramtext)
. = ALIGN(4);
_edata = .;
} > ram AT > flash
.bss :
{
_bss_start = .;
*(.bss)
. = ALIGN(4);
*(.bss.*)
. = ALIGN(4);
*(COMMON)
. = ALIGN(4);
_bss_end = .;
} > ram
PROVIDE(end = .);
_end = .;
. = ALIGN(512);
_regnual_start = .;
.gnuk_flash :
{
. = ALIGN (1024);
_data_pool = .;
KEEP(*(.gnuk_data))
. = ALIGN(1024);
. += 1024;
_keystore_pool = .;
. += 512*3;
. = ALIGN(1024);
_updatekey_store = .;
. += 1024;
. = ALIGN(1024);
} > flash =0xffffffff
}
__heap_base__ = _end;
__heap_end__ = __ram_end__ - __stacks_total_size__;
解决方法
解决方案是将链接描述文件中的src\sys.o
替换为*sys.o
。
如ld手册所述,
在任何您可以使用特定文件或节名称的地方,您 也可以使用通配符模式。链接器处理通配符的方式与 Unix shell可以。 “ *”字符与任意数量的字符匹配。 一种 '?'字符匹配任何单个字符。序列“ [字符]” 将匹配任何字符的单个实例;人物 可以用来指定字符范围,例如'[a-z]'以匹配 任何小写字母。 ''字符可用于引用 以下字符。
当文件名与通配符匹配时,通配符 将不匹配'/'字符(用于分隔目录名称 Unix)。由单个“ *”字符组成的模式是一个例外; 它将始终与任何文件名匹配。在部分名称中,通配符 字符将与“ /”字符匹配。
通配符仅匹配文件中明确指定的文件 命令行。链接器不搜索要扩展的目录 通配符。但是,如果您指定一个简单的文件名-不含 通配符-在链接描述文件中,文件名也不是 在命令行上指定,链接器将尝试打开 文件,就像它出现在命令行上一样。
sys.o
文件是在命令行中指定的,而不是链接器文件中的其他路径,因此链接器尝试将其链接两次。