Makefile 如果目标名称具有目录部分,则生成目录

Makefile 如果目标名称具有目录部分,则生成目录,makefile,wildcard,gnu-make,Makefile,Wildcard,Gnu Make,我有这个makefile代码: $(DIRS): @echo " MKDIR build/tmp/base/socket/$@" $(Q)mkdir -p $@/ %.a.s: @echo " CC build/tmp/base/socket/$@" $(Q)$(CC) $(CFLAGS_A) -S $< -o $@ %.so.s: @echo " CC build/tmp/base/socket/$

我有这个makefile代码:

$(DIRS):
    @echo   "   MKDIR   build/tmp/base/socket/$@"
    $(Q)mkdir -p        $@/


%.a.s:
    @echo   "   CC  build/tmp/base/socket/$@"
    $(Q)$(CC) $(CFLAGS_A) -S $< -o $@
%.so.s:
    @echo   "   CC  build/tmp/base/socket/$@"
    $(Q)$(CC) $(CFLAGS_SO) -S $< -o $@
%.o: %.s
    @echo   "   AS  build/tmp/base/socket/$@"
    $(Q)$(AS) $< -o $@


tcp/client.a.s: $(TCP_CLIENT_SRC) $(TCP_CLIENT_INC)
tcp/client.so.s: $(TCP_CLIENT_SRC) $(TCP_CLIENT_INC)

tcp/server.a.s: $(TCP_SERVER_SRC) $(TCP_SERVER_INC)
tcp/server.so.s: $(TCP_SERVER_SRC) $(TCP_SERVER_INC)
但它什么也没做

我还想到了更通用的,这会更好,但结果相同:

%.s: | $(@D)
我该怎么写呢



一种解决方法是每次调用mkdir(将其包含在%.A.s和%.so.s规则中),但这会增加对mkdir的不必要调用,不是吗?

您不能仅使用模式规则向给定的目标集添加先决条件。模式规则不是这样工作的:它们是规则:它们必须有一个与之相关联的配方。没有配方的模式规则实际上会删除该模式规则(请参阅)

您可以创建两组模式规则,一组用于所有目标,另一组用于仅以
tcp/
开头且具有额外先决条件的目标,但您必须编写两次整个模式规则,包括一个配方,而不仅仅是模式行


或者只需将
mkdir
放入配方中即可。已经存在的目录上的
mkdir
甚至不会引起注意。

您不能仅使用模式规则向给定的目标集添加先决条件。模式规则不是这样工作的:它们是规则:它们必须有一个与之相关联的配方。没有配方的模式规则实际上会删除该模式规则(请参阅)

您可以创建两组模式规则,一组用于所有目标,另一组用于仅以
tcp/
开头且具有额外先决条件的目标,但您必须编写两次整个模式规则,包括一个配方,而不仅仅是模式行


或者只需将
mkdir
放入配方中即可。已经存在的目录上的
mkdir
甚至不会引起注意。

我不喜欢模式规则。他们太武断了,不合我的口味。 (实际发生的情况取决于硬盘上可能有哪些文件。)


不能仅使用模式规则向给定的目标集添加先决条件

如果你使用的话,你可以。这是一个好得多的成语。在这里,我们用您希望模式规则应用到的源的实际列表作为模式规则的前缀。这是一个很好的地方,您可以使用make的noddy模式匹配来描述依赖关系

草图:

%.a: ; date >$@ # Pattern rule

tcp: ; mkdir -p $@ # Explicit rule

tcp/a.a: tcp/%.a: | tcp ; # Static pattern rule!

.PHONY: all
all: tcp/a.a
all: c.a
all: dir/b.a
all: ; : $@ Success
我们有:

$ make all
mkdir -p tcp
date >tcp/a.a
date >c.a
date >dir/b.a
/bin/sh: dir/b.a: No such file or directory
make: *** [Makefile:3: dir/b.a] Error 1
在这里,我们已经告诉make,在构建(即“运行”
tcp/a.a
的配方)之前,它必须首先构建
tcp
。这很有效。我们没有告诉make关于
dir/b.a
的目录,因此失败了。请注意,
.a
文件的配方仍处于普通模式规则中。这只是为了说明。我一定会改变这个

是的,在这种情况下,
tcp/
的模式规则是过度的。考虑一下,在创建<代码> TCP/A.A/COD>之前,您可能首先需要创建一个<代码> Auto/A.SRC(例如)。 易于扩展

targets := tcp/a.a tcp/b.a tcp/c.a
${targets}: tcp/%.a: auto/%.src | tcp ; # Static pattern rule!

[顺便说一句,在原始makefile中,存档和共享对象应该依赖于
.o
文件,而不是源(???)]

我不喜欢模式规则。他们太武断了,不合我的口味。 (实际发生的情况取决于硬盘上可能有哪些文件。)


不能仅使用模式规则向给定的目标集添加先决条件

如果你使用的话,你可以。这是一个好得多的成语。在这里,我们用您希望模式规则应用到的源的实际列表作为模式规则的前缀。这是一个很好的地方,您可以使用make的noddy模式匹配来描述依赖关系

草图:

%.a: ; date >$@ # Pattern rule

tcp: ; mkdir -p $@ # Explicit rule

tcp/a.a: tcp/%.a: | tcp ; # Static pattern rule!

.PHONY: all
all: tcp/a.a
all: c.a
all: dir/b.a
all: ; : $@ Success
我们有:

$ make all
mkdir -p tcp
date >tcp/a.a
date >c.a
date >dir/b.a
/bin/sh: dir/b.a: No such file or directory
make: *** [Makefile:3: dir/b.a] Error 1
在这里,我们已经告诉make,在构建(即“运行”
tcp/a.a
的配方)之前,它必须首先构建
tcp
。这很有效。我们没有告诉make关于
dir/b.a
的目录,因此失败了。请注意,
.a
文件的配方仍处于普通模式规则中。这只是为了说明。我一定会改变这个

是的,在这种情况下,
tcp/
的模式规则是过度的。考虑一下,在创建<代码> TCP/A.A/COD>之前,您可能首先需要创建一个<代码> Auto/A.SRC(例如)。 易于扩展

targets := tcp/a.a tcp/b.a tcp/c.a
${targets}: tcp/%.a: auto/%.src | tcp ; # Static pattern rule!

[顺便说一句,在原始makefile中,存档和共享对象应该依赖于
.o
文件,而不是源(??)

此答案仅显示实现@bobbogo答案的工作makefile

此Makefile是Makefile树的一个叶,因此此处未定义的所有变量都由上层Makefiles导出

Makefile

#! /usr/bin/make -f

################################################################################
# *AUTHOR*
# FULL NAME     "Alejandro Colomar Andrés"
################################################################################

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

DIRS    =                               \
        $(CURDIR)/tcp

OBJ     =                                                               \
        $(CURDIR)/tcp/client.o                                          \
        $(CURDIR)/tcp/server.o                                        \
        $(CURDIR)/foo.o

SRC     =                                                               \
        $(SRC_DIR)/base/socket/tcp/client.c                             \
        $(SRC_DIR)/base/socket/tcp/server.c                             \
        $(SRC_DIR)/base/socket/foo.c

DEP             = $(OBJ:.o=.d)
BOTH_OBJ        = $(subst .a.o,.a.o ,$(join $(OBJ:.o=.a.o),$(OBJ:.o=.so.o)))
BOTH_ASM        = $(subst .a.s,.a.s ,$(join $(OBJ:.o=.a.s),$(OBJ:.o=.so.s)))
NEEDDIR         = $(DEP) $(BOTH_ASM)

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

PHONY := all
all: $(BOTH_OBJ)
        @:

$(DIRS): $(CURDIR)/%:
    @echo   "   MKDIR   build/tmp/base/socket/$*"
    $(Q)mkdir -p        $@

$(NEEDDIR): | $(DIRS)

$(CURDIR)/%.d: $(SRC_DIR)/base/socket/%.c
        @echo   "       CC -M   build/tmp/base/socket/$*.d"
        $(Q)$(CC) $(CFLAGS_A) -MG -MT"$@"                               \
                        -MT"$(CURDIR)/$*.a.s" -MT"$(CURDIR)/$*.so.s"    \
                        -M $< -MF $@
$(CURDIR)/%.a.s: $(SRC_DIR)/base/socket/%.c $(CURDIR)/%.d
        @echo   "       CC      build/tmp/base/socket/$*.a.s"
        $(Q)$(CC) $(CFLAGS_A) -S $< -o $@
$(CURDIR)/%.so.s: $(SRC_DIR)/base/socket/%.c $(CURDIR)/%.d
        @echo   "       CC      build/tmp/base/socket/$*.so.s"
        $(Q)$(CC) $(CFLAGS_SO) -S $< -o $@
$(CURDIR)/%.o: $(CURDIR)/%.s
        @echo   "       AS      build/tmp/base/socket/$*.o"
        $(Q)$(AS) $< -o $@

include $(DEP)


PHONY += clean
clean:
        $(Q)rm -rf *.o *.s *.d
################################################################################
# Declare the contents of the PHONY variable as phony.
.PHONY: $(PHONY)


################################################################################
######## End of file ###########################################################
################################################################################

这个答案只是为了显示一个实现@bobbogo答案的工作Makefile

此Makefile是Makefile树的一个叶,因此此处未定义的所有变量都由上层Makefiles导出

Makefile

#! /usr/bin/make -f

################################################################################
# *AUTHOR*
# FULL NAME     "Alejandro Colomar Andrés"
################################################################################

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

DIRS    =                               \
        $(CURDIR)/tcp

OBJ     =                                                               \
        $(CURDIR)/tcp/client.o                                          \
        $(CURDIR)/tcp/server.o                                        \
        $(CURDIR)/foo.o

SRC     =                                                               \
        $(SRC_DIR)/base/socket/tcp/client.c                             \
        $(SRC_DIR)/base/socket/tcp/server.c                             \
        $(SRC_DIR)/base/socket/foo.c

DEP             = $(OBJ:.o=.d)
BOTH_OBJ        = $(subst .a.o,.a.o ,$(join $(OBJ:.o=.a.o),$(OBJ:.o=.so.o)))
BOTH_ASM        = $(subst .a.s,.a.s ,$(join $(OBJ:.o=.a.s),$(OBJ:.o=.so.s)))
NEEDDIR         = $(DEP) $(BOTH_ASM)

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

PHONY := all
all: $(BOTH_OBJ)
        @:

$(DIRS): $(CURDIR)/%:
    @echo   "   MKDIR   build/tmp/base/socket/$*"
    $(Q)mkdir -p        $@

$(NEEDDIR): | $(DIRS)

$(CURDIR)/%.d: $(SRC_DIR)/base/socket/%.c
        @echo   "       CC -M   build/tmp/base/socket/$*.d"
        $(Q)$(CC) $(CFLAGS_A) -MG -MT"$@"                               \
                        -MT"$(CURDIR)/$*.a.s" -MT"$(CURDIR)/$*.so.s"    \
                        -M $< -MF $@
$(CURDIR)/%.a.s: $(SRC_DIR)/base/socket/%.c $(CURDIR)/%.d
        @echo   "       CC      build/tmp/base/socket/$*.a.s"
        $(Q)$(CC) $(CFLAGS_A) -S $< -o $@
$(CURDIR)/%.so.s: $(SRC_DIR)/base/socket/%.c $(CURDIR)/%.d
        @echo   "       CC      build/tmp/base/socket/$*.so.s"
        $(Q)$(CC) $(CFLAGS_SO) -S $< -o $@
$(CURDIR)/%.o: $(CURDIR)/%.s
        @echo   "       AS      build/tmp/base/socket/$*.o"
        $(Q)$(AS) $< -o $@

include $(DEP)


PHONY += clean
clean:
        $(Q)rm -rf *.o *.s *.d
################################################################################
# Declare the contents of the PHONY variable as phony.
.PHONY: $(PHONY)


################################################################################
######## End of file ###########################################################
################################################################################

非常明显,你应该使用
mkdir-p
来确保你在并行构建过程中不会失败。非常明显,你应该使用
mkdir-p
来确保你在并行构建过程中不会失败。关于你的BTW问题:见最后一个扩展。那些是程序集文件。两者的区别在于
CFLAGS\u SO
具有
-fpic
,而
CFLAGS\u A
没有。因此,我将从.a.s文件中汇编.a.o对象文件,这些文件将被归档到.a库中。从.so.s文件中,我将汇编.so.o对象文件,这些文件将被编译成.so库。如果我传递整个对象列表,而不是仅传递以tcp开头的对象,它是否仍然有效(忽略那些与模式不匹配的对象,即不以tcp开头的对象)?:
$(OBJS):tcp/%.a:| tcp;#静态模式
@CacahueteFrito不合理地说,每个源文件名都必须与目标模式匹配<代码>文件.o:%.c:%.auto…不起作用。静态模式规则和模式规则有相同的问题:静态模式规则是一个exp