List goals/targets in GNU make that contain variab

2019-01-20 22:17发布

I have a fairly large makefile that creates a number of targets on the fly by computing names from variables. (eg foo$(VAR) : $(PREREQS)). Is there any way that gnu make can be convinced to spit out a list of targets after it has expanded these variables?

I'd like to be able to get the targets for an aribitrary makefile. I'm trying to write a completion function for my shell.

16条回答
疯言疯语
2楼-- · 2019-01-20 22:29

Found this solution in another thread:

sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\""

You can also add it to your Makefile:

list:
    sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\\""

And execute make list.

查看更多
Juvenile、少年°
3楼-- · 2019-01-20 22:32

Several responders have suggested using make -pn, which will print the database of rules but not execute anything -- more or less. The problem with this approach is that -n does still invoke all recursive makes, and it does still do a lot more work than necessary, because it prints out every command that it would have invoked in a regular build. A more efficient solution would be to create a trivial makefile, dummy.mk, with these contents:

__all_targets__: ; #no-op

Now invoke make as make -p -f Makefile -f dummy.mk __all_targets__. On any substantial build, the difference in the amount of output generated by make is significant. For example:

$ gmake -pn | wc
 138985 2632330 69612711
$ gmake -f Makefile -f /tmp/dummy.mk -pn __all_targets__ | wc
  21673   93437  878985

Execution time was dramatically better as well -- 2.063s for the first version, 0.059s for the second.

查看更多
趁早两清
4楼-- · 2019-01-20 22:33

I went looking for the same question and came up with this spin:

make -pn | sed -rn '/^[^# \t\.%].*:/p'

This removes all comment lines, pattern rules (lines beginning with tabs), all the intrinsics (example .c.o and %.o: %.c patterns).

查看更多
The star\"
5楼-- · 2019-01-20 22:34

Sure, but when do you want it to spit them out?

To report the name of the target when it runs the rule, put a line in the rule:

foo$(VAR): $(PREREQS)
    @echo now making the foo target: $@
    do_other_stuff...

To spit them all out at once, you could make a separate PHONY target:

.PHONY: show_vars
show_vars:
    @echo foo$(VAR)
    @echo bar$(PARAM) blah$(FLAG)
    # and so on

And this can be made a prerequisite of your default target:

all: show_vars
    ...

EDIT:
You want a way to show all possible targets of an arbitrary makefile, which I suppose means non-intrusively. Well...

To do it exactly, and be able to cope with sophisticated makefiles, e.g. involving rules constructed by eval statements, you'd have to write something close to a Make emulator. Impractical.

To see the targets of the simple rules, you could write a makefile that would act as a makefile scanner, operating on an arbitrary makefile:

  1. Get all the target names from the makefile using sed.
  2. `include` the makefile in order to use it to expand variables.
  3. Use `show_%: ; echo $$*` to print all the targets

This would be an impressive piece of work. Are you sure the goal is worth the effort?

查看更多
一夜七次
6楼-- · 2019-01-20 22:37
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'     

Taken from the make arg completion, which works like a charm.

查看更多
叛逆
7楼-- · 2019-01-20 22:37

Check out bash completion for make on GitHub.

查看更多
登录 后发表回答