如何修改makefile以将更改的源编译到对象目录中,文件列表除外

Posted

技术标签:

【中文标题】如何修改makefile以将更改的源编译到对象目录中,文件列表除外【英文标题】:How to modify makefile to compile changed source into object directory except for a list of files 【发布时间】:2017-09-12 15:48:31 【问题描述】:

我继承了一个使用 GNU Make 3.81 的 makefile。恕我直言,它过于复杂,因为它不使用模式。此外,它不会在需要时自动创建目标文件目录。我查看了几个示例并阅读了 GNU makefile 手册,但仍然没有看到应该简单的东西。似乎有很多方法推荐,但不清楚使用什么。我有大约 60 个 c 文件需要编译到名为 obj 的目录中。但是,我不想要 6 个将“主”程序编译到该目录中的测试程序。它们位于名为 OTHERSRCS 的列表中。如果这些文件中有任何更改,我希望将 c 文件减去 OTHERSRCS 编译到 obj 中。另外,如果 obj 目录不存在,我想创建它。 'make clean' 应该删除那个目录。我已经将 ANT 与 Java 一起使用,并且可以使依赖项工作,但我没有成功使用这个 makefile。一个简单的例子会很有帮助,它使用某种排除以及 c 文件的模式。

【问题讨论】:

特定规则优先于一般规则,因此请尝试通过简单地为例外提供特定规则来获得“排除”。 如果您仍然卡住,请考虑建立一个模型示例。如果他们不必为您提供一个示例(甚至可能不是您的意思),他们更有可能回答。 【参考方案1】:

在这个简单的例子中,当前目录下的 C 源文件 是foo.cbar.catest.canothertest.c。我们有:

OTHERSRCS := atest.c anothertest.c

$(OTHERSRCS) 中的每一个都将被单独编译并链接到 当前目录中的一个程序。所有剩余的 C 源文件,无论如何 这些是,将被编译到一个目录obj,应该是 在需要时创建,并将生成的目标文件全部链接到 一个程序foobar

生成文件

ALLSRCS := $(wildcard *.c)
OTHERSRCS := atest.c anothertest.c
foobar_SRCS := $(filter-out $(OTHERSRCS),$(ALLSRCS))
foobar_OBJS := $(addprefix obj/,$(foobar_SRCS:.c=.o))
PROGS := foobar atest anothertest

.PHONY: all clean

all : $(PROGS)

obj/%.o: %.c | obj 
    $(COMPILE.c) $< -o $@

obj:
    mkdir -p $@


foobar: $(foobar_OBJS)
    $(LINK.o) -o $@ $^ $(LDLIBS)

clean:
    rm -fr $(PROGS) obj

默认的make 运行如下:

$ make
mkdir -p obj
cc    -c foobar.c -o obj/foobar.o
cc    -c foo.c -o obj/foo.o
cc    -c bar.c -o obj/bar.o
cc   -o foobar obj/foobar.o obj/foo.o obj/bar.o 
cc     atest.c   -o atest
cc     anothertest.c   -o anothertest

当然还有 make foobar 就像前 5 行一样。

要了解关键细节,请参阅4.3 Types of Prerequisites 和8.2 Functions for String Substitution and Analysis 在the manual。在此示例中,无需为程序 atestanothertest 编写配方,因为它们是由 GNU make 的默认规则正确构建的。

如果您要重做继承的 makefile,请考虑合理化源代码树,例如至少不要将测试源与应用程序源放在同一目录中。

【讨论】:

这看起来很不错,但我明白了: woo$ make Makefile:52: *** target file `all' 同时具有 : 和 :: 条目。停止。 我刚刚安装了 GNU make 4.1,因为我读到这可能会修复所有关于目标的错误。当我运行 /usr/local/bin/make -v 时,我得到 GNU make 4.1,但是当我在源目录中运行 /usr/local/bin/make 时,我得到关于目标“所有”的相同错误。 @JohnWooten 嗨。需要查看确切的 makefile 来调试它,或者至少是一个重现它的最小示例。听起来像是抄录单。无论如何都在这里睡觉。【参考方案2】:

这里是my Makefile

这应该会让你继续前进。我尽量做到描述性强。

编辑: 要排除 .c 文件,您可以更改:

SRC     =   $(shell find $(SRC_DIR) -name '*.c')

SRC     =   $(shell find $(SRC_DIR) -name '*.c' ! -iname 'myFile.c')

【讨论】:

如何更改 myFile.c 以使用 OTHERSRCS 中的列表? 我不确定该列表,但您可以将所有这些 OTHERSRCS 文件放在单独的目录中,并使用 ! -path "./yourPath" 而不是 ! -iname。更多信息,你可以google:shell find exclude a list of files,或者类似的东西

以上是关于如何修改makefile以将更改的源编译到对象目录中,文件列表除外的主要内容,如果未能解决你的问题,请参考以下文章

如何制作 Makefile 以将命令及其输出记录到文件中?

Makefile 只重新编译更改的对象?

不修改Linux内核文件,直接用makefile编译驱动,是否要先把内核编译一遍?

Makefile不会在头文件更改时重新编译

编译时如何更改 makefile 诊断消息 [GNU ARM GCC, Eclipse make.exe]

Linux内核移植入门