关于 GNU makefile 的一些问题
我想知道是否有人有时间回答一些有关 GNU makefiles 的问题...
- 如果目录不存在(“./obj”)用于输出,如何创建该目录?
- 我有一个 makefile,但我有 2 个构建方法“调试”和“发布”,我可以在 1 个 makefile 中同时拥有这两个方法吗?如何告诉它要构建哪一个?
- 我一直在使用 Code::Blocks ,它只构建更改的文件,但我的 makefile 会在每次调用 make 命令时构建它们,而不触及任何文件。我怎样才能让它只构建更改的文件?
这是我当前的 makefile,
OBJPATH=./obj
COMPILER=gcc
Output: main.o Base64.o
$(COMPILER) -o Output.exe $(OBJPATH)/main.o $(OBJPATH)/Base64.o
strip Output.exe
main.o: main.c main.h
$(COMPILER) -c main.c -o $(OBJPATH)/main.o
Base64.o: Base64.c Base64.h
$(COMPILER) -c Base64.c -o $(OBJPATH)/Base64.o
谢谢。
i was wondering if anyone have sometime to answer some questions about GNU makefiles...
- how to create a directory if it doesn't exists ("./obj") for output?
- i have one makefile, but i got 2 build methods "Debug" and "Release", can i have both in 1 makefile and how to tell it which one to build?
- ive been using Code::Blocks which builds only changed files, but my makefile builds them everytime i call make command, without touching any files. how can i make it build changed files only?
here is my current makefile
OBJPATH=./obj
COMPILER=gcc
Output: main.o Base64.o
$(COMPILER) -o Output.exe $(OBJPATH)/main.o $(OBJPATH)/Base64.o
strip Output.exe
main.o: main.c main.h
$(COMPILER) -c main.c -o $(OBJPATH)/main.o
Base64.o: Base64.c Base64.h
$(COMPILER) -c Base64.c -o $(OBJPATH)/Base64.o
thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
对于第一个问题,您可以在其他任何目标之前放置一个假目标,大致如下:
这将在构建其他任何内容之前自动执行序言中的所有内容(您必须使其成为每个规则中的第一个依赖项)。例如,如果目录已存在,则
mkdir
开头的-
会忽略失败。对于第二个问题,您可以提供类似以下内容:
并将调试和发布代码实际放置在单独的子目录中。这样,您可以使用
make release
或make debug
进行构建,并使用make all
构建它们。第三个问题:你的 makefile 每次都会构建,因为规则告诉它这样做。例如,
Output: main.o Base64.o
将始终尝试构建,因为Output
永远不存在(正确的目标似乎是Output.exe)。
类似地,您的目标文件规则将始终执行,因为
main.o
和Base64.o
都不会被它们的语句更新(它们更新obj
中的文件) > 目录代替)。您也许可以通过创建目标
$(OBJPATH)/main.o
来解决这种情况,但说实话,我通常不担心将对象和可执行文件分离到单独的目录中。我倾向于将它们全部集中到一个目录中,然后让make -clean
清理它们。所以我开始的 makefile 是:
回应你的评论问题:
GNU Make 可能比我习惯的更强大,但是您可以通过设置环境变量然后按照以下方式重新运行 make 来做到这一点:
输出:
您可以看到标有
< 的两个单独的变量;== 上面。
正如我所说,使用 GNU Make 可能有一种更简单的方法,但这将帮助您入门。
For the first question, you can put a fake target before any of the others, along the lines of:
That will automatically execute everything in the preamble (you have to make it the first dependency in every rule) before it builds anything else. The
-
at the start of themkdir
ignores failures if, for example, the directory already exists.For the second question, you can provide something like:
and actually put the debug and release code in separate subdirectories. That way, you can build either with
make release
ormake debug
and build them both withmake all
.Third question: Your makefile builds every time because the rules tell it to. For example,
Output: main.o Base64.o
will always try to build sinceOutput
never exists (the correct target seems to beOutput.exe
).Similarly your object file rules will always execute since neither
main.o
norBase64.o
are updated by their statements (they update the files in theobj
directory instead).You may be able to fix that case by making the target
$(OBJPATH)/main.o
but, to be honest, I don't usually worry about separating objects and executables into separate directories. I tend to just lump them all into one directory and letmake -clean
clean them up.So the makefile I would start with would be:
In response to your comment question:
GNU Make may be more powerful than the ones I'm used to but you can do that by setting an environment variable then re-running make as per the following:
which outputs:
You can see the two separate variables marked with
<==
above.As I said, there's probably an easier way to do it with GNU Make but that'll get you started.
您可以有多个顶级构建目标。 makefile 中的
Output
是顶级目标。做两个。一个称为“调试”,另一个称为“发布”。然后,您可以为调试版本说make Debug
,为发布版本说make Release
。我没有使用过
Code::Blocks
(我不知道它是什么),但是如果你的Makefiles编写正确(即正确指定了依赖项),它只会重建所需的目标。You can have multiple top level build targets.
Output
in your makefile is a top level target. Make two. One called "Debug" and the other "Release". You can then saymake Debug
for the debug build andmake Release
for the release build.I haven't used
Code::Blocks
(I don't know what it is) but if your Makefiles are written properly (i.e. with dependencies properly specified), it will only rebuild the required targets.回复您的评论问题:
以下是不使用递归的方法:
In response to your comment question:
Here is how you do it without recursion: