链接期间阵列多个定义错误
Arrays multiple definition errors during linking
我正在尝试制作 GNUK software buildable with 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, '.', 0, '0', 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__;
解决方案是将 linker 脚本中的 src\sys.o
替换为 *sys.o
。
如ld手册所述,
In any place where you may use a specific file or section name, you
may also use a wildcard pattern. The linker handles wildcards much as
the Unix shell does. A '*' character matches any number of characters.
A '?' character matches any single character. The sequence '[chars]'
will match a single instance of any of the chars; the '-' character
may be used to specify a range of characters, as in '[a-z]' to match
any lower case letter. A '' character may be used to quote the
following character.
When a file name is matched with a wildcard, the wildcard characters
will not match a '/' character (used to separate directory names on
Unix). A pattern consisting of a single '*' character is an exception;
it will always match any file name. In a section name, the wildcard
characters will match a '/' character.
Wildcards only match files which are explicitly specified on the
command line. The linker does not search directories to expand
wildcards. However, if you specify a simple file name --a name with no
wildcard characters-- in a linker script, and the file name is not also
specified on the command line, the linker will attempt to open the
file as though it appeared on the command line.
sys.o
文件在命令行中指定的路径与 linker 文件中的路径不同,因此 linker 尝试 link 它两次。
我正在尝试制作 GNUK software buildable with 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, '.', 0, '0', 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__;
解决方案是将 linker 脚本中的 src\sys.o
替换为 *sys.o
。
如ld手册所述,
In any place where you may use a specific file or section name, you may also use a wildcard pattern. The linker handles wildcards much as the Unix shell does. A '*' character matches any number of characters. A '?' character matches any single character. The sequence '[chars]' will match a single instance of any of the chars; the '-' character may be used to specify a range of characters, as in '[a-z]' to match any lower case letter. A '' character may be used to quote the following character.
When a file name is matched with a wildcard, the wildcard characters will not match a '/' character (used to separate directory names on Unix). A pattern consisting of a single '*' character is an exception; it will always match any file name. In a section name, the wildcard characters will match a '/' character.
Wildcards only match files which are explicitly specified on the command line. The linker does not search directories to expand wildcards. However, if you specify a simple file name --a name with no wildcard characters-- in a linker script, and the file name is not also specified on the command line, the linker will attempt to open the file as though it appeared on the command line.
sys.o
文件在命令行中指定的路径与 linker 文件中的路径不同,因此 linker 尝试 link 它两次。