如何在makefile中正确使用%或*(星号)符号作为占位符?

Tim*_*nov 4 c makefile

我在创建“上下文无关/文件名不可知”makefile 来构建 C 项目时遇到问题,但每次添加新文件时都没有指定显式文件名。我有以下项目结构:

include/ #dir to store all header files
    lib1.h
    lib2.h
    ...
src/ # dir of source code
    obj/ #temporary dir for storing all .o files
        lib1.o
        lib2.o
        ...
    lib1.c # start with #include "lib1.h"
    lib2.c # the same
    ...
    main.c
Run Code Online (Sandbox Code Playgroud)

以及以下生成文件:

# dirs
IDIR=include
SDIR=src
ODIR=src/obj

_HEADS=*.h  #or maybe % percentage instead?
HEADS=$(patsubst %, $(IDIR)/%, $(_HEADS))
_OBJS=*.o
OBJS=$(patsubst %, $(ODIR)/%, $(_OBJS))
_CFILES=*.c
CFILES=$(patsubst %, $(SDIR)/%, $(_CFILES))

# compiler
GCC=gcc
CFLAGS=-I$(IDIR)

$(OBJS): $(CFILES) $(HEADS)
    $(GCC) -c -o $@ $< $(CFLAGS)

main: $(OBJS)
    $(GCC) -o $@ $^ $(CFLAGS)
Run Code Online (Sandbox Code Playgroud)

如果在src/include/文件夹下的 *.c 或 *.h 文件中发生任何更改,我想要实现的是构建可执行文件(不确定更改可能在 下src/obj)。所以现在make不要编译,因为它认为目标文件是“最新的”。所以我可能做错了什么,因为我需要先检查 .c 和 .h 文件。

另外我不确定(即使在阅读了几个教程之后)如何正确使用 % 以及使用 % 和 * 星号之间的区别。例如,我看到了这样的事情:

%.o: %.c %.h
    gcc -o foo %@ ...
Run Code Online (Sandbox Code Playgroud)

世界上的规则%.o是如何写成规则名称的(我想如果它们都是简单的名称而不是一些合乎逻辑的东西会更好)?或者,当您%@在实际规则中使用占位符以避免额外命名“开销”时才有意义。拜托,任何人都可以解释并帮助我修复我的makefile - 我真的把这些微妙的事情搞砸了......

Hay*_*ayt 6

* 是一个通配符,它​​为您提供一个列表,并且与“shell”相关。

% 是一个 makefile 内部通配符,它​​将以 for-each 的方式充当占位符(我将在下面解释)。

虽然为*.c您提供一个变量中所有 c 文件的列表,但您可以使用它做更多事情%

%.o: %.c %.h
    gcc -o foo %@
Run Code Online (Sandbox Code Playgroud)

例如,这被称为模式规则,意味着每个规则<placeholder>.c<placeholder>.h生成<placeholder>.o具有其下方相应配方的目标。

使用模式规则 make 会生成这样的东西

a.o : a.c a.h
    ...
b.o : b.c b.h
    ...
c.o : c.c c.h
    ...
Run Code Online (Sandbox Code Playgroud)

您目前正在尝试做的事情会导致 int

a.o b.o c.o : a.c b.c c.c a.h b.h c.h 
    gcc ....
Run Code Online (Sandbox Code Playgroud)

虽然这可能是有效的,但您有不必要的依赖项。a.o不需要依赖于b.c例如

_CFILES = *.c将导致“*.c”成为变量中的字符串而不是实际文件。如果你想扩展实际的文件名,你应该使用通配符函数

_CFILES  := $(wildcard *.c)
Run Code Online (Sandbox Code Playgroud)

现在

CFILES=$(patsubst %, $(SDIR)/%, $(_CFILES))
Run Code Online (Sandbox Code Playgroud)

也有像占位符这样的“for-each” %

这意味着每次有%它都会被$(SDIR)/%. 因为%patsubst 中您没有匹配的模式,所以这会变得很奇怪。你想在这里实现什么?如果你想src从路径中“切断” ,那将是相反的

CFILES=$(patsubst $(SRC)%, % , $(_CFILES))
Run Code Online (Sandbox Code Playgroud)

但我怀疑你想这样做。您应该阅读 makefile 文档中的一些内容,该文档在此处链接了很多次。我解释了很多。