如何修改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.c
、bar.c
、atest.c
、anothertest.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。在此示例中,无需为程序 atest
和 anothertest
编写配方,因为它们是由 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以将更改的源编译到对象目录中,文件列表除外的主要内容,如果未能解决你的问题,请参考以下文章
不修改Linux内核文件,直接用makefile编译驱动,是否要先把内核编译一遍?