c-简单的非递归Makefile,对象文件在单独的目录中



我搜索并尝试了几个例子,以使用非递归makefile完成一个简单的项目。过去,我使用简单的单目录代码库,但现在我正在为多个工程师构建一个环境:-)

+--app
|  +-- obj/
|  +-- Makefile
|  +-- first.c
|  +-- second.c
|
+--lib1
|  +-- obj/
|  +-- Makefile
|  +-- foo.c
|  +-- bar.c
|
+--lib2
|  +-- obj/
|  +-- Makefile
|  +-- sample.c

没什么特别的——只有两个目录(也许稍后会有第三个),其中包含库代码和多个应用程序,所有这些都在"app"目录中。为了保持干净,我想把.o和.d文件放在一个单独的obj/目录中。

  1. 我希望能够在像lib1和lib2这样的每个子目录中做一个"make"来验证库。它们将分别生成libabc.a和libxyz.a
  2. 我写了一些简单的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.maklib2/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.maklib2/lib2.mak是不好的,这是可以修复的。但这已经足够一天了。

相关内容

  • 没有找到相关文章

最新更新