gpt4 book ai didi

c - 使用 arm-none-eabi-ar 将库相互链接时如何避免 undefined symbol

转载 作者:太空宇宙 更新时间:2023-11-04 08:12:54 25 4
gpt4 key购买 nike

我在 Linux 上使用 arm-none-eabi-gcc 工具链,但在创建链接到其他文件的文件时遇到了问题。作为一个具体的例子,基础文件(libstm32f4_hal.a)应该有一个函数HAL_SPI_GetState并且使用nm,它似乎有

$ nm libstm32f4_hal.a
stm32f4xx_hal_spi.o:
...
0000158d T HAL_SPI_GetState
00001495 T HAL_SPI_IRQHandler
00000271 T HAL_SPI_Init
...

然后我想制作另一个使用 libstm32f4_hal.a 的存档 (libstm32f4_bsp.a)。第二个存档似乎构建正确,但当我尝试链接这些库时,链接器抛出以下错误。

cube/Drivers/BSP/STM32F4-Discovery/libstm32f4_bsp.a(stm32f4_discovery.o): In function `SPIx_Init':
cube/Drivers/BSP/STM32F4-Discovery/stm32f4_discovery.c:313: undefined reference to `HAL_SPI_GetState'

当我使用 nm 检查 libstm32f4_bsp.a 时,确实未定义函数 HAL_SPI_GetState

$ nm libstm32f4_bsp.a
stm32f4_discovery.o:
...
U HAL_SPI_GetState
U HAL_SPI_Init
...

这是我用来构建第二个存档的 makefile。

CC=arm-none-eabi-gcc
AR=arm-none-eabi-ar

HAL_DIR = ../../STM32F4xx_HAL_Driver

###########################################

vpath %.c

CFLAGS = -g -O2 -Wall
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -ffreestanding -nostdlib

CFLAGS += -I$(HAL_DIR)/Inc
CFLAGS += -I../../CMSIS/Device/ST/STM32F4xx/Include
CFLAGS += -I../../CMSIS/Include

SRCS = stm32f4_discovery.c stm32f4_discovery_accelerometer.c stm32f4_discovery_audio.c


OBJS = $(SRCS:.c=.o)

.PHONY: all clean

all: libstm32f4_bsp.a

%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $^ -L$(HAL_DIR) -lstm32f4_hal

libstm32f4_bsp.a: $(OBJS)
$(AR) -rvs $@ $(OBJS)

clean:
rm -f $(OBJS) libstm32f4_bsp.a

有人可以解释为什么会这样吗?我很乐意提供更多详细信息,但我对我在这里尝试做的事情相对缺乏经验,并且我不完全确定还有什么可以提供帮助。

上下文是,我正在尝试为 STM32F4-Discovery 开发板构建演示代码。它基本上将电路板设置为充当 USB 鼠标。由于 USB 堆栈很大,我的计划是将硬件抽象层 (HAL) 构建为存档,然后将特定于板的中间件构建为链接到 HAL 存档的存档,然后在我的最终构建中将演示代码链接到这两个文件。

感谢您的帮助。

编辑:

这是我用来构建项目的 makefile。

# STM32 Makefile for GNU toolchain and openocd
#
# This Makefile fetches the Cube firmware package from ST's' website.
# This includes: CMSIS, STM32 HAL, BSPs, USB drivers and examples.
#
# Usage:
# make cube Download and unzip Cube firmware
# make program Flash the board with OpenOCD
# make openocd Start OpenOCD
# make debug Start GDB and attach to OpenOCD
# make dirs Create subdirs like obj, dep, ..
# make template Prepare a simple example project in this dir
#
# Copyright 2015 Steffen Vogel
# License http://www.gnu.org/licenses/gpl.txt GNU Public License
# Author Steffen Vogel <post@steffenvogel.de>
# Link http://www.steffenvogel.de
#
# edited for the STM32F4-Discovery

# A name common to all output files (elf, map, hex, bin, lst)
TARGET = demo

# Take a look into $(CUBE_DIR)/Drivers/BSP for available BSPs
BOARD = STM32F4-Discovery
BSP_BASE = stm32f4_discovery

OCDFLAGS = -f board/stm32f4discovery.cfg
GDBFLAGS =

#EXAMPLE = Templates
EXAMPLE = Demonstrations

# MCU family and type in various capitalizations o_O
MCU_FAMILY = stm32f4xx
MCU_LC = stm32f401xc
MCU_MC = STM32F407xx
MCU_UC = STM32F407VG




# Your C files from the /src directory
SRCS = main.c
SRCS += system_$(MCU_FAMILY).c
SRCS += stm32f4xx_it.c

# Basic HAL libraries
#SRCS += stm32f4xx_hal_rcc.c stm32f4xx_hal_rcc_ex.c stm32f4xx_hal.c stm32f4xx_hal_cortex.c stm32f4xx_hal_gpio.c $(BSP_BASE).c

# USB .c
SRCS += usbd_conf_template.c usbd_core.c usbd_ctlreq.c usbd_ioreq.c
SRCS += usbd_hid.c
SRCS += usbd_desc.c
SRCS += stm32f4xx_hal_pcd.c

SRCS += stm32f4_discovery_accelerometer.c stm32f4xx_hal_tim.c

# Directories
OCD_DIR = /usr/share/openocd/scripts

CUBE_DIR = cube

BSP_DIR = $(CUBE_DIR)/Drivers/BSP/$(BOARD)
HAL_DIR = $(CUBE_DIR)/Drivers/STM32F4xx_HAL_Driver
CMSIS_DIR = $(CUBE_DIR)/Drivers/CMSIS

DEV_DIR = $(CMSIS_DIR)/Device/ST/STM32F4xx

CUBE_URL = http://www.st.com/st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/firmware/stm32cubef4.zip

# that's it, no need to change anything below this line!

###############################################################################
# Toolchain

PREFIX = arm-none-eabi
CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
SIZE = $(PREFIX)-size
GDB = $(PREFIX)-gdb

OCD = openocd

###############################################################################
# Options

# Defines
DEFS = -D$(MCU_MC) -DUSE_HAL_DRIVER

# Debug specific definitions for semihosting
DEFS += -DUSE_DBPRINTF

# Include search paths (-I)
INCS = -Itemplate/inc
INCS += -I$(BSP_DIR)
INCS += -I$(CMSIS_DIR)/Include
INCS += -I$(DEV_DIR)/Include
INCS += -I$(HAL_DIR)/Inc

# USB .h
INCS += -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Inc
INCS += -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc

# Library search paths
LIBS = -L$(CMSIS_DIR)/Lib

# Compiler flags
CFLAGS = -Wall -g -std=c99 -Os
CFLAGS += -mlittle-endian -mcpu=cortex-m4 -march=armv7e-m -mthumb
CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += $(INCS) $(DEFS)

CFLAGS += -mthumb-interwork

# Linker flags
LDFLAGS = -Wl,--gc-sections -Wl,-Map=$(TARGET).map $(LIBS) -Ttemplate/$(MCU_LC).ld

# Enable Semihosting
LDFLAGS += --specs=rdimon.specs -lc -lrdimon

# Source search paths
VPATH = ./template/src
VPATH += $(BSP_DIR)
VPATH += $(HAL_DIR)/Src
VPATH += $(DEV_DIR)/Source/

VPATH += $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src
VPATH += $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src

OBJS = $(addprefix template/obj/,$(SRCS:.c=.o))
DEPS = $(addprefix template/dep/,$(SRCS:.c=.d))

# Prettify output
V = 0
Q = @
P = > /dev/null
endif

###################################################

.PHONY: all dirs program debug template clean

all: $(TARGET).elf

-include $(DEPS)

dirs: template/dep template/obj cube
template/dep template/obj template/src template/inc:
@echo "[MKDIR] $@"
$Qmkdir -p $@

template/obj/%.o : %.c | dirs
@echo "[CC] $(notdir $<)"
$Q$(CC) $(CFLAGS) -c -o $@ $< -MMD -MF template/dep/$(*F).d -L$(HAL_DIR) -lstm32f4_hal -L$(BSP_DIR) -lstm32f4_bsp

$(TARGET).elf: $(OBJS)
@echo "[LD] $(TARGET).elf"
$Q$(CC) $(CFLAGS) $(LDFLAGS) template/src/startup_$(MCU_LC).s $^ -o $@ -L$(HAL_DIR) -lstm32f4_hal -L$(BSP_DIR) -lstm32f4_bsp
@echo "[OBJDUMP] $(TARGET).lst"
$Q$(OBJDUMP) -St $(TARGET).elf >$(TARGET).lst
@echo "[SIZE] $(TARGET).elf"
$(SIZE) $(TARGET).elf

openocd:
$(OCD) -s $(OCD_DIR) $(OCDFLAGS)

program: all
$(OCD) -s $(OCD_DIR) $(OCDFLAGS) -c "program $(TARGET).elf verify reset"

debug:
@if ! nc -z localhost 3333; then \
echo "\n\t[Error] OpenOCD is not running! Start it with: 'make openocd'\n"; exit 1; \
else \
$(GDB) -ex "target extended localhost:3333" \
-ex "monitor arm semihosting enable" \
-ex "monitor reset halt" \
-ex "load" \
-ex "monitor reset init" \
$(GDBFLAGS) $(TARGET).elf; \
fi

cube:
rm -fr $(CUBE_DIR)
wget -O /tmp/cube.zip $(CUBE_URL)
unzip /tmp/cube.zip
mv STM32Cube* $(CUBE_DIR)
chmod -R u+w $(CUBE_DIR)
rm -f /tmp/cube.zip

template: cube template/src template/inc
cp -ri $(CUBE_DIR)/Projects/$(BOARD)/$(EXAMPLE)/Src/* template/src
cp -ri $(CUBE_DIR)/Projects/$(BOARD)/$(EXAMPLE)/Inc/* template/inc
cp -i $(DEV_DIR)/Source/Templates/gcc/startup_$(MCU_LC).s template/src
cp -i $(CUBE_DIR)/Projects/$(BOARD)/$(EXAMPLE)/TrueSTUDIO/STM32F4-DISCO/$(MCU_UC)_FLASH.ld template/$(MCU_LC).ld

clean:
@echo "[RM] $(TARGET).elf"; rm -f $(TARGET).elf
@echo "[RM] $(TARGET).map"; rm -f $(TARGET).map
@echo "[RM] $(TARGET).lst"; rm -f $(TARGET).lst
@echo "[RMDIR] template/dep" ; rm -fr template/dep
@echo "[RMDIR] template/obj" ; rm -fr template/obj

rm:
rm -rf template
ifeq ($V, 0)

这是失败的链接命令。

`arm-none-eabi-gcc -Wall -g -std=c99 -Os -mlittle-endian -mcpu=cortex-m4 -march=armv7e-m -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -Itemplate/inc -Icube/Drivers/BSP/STM32F4-Discovery -Icube/Drivers/CMSIS/Include -Icube/Drivers/CMSIS/Device/ST/STM32F4xx/Include -Icube/Drivers/STM32F4xx_HAL_Driver/Inc -Icube/Middlewares/ST/STM32_USB_Device_Library/Core/Inc -Icube/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc -DSTM32F407xx -DUSE_HAL_DRIVER -DUSE_DBPRINTF -mthumb-interwork -Wl,--gc-sections -Wl,-Map=demo.map -Lcube/Drivers/CMSIS/Lib -Ttemplate/stm32f401xc.ld --specs=rdimon.specs -lc -lrdimon template/src/startup_stm32f401xc.s template/obj/main.o template/obj/system_stm32f4xx.o template/obj/stm32f4xx_it.o template/obj/usbd_conf_template.o template/obj/usbd_core.o template/obj/usbd_ctlreq.o template/obj/usbd_ioreq.o template/obj/usbd_hid.o template/obj/usbd_desc.o template/obj/stm32f4xx_hal_pcd.o template/obj/stm32f4_discovery_accelerometer.o template/obj/stm32f4xx_hal_tim.o -o demo.elf -Lcube/Drivers/STM32F4xx_HAL_Driver -lstm32f4_hal -Lcube/Drivers/BSP/STM32F4-Discovery -lstm32f4_bsp'

我把项目加载到github here以防万一有人有足够的动力尝试自己构建项目。作为旁注,我正在运行 Arch Linux。

最佳答案

你失败的命令是这样的

arm-none-eabi-gcc ...-mcpu=cortex-m4 .. template/obj/main.o \
-lstm32f4_hal ... -lstm32f4_bsp

并且您的 libstm32f4_hal.a 存档定义了函数 HAL_SPI_GetState,并且此函数由 libstm32f4_bsp.a 存档使用。

因此,您的链接命令中的存档顺序错误。您应该知道链接器(ld,通常由 gcc 调用以执行实际的链接步骤)从左到右处理输入存档(.a 文件),检查ld(1) 的手册页位于 http://linux.die.net/man/1/ld

Normally, an archive is searched only once in the order that it is specified on the command line.

您可以尝试更改 hal 和 bsp 存档的顺序 (-lstm32f4_bsp ... -lstm32f4_hal),但如果它也失败了,那么您就有了循环依赖。您可能会在链接命令 (-lstm32f4_bsp ... -lstm32f4_hal -lstm32f4_bsp) 中多次提及库,或者只是指示链接器使用 -(-)--start-group--end-group 链接器选项,如 man 和在 https://stackoverflow.com/a/5651895/196561 .这些选项应放置在具有循环依赖性的库周围:--start-group -lstm32f4_bsp ... -lstm32f4_hal --end-group

来自 man page of ld 的选项的完整描述

-( archives -) --start-group archives --end-group

The archives should be a list of archive files. They may be either explicit file names, or -l options.

The specified archives are searched repeatedly until no new undefined references are created. Normally, an archive is searched only once in the order that it is specified on the command line. If a symbol in that archive is needed to resolve an undefined symbol referred to by an object in an archive that appears later on the command line, the linker would not be able to resolve that reference. By grouping the archives, they all be searched repeatedly until all possible references are resolved.

Using this option has a significant performance cost. It is best to use it only when there are unavoidable circular references between two or more archives.

当您使用 gcc 调用链接器时,如果您的 gcc 无法识别它们,请使用 -Wl, 前缀将选项传递给链接器:-Wl,--start-group - lstm32f4_bsp ... -lstm32f4_hal -Wl,--结束组

当您使用 shell/make 时,您可能需要在选项的简短变体中引用 (),例如使用单引号:'-Wl ,-(' -lstm32f4_bsp ... -lstm32f4_hal '-Wl,-)'

关于c - 使用 arm-none-eabi-ar 将库相互链接时如何避免 undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37900872/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com