简单的非递归Makefile与目标文件在单独的目录中
我已经搜索并尝试了几个使用非递归makefile来完成简单项目的示例。在过去,我用了简单的单一代码库的目录,但现在我放在一起的环境多名工程师:-)简单的非递归Makefile与目标文件在单独的目录中
+--app
| +-- obj/
| +-- Makefile
| +-- first.c
| +-- second.c
|
+--lib1
| +-- obj/
| +-- Makefile
| +-- foo.c
| +-- bar.c
|
+--lib2
| +-- obj/
| +-- Makefile
| +-- sample.c
没什么fancy-只是两个目录(也许第三个版本)和库代码和多个应用程序都在“应用程序”目录中。我想将.o和.d文件保存在一个单独的obj /目录中以保持清洁。
- 我希望能够在每个子目录(如lib1和lib2)中执行“make”来验证库。他们将分别生成libabc.a和libxyz.a。
- 我写了一些简单的Makefile,但我的规则不起作用,我试图理解GNU make手册,但是迷路了。
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 [email protected] $<
应用程序/ Makefile文件:
ALL_APP = first second
% : %.c libabc.a libxyz.a
$(CC) $(CLFAGS) $^ -o [email protected]
include ../lib1/Makefile
include ../lib2/Makefile
现在,我已经定义在每个Makefile文件(显然)对同一目标的麻烦。就像我无法在lib1/Makefile和app/Makefile中定义一个clean,因为lib1包含在那里。虽然我希望我可以在lib1中单独做一个清理,但这是有道理的。
现在,当我在“应用程序”中进行制作时,没有制定obj/foo.o的规则。我猜是因为路径都是假的。 “obj /”指的是lib1/obj /,但是随着Makefile的包含,这些都丢失了。
我在做什么错了,我可以用我真正简单的Makefiles构建项目吗?网上的大多数例子都相当复杂,因为他们试图获得更多(我相信)。
在此先感谢(对于已经讨论过很多次的话题感到抱歉)。如果我能避免它,我现在宁愿不学习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 [email protected] $<
我们引入变量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 [email protected] $^
$(HERE)/obj/%.c : $(HERE)/%.c
$(CC) $(CFLAGS) -c -o [email protected] $<
这个Makefile仍然会工作得如之前从lib1/
内调用。为clean
规则
ALL_APP = first second
% : %.c ../lib1/libabc.a ../lib2/libxyz.a
$(CC) $(CLFAGS) $^ -o [email protected]
include ../lib1/Makefile
include ../lib2/Makefile
现在:但是,一旦我们做出相应的改动lib2/Makefile
,我们可以改变app/Makefile
。我们重命名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
并不好,这可以修复。但这足够一天。
我不认为在您的应用程序makefile中包含库makefiles是这里的正确解决方案。这就是我要做的:为每个目录编写一个完全正常运行的独立makefile。然后为您的应用程序编写一个简单的构建脚本,为每个库调用make,最后再调用make for your app。您也可以让构建脚本将构建的库复制到您的应用程序目录中。 – 2014-10-21 22:54:57
@BrandonYates这是或多或少的递归,但更多的删除了一步,因为你甚至不让make做递归构建。 – 2014-10-21 23:30:30
谢谢布兰登。我认为调用make并不是一个好主意,并且包含Makefile是一种更好的方法。彼得米勒写了一篇文章解释为什么。通过独立调用每个Makefile,依赖性更难管理。 – guraaf 2014-10-21 23:32:01