2

我已经搜索并尝试了一些示例来使用非递归 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)中进行“制作”以验证库。它们将分别生成 libabc.a 和 libxyz.a。
  2. 我写了一些简单的 Makefile 但我的规则不起作用,我试图理解 GNU make 手册但我迷路了。

lib1/生成文件:

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 $@ $<

应用程序/生成文件:

ALL_APP = first second
% : %.c libabc.a libxyz.a
     $(CC) $(CLFAGS) $^ -o $@
include ../lib1/Makefile
include ../lib2/Makefile

现在,我很难在每个 Makefile 中定义相同的目标(显然)。就像我无法在 lib1/Makefile 和 app/Makefile 中定义一个干净,因为 lib1 包含在那里。虽然我希望我可以单独在 lib1 中进行清理,但这是有道理的。

现在,当我在“app”中制作时,没有制作 obj/foo.o 的规则。我猜是因为路径都是假的。“obj/”指的是 lib1/obj/,但随着 Makefile 被包含在内,这一切都丢失了。

我做错了什么,我可以像上面那样使用非常简单的 Makefile 来构建我的项目。大多数在线示例都相当复杂,因为它们试图实现更多(我相信)。

在此先感谢(对于已经讨论过多次的话题,我们深表歉意)。如果可以避免的话,我宁愿现在不学习 automake 和 cmake。我希望我的项目足够简单,不需要使用这些强大的工具。

此致,

4

1 回答 1

3

让我们从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 $@ $<

当从内部调用时,此 makefile 仍将像以前一样工作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.mak例如,以这种方式硬编码路径是不好的lib2/lib2.mak,并且可以修复。但这一天就够了。

于 2014-10-28T22:54:20.237 回答