如何执行生成规则 return 以构建对象的 makefile 函数

How to do a makefile function that generate rules an return to build objects

我有当前代码 它允许我轻松生成二进制文件的目标文件

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

我想做一个函数,将资产作为参数,为它们生成规则,然后 return 我将 .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

我试图将 eval 的 foreach 循环与最终对象名称结合起来,但是当我这样做时我得到了 *** prerequisites cannot be defined in recipes.。 这种事情可以做吗?

OBJ=$(call BINARY_ASSETS,$(ASSETS))

这是错误的,因为 OBJ 的值,即 $(call ...),稍后在其他配方和先决条件中被扩展(即调用),这是 make 抱怨的原因。您可以在此处仅使用简单赋值:

OBJ:=$(call BINARY_ASSETS,$(ASSETS))

请参阅 two flavors of variables 上的 make 手册(如果您像我一样发现此文本难以理解,请尝试想象 make 中的“=”运算符将原样的文字字符串赋值给变量)。

此外,我强烈建议尽可能使用自动变量,例如:

$(NAME): $(OBJ)
    $(AR) $(ARFLAGS) $@ $?

您需要更新 ASSET_RULE 内的 OBJS,因为宏将只能 return $(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)

测试 运行 我将 eval 替换为 info 以显示生成的代码:

$ 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)