makefile - 用于输入目标文件的 Makefile 配方问题
问题描述
我有一个生成文件,我对其进行了编辑,以便目标文件应该进入一个单独的目录。
我编辑了makefile,它现在正在做我想做的事情,但是在链接器阶段它没有按预期工作,因为我做错了什么。
我有一个sources
文件,makefile
如下所示:
源文件
TARGET = demo
SRC_DIR = modbus/ascii/ \
modbus/functions/ \
modbus/port/ \
modbus/rtu/ \
modbus/ \
./
INCLUDE_DIR = modbus/include/ \
modbus/port/ \
modbus/rtu \
modbus/ascii \
./
SOURCE = modbus/ascii/mbascii.c \
modbus/functions/mbfunccoils.c \
modbus/functions/mbfuncdiag.c \
modbus/functions/mbfuncdisc.c \
modbus/functions/mbfuncholding.c \
modbus/functions/mbfuncinput.c \
modbus/functions/mbfuncother.c \
modbus/functions/mbutils.c \
modbus/port/port.c \
modbus/port/portevent.c \
modbus/port/portserial.c \
modbus/port/porttimer.c \
modbus/rtu/mbcrc.c \
modbus/rtu/mbrtu.c \
modbus/mb.c \
demo.c \
startup_LPC17xx.c \
system_LPC17xx.c
生成文件
include ./sources
ARCH = arm-none-eabi
BUILD_DIR := build/objs
# Tool definitions
CC = $(ARCH)-gcc
LD = $(ARCH)-gcc
AR = $(ARCH)-ar
AS = $(ARCH)-as
CP = $(ARCH)-objcopy
OD = $(ARCH)-objdump
SIZE = $(ARCH)-size
RM = rm
Q = # @./quiet "$@"
# Flags
CFLAGS = -W -Wall -O0 --std=gnu99 -fgnu89-inline -mcpu=cortex-m3 -mthumb
CFLAGS += -ffunction-sections -fdata-sections
ASFLAGS =
LDFLAGS = -nostartfiles -specs=nosys.specs
CPFLAGS =
ODFLAGS = -x --syms
PRFLAGS ?=
# Source files
LINKER_SCRIPT = LPC17xx.ld
OBJS = $(SOURCE:.c=.o)
BUILD_OBJS := $(patsubst %,$(BUILD_DIR)/%,$(SOURCE:.c=.o))
OBJ_DIR := $(dir $(BUILD_OBJS))
INC_PARAMS = $(foreach d, $(INCLUDE_DIR), -I$d)
print-% : ; @echo $* = $($*)
.PHONY: all size clean nuke
all: $(TARGET).bin $(TARGET).hex
isp: $(TARGET).bin
# @./quiet $< cp $^ $(MBED_VOLUME)/
size: $(TARGET).elf
@$(SIZE) $<
%.hex: %.elf
$Q $(CP) $(CPFLAGS) -O ihex $< $*.hex
%.bin: %.elf
$Q $(CP) $(CPFLAGS) -O binary $< $*.bin
$(TARGET).elf: $(OBJS)
@touch $(@:.elf=.map)
$Q $(LD) -Xlinker -Map $(@:.elf=.map) $(LDFLAGS) -T $(LINKER_SCRIPT) $(BUILD_DIR)/$^ -o $@
$Q $(OD) $(ODFLAGS) $@ > $(@:.elf=.dump)
@$(SIZE) $@
$(OBJS): %.o: %.c
mkdir -p $(dir $(BUILD_OBJS))
$Q $(CC) $(CFLAGS) $(INC_PARAMS) -c $< -o $(BUILD_DIR)/$@
.PHONY: clean
clean: CRUFT=$(shell find . -name '*.o' -o -name '*.d')
clean: ; rm -f $(CRUFT); rm -f *.elf *.hex *.bin *.dump *.map; rm -rf $(BUILD_DIR)/*
nuke: clean
-rm -f *.hex *.bin *.dump *.map
问题是:
$Q $(LD) -Xlinker -Map $(@:.elf=.map) $(LDFLAGS) -T $(LINKER_SCRIPT) $(BUILD_DIR)/$^ -o $@
其输出为:
arm-none-eabi-gcc -Xlinker -Map demo.map -nostartfiles -specs=nosys.specs -T LPC17xx.ld build/objs/modbus/ascii/mbascii.o modbus/functions/mbfunccoils.o modbus/functions/mbfuncdiag.o modbus/functions/mbfuncdisc.o modbus/functions/mbfuncholding.o modbus/functions/mbfuncinput.o modbus/functions/mbfuncother.o modbus/functions/mbutils.o modbus/port/port.o modbus/port/portevent.o modbus/port/portserial.o modbus/port/porttimer.o modbus/rtu/mbcrc.o modbus/rtu/mbrtu.o modbus/mb.o demo.o startup_LPC17xx.o system_LPC17xx.o -o demo.elf
输出命令仅从build/objs
.
休息对象文件路径没有build/objs/
.
请有人帮我解决这个问题吗?
解决方案
您违反了 Mad Scientist 的第二条 makefile 规则,并引发了比您知道的更多的问题。
看看这些规则(简化):
$(TARGET).elf: $(OBJS)
$(LD) $(BUILD_DIR)/$^ -o $@
$(OBJS): %.o: %.c
$(CC) -c $< -o $(BUILD_DIR)/$@
假设构建目录是build/
,目标文件是build/foo.o
. 第二条规则的目标是foo.o
,但它实际构建的是build/foo.o
。同样,第一条规则声称foo.o
是先决条件,但实际上并没有使用foo.o
,它使用build/foo.o
这两个错误在某种意义上相互抵消了;Make 成功构建了主要目标。但是正如您所发现的,如果有多个目标文件,则会出现问题,因为如果先决条件列表是foo.o bar.o
,那么
`$(BUILD_DIR)/$^`
扩展到
build/foo.o bar.o
此外,即使build/foo.o
存在并且是最新的,Make 也会运行第二条规则,如果存在则将无法运行它foo.o
。非 PHONY 规则的目标应该是它构建的文件的名称,而非 PHONY 的先决条件应该是与其存在相关的文件的名称:
$(TARGET).elf: $(BUILD_OBJS)
$(LD) $^ -o $@
$(BUILD_OBJS): $(BUILD_DIR)/%.o: %.c
$(CC) -c $< -o $@
推荐阅读
- php - 用php删除部分字符串
- c# - 如何以编程方式将样式设置为 TextAppearance.DeviceDefault.Medium?
- javascript - 返回值不显示以及如何传递使用输入按钮接收的值
- firefox - 带有引导程序的 Mozilla 开发工具错误
- android - Android DataBinding - 为什么数据绑定不支持@mipmap 图像
- c# - 在 Chrome Selenium 上找不到文本框
- heroku - 将域名连接到 Heroku 应用程序时出现问题
- amazon-web-services - AWS S3:IA 与 One-Zone IA 存储类
- java - 在 Hibernate 中查找没有 id 的对象
- apache-spark - 为什么即使在火花上下文关闭后仍有剩余的java进程