我是Makefiles的新手,我试图在我的makefile中包含一个调试器选项,当我输入" make debug时打开调试器。"但是,该命令会返回错误。我已经在我的虚拟机中安装了ddd调试器。这是我下面的makefile。有帮助吗?
main: main.cpp puzzle.cpp fuse.cpp
g++ --std=c++11 -o main main.cpp
./main
clean:
-rm -f *.o main
debug:
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp ddd debug
答案 0 :(得分:2)
ddd debug
需要单独作为一个单独的命令执行,你需要添加缺少的-o
开关:
debug:
g++ --std=c++11 -g -o debug main.cpp puzzle.cpp fuse.cpp
ddd debug
但是,如果debug
已存在,则不会执行此操作; make
尝试优化,如果目标已经存在,或者比列出的依赖项(没有)更新,它将不会运行配方。
相反,将此规则分为两部分。二进制文件(列出了依赖项)和run命令(应该标记为虚假目标)。假冒目标将确保配方仍然运行,即使存在与配方的输出名称相同的文件(在此示例中为run-debug
)。
debug: main.cpp puzzle.cpp fuse.cpp
g++ --std=c++11 -g -o debug main.cpp puzzle.cpp fuse.cpp
run-debug: debug
ddd debug
.PHONY: run-debug
这样,make run-debug
将始终调用调试器(如果编译成功),但如果debug
二进制文件比源文件新,则不会执行编译。
我不熟悉ddd
,但有些调试器会以类似于shell的方式查找二进制文件,因此您可能需要将ddd
行修改为:
ddd ./debug
请勿忘记将clean
规则修补为(1)删除debug
和(2)虚假:
clean:
-rm -f *.o main debug
.PHONY: clean run-debug
答案 1 :(得分:2)
<强> TL; DR 强>
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp ddd debug
此行有误。它告诉G ++使用选项--std=c++11 -g
编译给出的文件列表 - 包括“ddd”和“debug”(两次) - 到a.out
(或a.exe
如果你“关于Windows / Cygwin。”
这不是你想要的,因为“debug”和“ddd”不太可能是有效的C ++源文件,编译器运行失败。
如果您输入make debug
,则make
将执行debug
规则:
debug:
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp ddd debug
如果没有名为debug
的文件(*),make
将尝试使用以下命令重新创建它:
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp ddd debug
我不太清楚你期望该命令要做什么。我猜你打算按顺序执行两个命令:
debug:
g++ --std=c++11 -g debug main.cpp puzzle.cpp fuse.cpp
ddd debug
但是,编译器行出错了。我猜你想要这样的东西(注意-o
):
g++ --std=c++11 -g -o debug main.cpp puzzle.cpp fuse.cpp
main: main.cpp puzzle.cpp fuse.cpp
g++ --std=c++11 -o main main.cpp
./main
这有几个方面。
当任何文件make
,main
或main.cpp
为<{1>}时,此规则会指示puzzle.cpp
从头开始重建fuse.cpp
感动。但是,命令只提供重新编译main.cpp
- 其他两个文件永远不会(重新)编译。
好的 Makefile规则只执行(重新)构建它所命名的文件所需的内容,并且尽可能通用。
例如,要“告诉”制作如何从任何给定的*.o
文件创建*.cpp
文件($@
和@<
作为“规则目标”的占位符和“第一依赖”,分别):
%.o: %.cpp
g++ --std=c++11 -o $@ @<
完成后,您可以告诉如何从单个对象文件构建可执行文件($^
是“所有依赖项”的占位符):
main: main.o puzzle.o fuse.o
g++ --std=c++11 -o $@ $^
这样,如果您触摸其中一个源文件(例如puzzle.cpp
),则仅重建一个目标文件,并重新链接main
可执行文件。对于大型项目,此显着减少(重新)编译时间。
(*)如果你有不实际创建文件的规则,你应该将它们标记为.PHONY
,所以make
将执行它们即使该名称的文件恰好已经存在。
您通常也希望禁用调试优化,以避免优化时可能发生的一些陌生事情。
所以(为了更简单的例子,总是使用 -g
调试信息来编译):
.PHONY: debug
%.o: %.cpp
g++ --std=c++11 -g -O0 -o $@ @<
main: main.o puzzle.o fuse.o
g++ --std=c++11 -g -O0 -o $@ @^
debug: main
ddd main
您的Makefile 还没有考虑的是,当任何头文件时,需要重新编译目标文件 包括被触动。这种依赖性处理很容易用GCC,但超出了这个答案的范围。让我指出Makefile tutorial at OSDev.org(主要由我编写),逐步介绍如何让Makefile“正确”。