如何使用目标和源的不同目录编写Makefile [英] How to write a Makefile using different directories for targets and sources

查看:137
本文介绍了如何使用目标和源的不同目录编写Makefile的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个Makefile,我想将构建目录和源目录分开.我最初的想法只是哦,我可以写规则到文件名的源路径之前,然后完成它."

I am writing up a Makefile and I would like to separate the build and source directories. My initial thought was just "Oh, I can write my rules prepending the source path to the filename and be done with it."

问题是此解决方案将是超级重复的,而且看起来不太好.为自己编写Makefile并将目标存储在与保存我的源代码的目录不同的目录中的最佳方法是什么.

The problem is that this solution would be super repetitive and doesn't look very nice. What would be the best approach for writing myself a Makefile that stores targets in a directory distinct from the directory holding my sources.

推荐答案

程序很好地支持将构建的目标存储在与保存源的目录不同的目录中.使用此功能的Makefile可能很难编写,因此我将在答案中回顾最重要的技术.

The program bsdmake has a very good support for storing the built targets in a directory distinct form the one holding the sources. A Makefile using this functionality might be a bit harder to write, so I will review the most important techniques in my answer.

内置变量.OBJDIR包含用于构建目标的目录的名称.确定如下(摘录自man页):

The built-in variable .OBJDIR contains the name of a directory where targets are built. It is determined like this (excerpt from the man page):

 .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}

程序makechdir(2)转换为.OBJDIR并将PWD设置为该目录之前 执行任何目标.在没有任何充分准备的情况下,.OBJDIR.CURDIR,因此我们需要在运行make生成目标之前创建所需的目录或树结构.

The program make will chdir(2)to .OBJDIR and set PWD to that directory before executing any targets. In the absence of any adequate preparation .OBJDIR is .CURDIR, therefore we need to create the desired directory — or tree structure ­— before running make to build our targets.

假设,您选择依靠第一种机制来设置.OBJDIR,然后可以组织构建系统,以便在运行make来构建目标之前,

Assume, you choose to rely on the first mechanism to set .OBJDIR, you can then organise your build system so that, before running make to build your targets,

  • 环境变量MAKEOBJDIRPREFIX设置为合适的值.
  • 特殊脚本(可能是make目标)准备${MAKEOBJDIRPREFIX}下的一个或多个必要目录.
  • The environment variable MAKEOBJDIRPREFIX is set to suitable value.
  • A special script (it might be a make target) prepares the necessary directory or directories under ${MAKEOBJDIRPREFIX}.

我们考虑一个简单的Makefile,并描述了使先前的设置生效所需的安排.

We consider a simple Makefile and describe arrangements necessary for the previous setup to work.

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之前,程序makechdir(2)${.OBJDIR},并从该目录运行编译器cc.由于源a.c位于另一个目录中,因此编译器cc将找不到它,并且编译将失败.通过使用make定义的局部变量可以解决此问题,因此先前的Makefile会转换为:

Before building a.o the program make will chdir(2) to ${.OBJDIR} and run the compiler cc from that directory. Since the source a.c is located in another directory, the compiler cc will not find it and the compilation will fail. This issue is solved by using the local variables defined by make, the previous Makefile therefore translates to:

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模式在命令行的各个位置适当地选择源代码片段.

Note how globbing patterns are used in the last recipe to appropriately select pieces of the sources at the various locations of the command line.

用于的构建系统-甚至可能-使用此功能可以同时为各种架构构建操作系统. (这也使清理更容易!)您可以研究这些Makefile,以更好地了解所涉及的技术.

The build system for freebsd — and possibly netbsd and openbsd — use this functionality to be able to build simultaneously the operating system for various architectures. (It also make cleaning easier!) You could study these Makefiles to gain a better understanding of the techniques involved.

我的可移植宏 bsdowl 用于

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆