我正在写一个Makefile
,我想分开构建和源目录。我最初的想法只是“哦,我可以编写我的规则,将源路径添加到文件名之前并完成它。”
问题是这个解决方案会超重复,看起来不太好。写一个Makefile
的最佳方法是什么,它将目标存储在与保存我的源的目录不同的目录中。
答案 0 :(得分:1)
程序bsdmake非常支持将构建的目标存储在与持有源的目录不同的目录中。使用此功能的Makefile
可能会更难写,因此我将在回答中查看最重要的技巧。
内置变量.OBJDIR
包含构建目标的目录的名称。它是这样确定的(摘自man
页面):
.OBJDIR A path to the directory where the targets are built. Its
value is determined by trying to chdir(2) to the follow‐
ing directories in order and using the first match:
1. ${MAKEOBJDIRPREFIX}${.CURDIR}
(Only if ‘MAKEOBJDIRPREFIX’ is set in the environ‐
ment or on the command line.)
2. ${MAKEOBJDIR}
…
6. ${.CURDIR}
程序make
将chdir(2)
改为.OBJDIR
并将PWD
设置为该目录之前
执行任何目标。如果没有任何足够的准备.OBJDIR
是.CURDIR
,那么我们需要创建所需的目录 - 或树结构 - 然后再运行make
来构建我们的目标。
假设您选择依靠第一种机制来设置.OBJDIR
,然后您可以组织构建系统,以便在运行make
之前构建目标,
MAKEOBJDIRPREFIX
设置为合适的值。make
目标)准备${MAKEOBJDIRPREFIX}
下的必要目录。我们考虑一个简单的Makefile
,并描述上一个设置工作所需的安排。
program : a.o b.o c.o
cc a.o b.o c.o -o program
a.o b.o c.o : defs.h
a.o : a.c
cc -c a.c
b.o : b.c
cc -c b.c
c.o : c.c
cc -c c.c
manual.html: manual.css
manual.html: a.c b.c c.c defs.h
manualtool -c manual.css -o manual.html a.c b.c c.c defs.h
在构建a.o
之前,程序make
将chdir(2)
发送到${.OBJDIR}
并从该目录运行编译器cc
。由于源a.c
位于另一个目录中,编译器cc
将找不到它,编译将失败。通过使用make
定义的局部变量解决了此问题,因此前一个Makefile
转换为:
program : a.o b.o c.o
cc ${.ALLSRC} -o program
a.o b.o c.o : defs.h
a.o : a.c
cc -c ${.ALLSRC:M*.c}
b.o : b.c
cc -c ${.ALLSRC:M*.c}
c.o : c.c
cc -c ${.ALLSRC:M*.c}
manual.html: manual.css
manual.html: a.c b.c c.c defs.h
manualtool -c ${.ALLSRC:M*.css} -o manual.html ${.ALLSRC:N*.css}
请注意最后一个配方中如何使用globbing模式在命令行的各个位置正确选择各个源。
freebsd的构建系统 - 可能netbsd和openbsd - 使用此功能可以同时构建各种体系结构的操作系统。 (这也使清洁更容易!)您可以研究这些Makefile以更好地理解所涉及的技术。
我bsdowl的便携式宏bdsmake也支持bsdmake
的此功能,您可以查看文件bps.objdir.mk
和ocaml示例。