我搜索并尝试了几个例子,以使用非递归makefile完成一个简单的项目。过去,我使用简单的单目录代码库,但现在我正在为多个工程师构建一个环境:-)
+--app
| +-- obj/
| +-- Makefile
| +-- first.c
| +-- second.c
|
+--lib1
| +-- obj/
| +-- Makefile
| +-- foo.c
| +-- bar.c
|
+--lib2
| +-- obj/
| +-- Makefile
| +-- sample.c
没什么特别的——只有两个目录(也许稍后会有第三个),其中包含库代码和多个应用程序,所有这些都在"app"目录中。为了保持干净,我想把.o和.d文件放在一个单独的obj/目录中。
- 我希望能够在像lib1和lib2这样的每个子目录中做一个"make"来验证库。它们将分别生成libabc.a和libxyz.a
- 我写了一些简单的Makefile,但我的规则不起作用,我试图理解GNU制作手册,但我迷路了
lib1/Makefile:
lib_src = foo.c bar.c
lib_obj = $(patsubst %.c,obj/%.o,$(lib_src))
libabc.a: $(lib_obj)
@echo [Archive... $(@F)]
@$(AR) -cr libabc.a $^
obj/%.c : %.c
$(CC) $(CFLAGS) -c -o $@ $<
app/Makefile:
ALL_APP = first second
% : %.c libabc.a libxyz.a
$(CC) $(CLFAGS) $^ -o $@
include ../lib1/Makefile
include ../lib2/Makefile
现在,我很难在每个Makefile中定义相同的目标(显然)。就像我无法在lib1/Makefile和app/Makefile中定义clean一样,因为lib1包含在其中。虽然我希望我能单独在lib1中进行清理,但这是有道理的。
现在,当我在"app"中制作时,没有规则来制作obj/foo.o。我想是因为路径都是假的。"obj/"指的是lib1/obj/,但随着Makefile的加入,这一切都丢失了。
我做错了什么?我可以像上面那样使用非常简单的Makefile来构建我的项目吗。网上的大多数例子都相当复杂,因为它们试图实现更多(我相信)。
提前感谢(对于已经讨论过多次的话题表示抱歉)。如果可以避免的话,我宁愿现在不学习automake和cmake。我希望我的项目足够简单,不需要使用这些强大的工具。
致问候,
让我们从lib1/Makefile
:开始
lib_src = foo.c bar.c
lib_obj = $(patsubst %.c,obj/%.o,$(lib_src))
libabc.a: $(lib_obj)
@echo [Archive... $(@F)]
@$(AR) -cr libabc.a $^
obj/%.c : %.c
$(CC) $(CFLAGS) -c -o $@ $<
我们引入了变量HERE
,并进行了一些小的更改:
HERE := ../lib1
lib_src := foo.c bar.c
lib_obj := $(patsubst %.c,$(HERE)/obj/%.o,$(lib_src))
$(HERE)/libabc.a: $(lib_obj)
@echo [Archive... $(@F)]
@$(AR) -cr $@ $^
$(HERE)/obj/%.c : $(HERE)/%.c
$(CC) $(CFLAGS) -c -o $@ $<
当从lib1/
中调用时,该生成文件仍将像以前一样工作。但一旦我们对lib2/Makefile
进行了相应的更改,我们就可以更改app/Makefile
:
ALL_APP = first second
% : %.c ../lib1/libabc.a ../lib2/libxyz.a
$(CC) $(CLFAGS) $^ -o $@
include ../lib1/Makefile
include ../lib2/Makefile
现在是clean
规则我们重命名lib1/Makefile
=>lib1/lib1.mak
和lib2/Makefile
=>lib2/lib2.mak
,编写一个新的lib1/Makefile
:
include lib1.mak
clean:
@rm -f lib*.a obj/*
在lib2/
中执行相同操作,并修改app/Makefile
:
...
include ../lib1/lib1.mak
include ../lib1/lib1.mak
clean:
@rm -f $(ALL_APP)
@$(MAKE) -C ../lib1 clean
@$(MAKE) -C ../lib2 clean
(我们可以在没有递归的情况下完成,但它会更复杂,以这种方式使用递归Make确实没有错。)
一些进一步的改进是可能的。例如,以这种方式将路径硬编码为lib1/lib1.mak
和lib2/lib2.mak
是不好的,这是可以修复的。但这已经足够一天了。