Debuggen des Makefiles / Teil 1 /

Das Debuggen eines Makefiles  ist ein bisschen schwarze Magie. Leider gibt es keinen Makefile- Debugger, der den Fortschritt einer bestimmten Regel oder die Erweiterung einer Variablen untersucht. Der größte Teil des Debuggens kann mit normalen Ausdrucken und Überprüfen des Makefiles durchgeführt werden . Natürlich hilft GNU make ein wenig mit seinen integrierten Methoden und Befehlszeilenoptionen. Eine der besten Techniken zum Debuggen von Makefiles besteht darin, Debug-Hooks hinzuzufügen und sichere Programmiertechniken zu verwenden, um sich auf Fehler zu stützen. Im Folgenden sind einige grundlegende Debugging-Techniken und sichere Codierungsmethoden aufgeführt, die meiner Meinung nach am nützlichsten sind.





Debugging-Funktionen von make

Eine sehr nützliche  Funktion zum Debuggen eines Makefiles, das nicht funktioniert warning



. Da die Funktion warning



zu einer leeren Zeichenfolge erweitert wird, kann sie an einer beliebigen Stelle im Makefile verwendet werden : auf der obersten Ebene, im Zielnamen, in der Abhängigkeitsliste und in Befehlsskripten. Auf diese Weise können die Werte von Variablen dort gedruckt werden, wo sie für ihre Überprüfung am besten geeignet sind. Zum Beispiel:





$(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):
      
      



Gibt Ausgabe:





$ 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
      
      



Beachten Sie, dass die Ausführung der Funktion warning



dem normalen Ablauf des Algorithmus make



für sofortige und verzögerte Berechnungen folgt . Außerdem wird die Zuordnung zu BAZ



enthält warning



und die Nachricht erst gedruckt, wenn BAZ



sie in die Abhängigkeitsliste erweitert wird.





Die Möglichkeit, einen warning



Anruf überall einzufügen , macht ihn zu einem sehr nützlichen Debugging-Tool.





Befehlszeilenoptionen

: --just-print (-n)



, --print-data-base (-p)



--warn-undefined-variables



.





--just-print

makefile — make



--just-print (-n)



. 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



. --just-print



, makefile. , make



( ) $(objects)



.





--print-data-base

, . , "" makefile, make



. : , , , , ( ) vpath . .





Variables :





# 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



(. make manual). , . . .





Directories make



, make



. make, SCCS RCS -, , . : , 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, .





makefile.  — , . , :





%.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) $<
      
      



- "Not a target";  — . , make



. , vpath , .





VPATH Search Paths VPATH



vpath



.





makefile', eval



, - , .





--warn-undefined-variables

make



. , , . , , . make



, makefile' , :





$ make --warn-undefined-variables -n
makefile:35: warning: undefined variable MAKECMDGOALS
makefile:45: warning: undefined variable CFLAGS
makefile:45: warning: undefined variable TARGET_ARCH
...
makefile:35: warning: undefined variable MAKECMDGOALS
make: warning: undefined variable CFLAGS
make: warning: undefined variable TARGET_ARCH
make: warning: undefined variable CFLAGS
make: warning: undefined variable TARGET_ARCH
...
make: warning: undefined variable LDFLAGS
make: warning: undefined variable TARGET_ARCH
make: warning: undefined variable LOADLIBES
make: warning: undefined variable LDLIBS
      
      



, .





--debug

make



, --debug



. . : basic



, verbose



, implicit



, jobs



, all



, makefile



, .





--debug



, basic



- . -d



, all



. : --debug=option1,option2



, option



( , make ):





  • basic





    . , make



    , .





  • verbose





    basic



    , .





  • implicit





    basic



    , .





  • jobs





    make



    ' . basic



    .





  • all





    -d



    .





  • makefile





    , , makefile . , . make



    makefile' . basic



    , all



    .





,

, makefile , . , makefile , .





, , , . , , , . makefile, . , makefile . , - , , , .





«KISS» — . makefile , , . . , , .





, makefile' , , - , , C++ Java. make



! , .





makefile . , make



, makefile , :





do:
   cd i-dont-exist; \
   echo *.c
      
      



makefile , :





$ make
cd i-dont-exist; \
echo *.c
/bin/sh: line 1: cd: i-dont-exist: No such file or directory
*.c
      
      



, .c



, . . -, :





SHELL = /bin/bash
do:
   cd i-dont-exist && \
   shopt -s nullglob &&
   echo *.c
      
      



cd



make



, echo



make



. , nullglob



bash



. (, .)





$ make
cd i-dont-exist && \
echo *.c
/bin/sh: line 1: cd: i-dont-exist: No such file or directory
make: *** [do] Error 1
      
      



. makefile' , , . ?





_MKDIRS := $(shell for d in $(REQUIRED_DIRS); do [[ -d $$d \
]] || mkdir -p $$d; done)
      
      



:





_MKDIRS := $(shell                           \
             for d in $(REQUIRED_DIRS);      \
             do                              \
               [[ -d $$d ]] || mkdir -p $$d; \
             done)
      
      



, , , . . , - , , , .





, . , :





TAGS:
        cd src \
        ctags --recurse

disk_free:
        echo "Checking free disk space..." \
        df . | awk '{ print $$4 }'

      
      



. . , strip



. . , , .





. , .  — make . « » .





,  — if



, , assert



, , , ( ), , , make



.





 — . make — 3.80:





NEED_VERSION := 3.80
$(if $(filter $(NEED_VERSION),$(MAKE_VERSION)),,             \
 $(error You must be running make version $(NEED_VERSION).))
      
      



Java CLASSPATH



.





- .





assert



, :





# $(call assert,condition,message)
define assert
   $(if $1,,$(error Assertion failed: $2))
endef
# $(call assert-file-exists,wildcard-pattern)
define assert-file-exists
   $(call assert,$(wildcard $1),$1 does not exist)
endef
# $(call assert-not-null,make-variable)
define assert-not-null
   $(call assert,$($1),The variable "$1" is null)
endef
      
      



assert



makefile , .





:





# $(debug-enter)
debug-enter = $(if $(debug_trace),\
                $(warning Entering $0($(echo-args))))

# $(debug-leave)
debug-leave = $(if $(debug_trace),$(warning Leaving $0))
comma := ,
echo-args = $(subst ' ','$(comma) ',\
              $(foreach a,1 2 3 4 5 6 7 8 9,'$($a)'))
      
      



, . debug_trace



:





$ make debug_trace=1
      
      



@



, , :





QUIET := @
target:
   $(QUIET) some command
      
      



:





$ make QUIET=
      
      










All Articles