makefile make了之后怎么调试程序

makefile make了之后怎么调试程序,第1张

运行man make或者make -h或者make --help查看make的帮助信息,它的选项有助于调试的有几个。

例如-d,显示有用的信亩盯神息:

-d Print lots of debugging information.

例如-w,显示当前的目录:

-w Print the current directory.

例如,-n的作用是,不迅亏真的去执行命令,而是将要执行的命令都打印(显示)出来:

-n,

Don't actually run any commandsjust print them.

另外,自己可以在 makefile里面加入显示命令,或者加入$(warning XXX),加入则侍$(error XXX), 加入$(info XXX)等等,这都能起到调试作用。

makefile 的调试有点像魔法。可惜,并不存在makefile 调试器之类的东西可用来查看特定规则是如何被求值的,或某个变量是如何被扩展的。相反,大部分的调试过程只是在执

行输出的动作以及查看makefile。事实段察上,GNU make 提供了若干可以协助调试的内置函数以及命令行选项。

用来调试makefile 的一个最好方法就是加入调试挂钩以及使用具保护的编程技术,让你能够在事情出错时恢复原状。我将会介绍若干基本的调试技术以及我所发现的最有用的具保

护能力的编码习惯。

1.make 的调试功能

warning函数非常适合用来调试难以捉摸的makefile。因为warning函数会被扩展成空字符串,所以它可以放在makefile 中的任何地方:开始的位置、工作目标或必要条件列表中以

及命令脚本中。这让你能够在最方便查看变量的地方输出变量的值。例如:

$(warning A top-level warning)

FOO := $(warning Right-hand side of a simple variable)bar

BAZ = $(warning Right-hand side of a recursive variable)boo

$(warning A target)target: $(warning In a prerequisite list)makefile

$(BAZ)

$(warning In a command script)

ls

$(BAZ):

这会产生如下的输出:

$ make

makefile:1: A top-level warning

makefile:2: Right-hand side of a simple variable

makefile:5: A target

makefile:5: In a prerequisite list

makefile:5: Right-hand side of a recursive variable

makefile:8: Right-hand side of a recursive variable

makefile:6: In a command script

ls

makefile

请注意,warning函数的求值方式是按照make标准的立即和延后求值算法。虽然对BAZ的赋值动作中包含了一个warning函数,但是直到BAZ在必要条件列表中被求值后,这个信孝判息才

会被输出来。

“可以在任何地方安插warning调用”的这个特性,让它能够成为一个基本的调试工具。

2.命令行选项

我找到了三个最适合用来调试的命令行选项:

--just-print(-n)

--print-database(-p)

--warn-undefined-variables。

2.1 --just-print

在一个新的makefile 工作目标上,我所做的第一个测试就是以--just-print(-n)选项来调用make。这会使得make读进makefile并且输出它更新工作目标时将会执行的命令,但是

不会真的执行它们。GNU make 有一个方便的功能,就是允许你为将被输出的命令标上安静模式修饰符(@)。

这个选项被假设可以抑制所有命令的执行动作,然而这只在特定的状况下为真。实际上,你必须小心以对。尽管make不会运行命令脚本,但是在立即的语境之中,它会对shell函数

调用进行求值动作。例如:

REQUIRED_DIRS = ...

_MKDIRS := $(shell for d in $(REQUIRED_DIRS)\

do \

[[ -d $$d ]] || mkdir -p $$d\

done)

$(objects) : $(sources)

正如我们之前所见,_MKDIRS 简单变量的目的是触发必要目录的创建动作。如果这个makefile 是以--just-print 选项的方式运行的,那么当make 读进makefile 时,巧燃改shell命令将

会一如往常般被执行。然后,make 将会输出(但不会执行)更新$(objects)文件列表所需要进行的每个编译命令。

2.2 --print-data-base

--print-data-base(-p)是另一个你常会用到的选项。它会运行makefile,显示GNU版权信息以及make 所运行的命令,然后输出它的内部数据库。数据库里的数据将会依种类划分

成以下几个组:variables、directories、implicit rules、pattern-specific variables、files(explicit rules)以及vpath earch path。如下所示:

# GNU Make 3.80

# Copyright (C) 2002 Free Software Foundation, Inc.

# This is free softwaresee the source for copying conditions.

# There is NO warrantynot even for MERCHANTABILITY or FITNESS FOR A

# PARTICULAR PURPOSE.

正常的命令将会在此处执行

# Make data base, printed on Thu Apr 29 20:58:13 2004

# Variables

...

# Directories

...

# Implicit Rules

...

# Pattern-specific variable values

...

# Files

...

# VPATH Search Paths

让我们更详细地查看以上这几个区段

变量区段(variable)将会列出每个变量以及具描述性的注释:

# automatic

<D = $(patsubst %/,%,$(dir $<))

# environment

EMACS_DIR = C:/usr/emacs-21.3.50.7

# default

CWEAVE = cweave

# makefile (from `../mp3_player/makefile', line 35)

CPPFLAGS = $(addprefix -I ,$(include_dirs))

# makefile (from `../ch07-separate-binaries/makefile', line 44)

RM := rm -f

# makefile (from `../mp3_player/makefile', line 14)

define make-library

libraries += $1

sources += $2

$1: $(call source-to-object,$2)

$(AR) $(ARFLAGS) $$@ $$^

endef

自动变量不会被显示出来,但是通过它们可以方便变量的获得,像$(<D)。注释所指出的是origin 函数所返回的变量类型(参见“较不重要的杂项函数”一节)。如果变量被定义

在一个文件中,则会在注释中指出其文件名以及该定义所在的行号。简单变量和递归变量的差别在于赋值运算符。简单变量的值将会被显示成右边部分被求值的形式。

下一个区段标示为Directories,它对make 开发人员比对make 用户有用。它列出了将会被make 检查的目录,包括可能会存在的SCCS 和RCS 子目录,但它们通常不存在。对每个目

录来说,make 会显示实现细节,比如设备编号、inode 以及文件名模式匹配的统计数据。

接着是Implicit Rules 区段。这个区段包含了make 数据库中所有的内置的和用户自定义的模式规则。此外,对于那些定义在文件中的规则,它们的注释将会指出文件名以及行号

%.c %.h: %.y

# commands to execute (from `../mp3_player/makefile', line 73):

$(YACC.y) --defines $<

$(MV) y.tab.c $*.c

$(MV) y.tab.h $*.h

%: %.c

# commands to execute (built-in):

$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@

%.o: %.c

# commands to execute (built-in):

$(COMPILE.c) $(OUTPUT_OPTION) $<

查看这个区段,是让你能够熟悉make 内置规则的变化和结构的最佳方法。当然,并非所有的内置规则都会被实现成模式规则。如果你没有找到你想要的规则,可以查看Files区段

,旧式后缀规则就列在该处。

下一个区段被标示为Pattern-specific variables,此处所列出的是定义在makefile 里的模式专属变量。所谓模式专属变量,就是变量定义的有效范围被限定在相关的模式规则执

行的时候。例如,模式变量YYLEXFLAG 被定义成:

%.c %.h: YYLEXFLAG := -d

%.c %.h: %.y

$(YACC.y) --defines $<

$(MV) y.tab.c $*.c

$(MV) y.tab.h $*.h

将会被显示成:

# Pattern-specific variable values

%.c :

# makefile (from `Makefile', line 1)

# YYLEXFLAG := -d

# variable set hash-table stats:

# Load=1/16=6%, Rehash=0, Collisions=0/1=0%

%.h :

# makefile (from `Makefile', line 1)

# YYLEXFLAG := -d

# variable set hash-table stats:

# Load=1/16=6%, Rehash=0, Collisions=0/1=0%

# 2 pattern-specific variable values

接着是Files 区段,此处所列出的都是与特定文件有关的自定义和后缀规则:

# Not a target:

.p.o:

# Implicit rule search has not been done.

# Modification time never checked.

# File has not been updated.

# commands to execute (built-in):

$(COMPILE.p) $(OUTPUT_OPTION) $<

lib/ui/libui.a: lib/ui/ui.o

# Implicit rule search has not been done.

# Last modified 2004-04-01 22:04:09.515625

# File has been updated.

# Successfully updated.

# commands to execute (from `../mp3_player/lib/ui/module.mk', line 3):

ar rv $@ $^

lib/codec/codec.o: ../mp3_player/lib/codec/codec.c ../mp3_player/lib/codec/codec.c ../mp3_player/include/codec/codec.h

# Implicit rule search has been done.

# Implicit/static pattern stem: `lib/codec/codec'

# Last modified 2004-04-01 22:04:08.40625

# File has been updated.

# Successfully updated.

# commands to execute (built-in):

$(COMPILE.c) $(OUTPUT_OPTION) $<


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12452294.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存