Is there a way to flag some targets in a Makefile
so that they don't appear at all in the shell when the user types make
and then presses Tab
?
I am having a Makefile
with too many recipes and I don't want them all to appear in the shell autocompletion when a users presses Tab
looking for targets.
-
@derobert bash, added tagMarcus Junius Brutus– Marcus Junius Brutus2014-09-10 16:45:33 +00:00Commented Sep 10, 2014 at 16:45
4 Answers
After studying the problem and coming up with a solution that I wrote in the first answer, I realized that there is another very simple way.
Just start the target's names you don't want to show beginning with a dot.
Example:
.PHONY: foo .hiddentarget
foo: foo.x .hiddentarget
foo.x: foo.c
touch foo.x
.hiddentarget: foo.x
echo foo.x ok, I believe
And that's all you need!
I came to this idea after trying to figure out how to prevent a target named .HIDDENGOALS being called by mistake and run all hidden goals. :)
Warning Although I don't see any, I'm not sure if there isn't any side effect on using target names like this ".targetname" (starting with a dot).
-
Doesn't seem to work for nested hidden files, i.e.
foo/.hidden: ...
,bar/.hidden: ...
,.hidden: foo/.hidden bar/.hidden
; these will still show up, so some additional gymnastics is required.Filip Dupanović– Filip Dupanović2015-03-31 09:19:17 +00:00Commented Mar 31, 2015 at 9:19 -
I'm not sure if I followed you @FilipDupanović. This is for hiding targets, not files.DrBeco– DrBeco2016-06-15 13:11:15 +00:00Commented Jun 15, 2016 at 13:11
-
1That time when you google and find your own answer.... :DDrBeco– DrBeco2020-01-27 00:45:06 +00:00Commented Jan 27, 2020 at 0:45
-
I feel you - happened a few times to me too but more often where I was asking the question ;) One problem/missing feature of this approach, I think, is that you can't hide goals that are actually file names which always show up(?) So in your example it's not possible to hide the foo.x goal.stefanct– stefanct2020-09-17 01:41:34 +00:00Commented Sep 17, 2020 at 1:41
To hide some targets, you'd need to hack the autocompletion function of your shell. bash
uses /etc/bash_completion
and /etc/bash_completion.d/*
for that.
Can't recall how tcsh does it.
I've observed that this also works by starting the target with an underscore
_hiddentarget:
@echo "Running hidden target"
EDITED Best to read the other answer (target name starting with a dot). But I'll let this answer here, as the programming part may help other similar issues.
Ok, it took me some time to come up with a solution. This is a (good) draft, and hopefully it will do the job right.
You must edit the file /usr/share/bash-completion/completions/make (for Debian Wheezy, or some similar to your system)
In my current version, line numbers 70 to 73 have the code:
70 COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
71 awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
72 {split($1,A,/ /);for(i in A)print A[i]}' )" \
73 -- "$cur" ) )
Replace then for the foloowing code:
70 HIDDENGOALS="$(make -qp | grep '^\.HIDDENGOALS:' | cut -d' ' -f2- | sed 's/ /\\|/g')"
71 if [[ "$HIDDENGOALS" == "" || "$HIDDENGOALS" == ".HIDDENGOALS:" ]]; then
72 COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
73 awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
74 {split($1,A,/ /);for(i in A)print A[i]}' )" \
75 -- "$cur" ) )
76 else
77 COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
78 awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
79 {split($1,A,/ /);for(i in A)print A[i]}' \
80 | grep -ve "$HIDDENGOALS" )" \
81 -- "$cur" ) )
Now inside your makefile
you can use the following special target to hide goals from bash autocompletion:
.HIDDENGOALS: somegoal anothergoal goalstohide
much like a .PHONY
special target (there are some differences).
Careful:
(I) As this solution works through a grep -ev
, the special target isn't quite so. It will use anything in the line to match just the way a Regular Expression does.
So, if you have a target, say, copy2
, and another copy
, writting
.HIDDENGOALS: copy
will hide both goals!
I let the solution to this behavior as an exercise to the reader! ;)
(II) Another thing to notice, the :
is hardcoded to be next to .HIDDENGOALS:
, meaning that although targets allow spaces like .PHONY :
, this special hack doesn't.
(III) I think it would be better to edit a local file instead of /usr/share/bash-completion/completions/make, to avoid losing the information when an upgrade comes. But I did not tested any options. If you know, please comment and I'll update this answer.
(IV) There is a slight chance of a curious run the very target .HIDDENGOALS with a make .HIDDENGOALS
. That would run all hidden goals. And autocompleting the name wasn't possible, which lead me to the other quite simple answer!
-
2What are the odds that you would end up googling some problem years later just to find out that the guy who gives you the answer is yourself? :)DrBeco– DrBeco2017-03-07 03:44:29 +00:00Commented Mar 7, 2017 at 3:44