我有一个如下的目录结构:
- 生成文件
bin
main.c Makefile
lib
lib1.c lib2.c Makefile
tst
test1.cc Makefile
在我的Makfile中,我有如下代码:
ALL_OBJECTS = main.o lib1.o lib2.o
BINS = binary
binary,SRCS = main.o lib1.o lib2.o
OBJS = $($(*),SRCS)
all: $(ALL_OBJECTS) $(BINS)
%.o : %.c
${CC} -c $^ -o $@
binary:
${CC} -o $@ $(OBJS)
我的问题是,当我更改源文件(如main.c、lib1.c或lib2.c(时,*.o文件会在make期间重新编译,但二进制文件不会重新编译。当二进制文件的某个依赖项发生更改时,我如何确保重新编译它?
Makefile的某些部分对我来说意义不大,而且您显示的目录结构似乎与您显示的Makefile不太匹配。例如,对于一个名为lib
的目录,它包含自己的Makefile,我希望看到Makefile创建一个依赖于lib1.o和lib2.o的库。然后binary
将依赖于该库。
但现在,您似乎只是从一个Makefile构建binary
,而忽略了lib
目录中的Makefile。这也可以,但它将与以前的场景不同。
现在,让我们从一点";"更平坦";目录结构,main.c
、lib1.c
和lib2.c
都包含在一个目录中(Makefile位于同一目录中(。对于这种情况,我们可以用一个非常简单的Makefile构建二进制文件:
binary: lib1.o lib2.o main.o
$(CC) -o binary lib1.o lib2.o main.o
我们只是让二进制依赖于对象文件,以及如何从这些对象文件创建二进制。任何合理的现代make实用程序都已经有了关于如何编译.c文件以生成.o文件的内置规则,所以我们不必做更多的事情,除非我们希望在构建这些对象文件的方式上有一些不寻常的地方。
不过,这确实在两个地方重复了对象文件的名称。我们通常宁愿避免这种情况。我们可以将定义对象文件的名称从规则中分离出来,从中生成二进制文件,得到更像这样的东西:
OBJS = lib1.o lib2.o main.o
binary: $(OBJS)
$(CC) -o binary $(OBJS)
现在我们只在一个地方有对象文件的名称,所以如果(对于一个明显的例子(我们添加另一个对象文件,我们只需要在一个位置添加它的名称,而不是在两个位置。
根据你对@JerryCoffin的回答的最后一条评论,你可以做这样的事情:
binary1 : lib1.o lib2.o main1.o
binary2 : lib2.o main2.o
binary3 : lib1.o main3.o
binary1 binary2 binary3:
$(CC) -o $@ $^
前三行没有配方,因此只是向相关联的二进制文件添加先决条件。然后使用自动变量$^
为二进制目标定义一个配方,该变量将扩展到该目标的依赖项。