我在创建“上下文无关/文件名不可知”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 - 我真的把这些微妙的事情搞砸了......
* 是一个通配符,它为您提供一个列表,并且与“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 文档中的一些内容,该文档在此处链接了很多次。我解释了很多。