Reputation: 3716
Is there any trick in GNU Makefiles to get all dependencies of a rule?
Example:
rule1: dep1_1 dep1_2 dep1_3
rule2: dep2_1 dep2_2 rule1
dump_deps:
echo "Dependencies of rule1: $(call do_the_trick, $(rule1))"
echo "Dependencies of rule2: $(call do_the_trick, $(rule2))"
install: $(prefix install-,$(call do_the_trick, $(rule1)))
I'd like to be able to call make dump_deps
and see:
dep1_1 dep1_2 dep1_3
dep2_1 dep2_2 dep1_1 dep1_2 dep1_3
Or automatically install dependencies with make install
and things like.
Is it possible?
EDIT:
I changed the example to show better that I want something automatic, and not having to hardcode dependency lists myself.
Upvotes: 3
Views: 2632
Reputation: 438
You can't show the transitive dependencies, only the direct ones, however, you can take the output generated below and feed it into the programs dot
(part of graphviz
) to make sense of the these transitive relationships.
Edit: I guess you could also post-process the results in other ways to just list the deps, but I think pretty pictures are better; feel free to downvote if you disagree ;)
Here's a sample makefile (watch for missing tabs when c&p!):
# Makefile that demonstrates how to dump dependencies.
# The macros we use for compiling stuff.
CC_OBJ=$(CC) -o $@ -c $(CFLAGS) $<
CC_BIN=$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^
# If we get "DUMP_DEPS=1 DUMP_DOT=1" on the command line, then instead of
# make-style dependencies, we'll output 'dot' syntax.
# Note: normally, DUMP_DOT_TAIL is undefined, so it doesn't generate any noise.
ifeq ($(DUMP_DOT),1)
DUMP_DOT_HEAD=digraph dependencies {
DUMP_DOT_TAIL=@echo "}"
$(info $(DUMP_DOT_HEAD))
list_dep=@for f in $^; do echo " \"$@\" -> \"$$f\";"; done
else
list_dep=@echo "$@: $^"
endif
# If we get "DUMP_DEPS=1" on the command line, then
# instead of building the code, just print the dependencies.
ifeq ($(DUMP_DEPS),1)
CC_OBJ=$(list_dep)
CC_BIN=$(list_dep)
endif
# An implicit rule that builds *.c -> *.o.
%.o:%.c
$(CC_OBJ)
# Variables for stuff we wanna build.
target=hello
objects=main.o
objects+=stuff.o
objects+=yeah.o
# The top-level 'all' target.
.PHONY: all
all: $(target)
$(DUMP_DOT_TAIL)
# Builds our final executable
$(target): $(objects)
$(CC_BIN)
# A standard clean target.
.PHONY: clean
clean:
-rm -f $(target) $(objects)
Now, you can do this:
make -B DUMP_DEPS=1
And it will go through and list all your pre-requisites is make style of "target: pre-requisite". Sample outputs:
Normal run:
cc -o main.o -c main.c
cc -o stuff.o -c stuff.c
cc -o yeah.o -c yeah.c
cc -o hello main.o stuff.o yeah.o
With make -B DUMP_DEPS=1
:
main.o: main.c
stuff.o: stuff.c
yeah.o: yeah.c
hello: main.o stuff.o yeah.o
With make -B DUMP_DEPS=1 DUMP_DOT=1
:
digraph dependencies {
"main.o" -> "main.c";
"stuff.o" -> "stuff.c";
"yeah.o" -> "yeah.c";
"hello" -> "main.o";
"hello" -> "stuff.o";
"hello" -> "yeah.o";
}
You could then run the following to output a pretty picture to an SVG image:
make -B DUMP_DEPS=1 DUMP_DOT=1 | dot -Tsvg > deps.svg
Here's what it looks like (this is actually a png, generated with -Tpng > deps.png
):
I think this would need some extra work to produce accurate results in all situations, but the principle is sound (e.g. if you use gcc-generated dependency files, you'll need to create them first).
Upvotes: 3
Reputation: 17572
use the buit in variables available with the make utility , $^ -- this represents all the dependencies of the rule.
also looking thru your code , i did make the rule1 into a variable / macro form to suit my purpose ......
rule1 := dep1 dep2 dep3
Upvotes: 1
Reputation: 2157
This should list all of the dependencies:
DEPEND = dep1 dep2 dep3
.PHONY: $(DEPEND)
dump_deps: $(DEPEND)
@printf "%s\n" $^
You should remove the line with .PHONY target for your needs. It is used for the sake of the example. And please note that there is a tab between the beginning of the line and printf.
Upvotes: 1