>我有当前的代码它使我可以轻松地生成二进制文件的对象文件
define ASSET_RULE
$(addsuffix .o,$(basename $(1))): $(1)
$(LD) -r -b binary $(1) -o $(addsuffix .o,$(basename $(1)))
endef
SRC=avatar.jpg
avatar2.png
OBJ=$(addsuffix .o,$(basename $(SRC)))
NAME=assets.a
all: $(NAME)
$(foreach file,$(SRC), $(eval $(call ASSET_RULE,$(file))))
$(NAME): $(OBJ)
$(AR) rcs $(NAME) $(OBJ)
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY: clean fclean all re
我想做一个函数,将资产作为参数,为它们生成规则,并将 .o 文件返回给我以编译为依赖项。到最后,我希望有类似的东西。
ASSETS=avatar.jpg
avatar2.png
OBJ=$(call BINARY_ASSETS,$(ASSETS))
NAME=assets.a
all: $(NAME)
$(NAME): $(OBJ)
$(AR) rcs $(NAME) $(OBJ)
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY: clean fclean all re
我试图将我的 foreach 循环与最终的对象名称结合起来,但是当我这样做时,我得到了*** prerequisites cannot be defined in recipes.
。这种事情可以做吗?
在ASSET_RULE
中更新OBJS
,因为宏只能返回$(eval)
的makefile代码。我已经省略了您的makefile中与手头问题无关的所有部分:
# $(1): source file name
define ASSET_RULE
_obj_name := $(addsuffix .o,$(basename $(1)))
$$(_obj_name): $(1)
$(LD) -r -b binary $$< -o $$@
OBJS += $$(_obj_name)
_obj_name :=
endef
# $(1): list of source files
BINARY_ASSETS = $(eval
$(foreach _a,$(1),
$(call ASSET_RULE,$(_a))
)
)
ASSETS :=
avatar.jpg
avatar2.png
OBJS :=
$(call BINARY_ASSETS,$(ASSETS))
.PHONY: all
all: $(OBJS)
测试运行,我用info
替换了eval
以显示生成的代码:
$ make
_obj_name := avatar.o
$(_obj_name): avatar.jpg
ld -r -b binary $< -o $@
OBJS += $(_obj_name)
_obj_name :=
_obj_name := avatar2.o
$(_obj_name): avatar2.png
ld -r -b binary $< -o $@
OBJS += $(_obj_name)
_obj_name :=
make: Nothing to be done for 'all'.
如果要使用 BINARY_ASSETS
更新不同的变量,则需要第二个参数来传入变量名称:
# $(1): source file name
# $(2): variable name to add object file name to
define ASSET_RULE
_obj_name := $(addsuffix .o,$(basename $(1)))
$$(_obj_name): $(1)
$(LD) -r -b binary $$< -o $$@
$(2) += $$(_obj_name)
_obj_name :=
endef
# $(1): list of source files
# $(2): variable name to add object file names to
BINARY_ASSETS = $(eval
$(foreach _a,$(1),
$(call ASSET_RULE,$(_a),$(2))
)
)
$(call BINARY_ASSETS,$(ASSETS),OBJS)
OBJ=$(call BINARY_ASSETS,$(ASSETS))
这是错误的,因为OBJ
的价值,即 $(call ...)
,稍后在其他配方和先决条件中扩展(即调用(,这是 make 抱怨的原因。您只能在此处使用简单的赋值:
OBJ:=$(call BINARY_ASSETS,$(ASSETS))
查阅 make 关于两种变量的手册(如果您像我一样发现这段文字难以理解,请尝试想象 make 中的"="运算符将文本字符串原封不动地分配给变量(。
此外,我强烈建议尽可能使用自动变量,例如:
$(NAME): $(OBJ)
$(AR) $(ARFLAGS) $@ $?