微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

链接期间排列多个定义错误

如何解决链接期间排列多个定义错误

我正在尝试使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文件是在命令行中指定的,而不是链接器文件中的其他路径,因此链接器尝试将其链接两次。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。