包含ddd调试器选项的C ++ Makefile

时间:2017-09-12 21:08:08

标签: c++ debugging makefile

我是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

2 个答案:

答案 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

这有几个方面。

任何文件makemainmain.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“正确”。