Skip to content

Instantly share code, notes, and snippets.

@ruittenb
Last active October 9, 2025 07:48
Show Gist options
  • Select an option

  • Save ruittenb/5d2d281237385276f49652b9b9f6d5a1 to your computer and use it in GitHub Desktop.

Select an option

Save ruittenb/5d2d281237385276f49652b9b9f6d5a1 to your computer and use it in GitHub Desktop.

Revisions

  1. René Uittenbogaard revised this gist Mar 18, 2022. 1 changed file with 17 additions and 9 deletions.
    26 changes: 17 additions & 9 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -6,15 +6,18 @@
    # also known as : https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1

    ############################################################################
    #
    # DESCRIPTION
    #
    # This code defines a 'help' target to add to your Makefile, that can auto-
    # matically create a list of your Makefile's targets, with short descriptions.
    #
    # This has been tested on (and compatible with):
    # - GNU make 3.81
    # - GNU awk 5.1.1
    # - MacOS awk version 20200816
    #

    ############################################################################
    #
    # INSTALLATION
    #
    # Copy this block over to your own Makefile:
    @@ -23,10 +26,9 @@

    .PHONY: help # See https://tinyurl.com/makefile-autohelp
    help: ## Print help for each target
    @awk -v tab=12 'BEGIN{FS="(:.*## |##@ )";c="\033[36m";m="\033[0m";y=" ";a=2;h()}function t(s){gsub(/[ \t]+$$/,"",s);gsub(/^[ \t]+/,"",s);return s}function u(g,d){split(t(g),f," ");for(j in f)printf"%s%s%-"tab"s%s%s\n",y,c,t(f[j]),m,d}function h(){printf"\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n",y,c,m}/\\$$/{gsub(/\\$$/,"");b=b$$0;next}b{$$0=b$$0;b=""}/^[-a-zA-Z0-9*\/%_. ]+:.*## /{p=sprintf("\n%"(tab+a)"s"y,"");gsub(/\\n/,p);if($$1~/%/&&$$2~/^%:/){n=split($$2,q,/%:|:% */);for(i=2;i<n;i+=2){g=$$1;sub(/%/,q[i],g);u(g,q[i+1])}}else if($$1~/%/&&$$2~/%:[^%]+:[^%]+:%/){d=$$2;sub(/^.*%:/,"",d);sub(/:%.*/,"",d);n=split(d,q,/:/);for(i=1;i<=n;i++){g=$$1;d=$$2;sub(/%/,q[i],g);sub(/%:[^%]+:%/,q[i],d);u(g,d)}}else u($$1,$$2)}/^##@ /{gsub(/\\n/,"\n");if(NF==3)tab=$$2;printf"\n%s\n",$$NF}END{print""}' $(MAKEFILE_LIST) # v1.61
    @awk -v tab=12 'BEGIN{FS="(:.*## |##@ |@## )";c="\033[36m";m="\033[0m";y=" ";a=2;h()}function t(s){gsub(/[ \t]+$$/,"",s);gsub(/^[ \t]+/,"",s);return s}function u(g,d){split(t(g),f," ");for(j in f)printf"%s%s%-"tab"s%s%s\n",y,c,t(f[j]),m,d}function h(){printf"\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n",y,c,m}/\\$$/{gsub(/\\$$/,"");b=b$$0;next}b{$$0=b$$0;b=""}/^[-a-zA-Z0-9*\/%_. ]+:.*## /{p=sprintf("\n%"(tab+a)"s"y,"");gsub(/\\n/,p);if($$1~/%/&&$$2~/^%:/){n=split($$2,q,/%:|:% */);for(i=2;i<n;i+=2){g=$$1;sub(/%/,q[i],g);u(g,q[i+1])}}else if($$1~/%/&&$$2~/%:[^%]+:[^%]+:%/){d=$$2;sub(/^.*%:/,"",d);sub(/:%.*/,"",d);n=split(d,q,/:/);for(i=1;i<=n;i++){g=$$1;d=$$2;sub(/%/,q[i],g);sub(/%:[^%]+:%/,q[i],d);u(g,d)}}else u($$1,$$2)}/^##@ /{gsub(/\\n/,"\n");if(NF==3)tab=$$2;printf"\n%s\n",$$NF}END{print""}' $(MAKEFILE_LIST) # v1.62

    ############################################################################
    #
    # USAGE
    #
    # The awk option '-v tab=12' can be changed to change the initial indentation of the output.
    @@ -37,7 +39,6 @@ help: ## Print help for each target
    # '##@' at the start of a line is used for header lines.

    ############################################################################
    #
    # EXAMPLES
    #

    @@ -76,15 +77,22 @@ and its continuation, with prerequisites spanning lines

    double: prereq ## This will not be shown ## Sequential comments only show the latter

    newline: ## Comments may\ncontain newlines,\nspecified as "backslash-n"
    newline: ## Comments may\ncontain newlines,\nspecified with backslash-n

    ##@ 16 ##@ Heading text may change the indentation of the next block:
    # --------------------------------------------------------------------------
    # Multiple targets:

    target1 target2: ## Multiple targets will be split across lines

    goal1 \
    goal2: ## Multiple targets may span lines

    # --------------------------------------------------------------------------
    ##@ 16 @## Heading text may change the indentation of the next block.

    # --------------------------------------------------------------------------
    ##@ Examples of targets with wildcards:

    target-%: ## %:one:% Wildcard targets may be... %:two:% ...specified with individual descriptions

    copy-%: ## %:here:% Copy things hither %:there:% Copy things thither
    @@ -117,7 +125,7 @@ It will not be parsed by 'make help'.
    #
    # @awk -v tab=12 '
    # BEGIN {
    # FS = "(:.*## |##@ )";
    # FS = "(:.*## |##@ |@## )";
    # buffer = "";
    # color = "\033[36m";
    # nocolor = "\033[0m";
    @@ -178,6 +186,6 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.61
    # ' $(MAKEFILE_LIST) # v1.62


  2. René Uittenbogaard revised this gist Apr 16, 2021. 2 changed files with 17 additions and 9 deletions.
    22 changes: 15 additions & 7 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -23,13 +23,13 @@

    .PHONY: help # See https://tinyurl.com/makefile-autohelp
    help: ## Print help for each target
    @awk -v tab=12 'BEGIN{FS=":.*## ";c="\033[36m";m="\033[0m";y=" ";a=2;h()}function t(s){gsub(/[ \t]+$$/,"",s);gsub(/^[ \t]+/,"",s);return s}function u(g,d){split(t(g),f," ");for(j in f)printf"%s%s%-"tab"s%s%s\n",y,c,t(f[j]),m,d}function h(){printf"\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n",y,c,m}/\\$$/{gsub(/\\$$/,"");b=b$$0;next}b{$$0=b$$0;b=""}/^[-a-zA-Z0-9*\/%_. ]+:.*## /{p=sprintf("\n%"(tab+a)"s"y,"");gsub(/\\n/,p);if($$1~/%/&&$$2~/^%:/){n=split($$2,q,/%:|:% */);for(i=2;i<n;i+=2){g=$$1;sub(/%/,q[i],g);u(g,q[i+1])}}else if($$1~/%/&&$$2~/%:[^%]+:[^%]+:%/){d=$$2;sub(/^.*%:/,"",d);sub(/:%.*/,"",d);n=split(d,q,/:/);for(i=1;i<=n;i++){g=$$1;d=$$2;sub(/%/,q[i],g);sub(/%:[^%]+:%/,q[i],d);u(g,d)}}else u($$1,$$2)}/^##@ /{gsub(/\\n/,"\n");printf"\n%s\n",substr($$0,5)}END{print""}' $(MAKEFILE_LIST) # v1.60
    @awk -v tab=12 'BEGIN{FS="(:.*## |##@ )";c="\033[36m";m="\033[0m";y=" ";a=2;h()}function t(s){gsub(/[ \t]+$$/,"",s);gsub(/^[ \t]+/,"",s);return s}function u(g,d){split(t(g),f," ");for(j in f)printf"%s%s%-"tab"s%s%s\n",y,c,t(f[j]),m,d}function h(){printf"\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n",y,c,m}/\\$$/{gsub(/\\$$/,"");b=b$$0;next}b{$$0=b$$0;b=""}/^[-a-zA-Z0-9*\/%_. ]+:.*## /{p=sprintf("\n%"(tab+a)"s"y,"");gsub(/\\n/,p);if($$1~/%/&&$$2~/^%:/){n=split($$2,q,/%:|:% */);for(i=2;i<n;i+=2){g=$$1;sub(/%/,q[i],g);u(g,q[i+1])}}else if($$1~/%/&&$$2~/%:[^%]+:[^%]+:%/){d=$$2;sub(/^.*%:/,"",d);sub(/:%.*/,"",d);n=split(d,q,/:/);for(i=1;i<=n;i++){g=$$1;d=$$2;sub(/%/,q[i],g);sub(/%:[^%]+:%/,q[i],d);u(g,d)}}else u($$1,$$2)}/^##@ /{gsub(/\\n/,"\n");if(NF==3)tab=$$2;printf"\n%s\n",$$NF}END{print""}' $(MAKEFILE_LIST) # v1.61

    ############################################################################
    #
    # USAGE
    #
    # The awk option '-v tab=12' can be changed to change the indentation of the output.
    # The awk option '-v tab=12' can be changed to change the initial indentation of the output.
    #
    # Descriptions for each target should be added in the Makefile itself:
    #
    @@ -41,6 +41,9 @@ help: ## Print help for each target
    # EXAMPLES
    #

    # --------------------------------------------------------------------------
    ##@ Examples of heading text:

    ##@ This is heading text, which is shown on a separate line.

    ##@ Heading text may \
    @@ -51,6 +54,7 @@ span multiple lines.
    # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    # --------------------------------------------------------------------------
    ##@ Examples of targets:

    show1: ## Description for show1, no prerequisites
    @@ -74,17 +78,20 @@ double: prereq ## This will not be shown ## Sequential comments only show the la

    newline: ## Comments may\ncontain newlines,\nspecified as "backslash-n"

    ##@ 16 ##@ Heading text may change the indentation of the next block:

    target1 target2: ## Multiple targets will be split across lines

    goal1 \
    goal2: ## Multiple targets spanning lines
    goal2: ## Multiple targets may span lines

    target-%: ## %:one:% Wildcard targets may be... %:two:% ...specified with individual descriptions

    copy-%: ## %:here:% Copy things hither %:there:% Copy things thither

    test-%: ## Test the %:prod:stag:% environment
    test-%: ## Test the %:production:staging:% environment

    # --------------------------------------------------------------------------
    ##@ Nothing should be printed from the lines below:

    noshow1: # This is just any comment, which will not be parsed by 'make help'
    @@ -110,7 +117,7 @@ It will not be parsed by 'make help'.
    #
    # @awk -v tab=12 '
    # BEGIN {
    # FS = ":.*## ";
    # FS = "(:.*## |##@ )";
    # buffer = "";
    # color = "\033[36m";
    # nocolor = "\033[0m";
    @@ -165,11 +172,12 @@ It will not be parsed by 'make help'.
    # }
    # /^##@ / {
    # gsub(/\\n/, "\n");
    # printf "\n%s\n", substr($0, 5);
    # if (NF == 3) tab = $2;
    # printf "\n%s\n", $NF;
    # }
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.60
    # ' $(MAKEFILE_LIST) # v1.61


    4 changes: 2 additions & 2 deletions minimize.pl
    Original file line number Diff line number Diff line change
    @@ -8,9 +8,9 @@
    $_ = join "", map { chomp; s/^# *//; $_ } grep { /^# \@awk/ .. 0 } <>;

    # remove whitespace around operators, statements and blocks
    s/ ([+=<>~]|[-+<>]=|!~|&&|\|\|) /$1/g;
    s/ ([+=<>~]|[-+<>=]=|!~|&&|\|\|) /$1/g;
    s/([;{}(),]) (?!#)/$1/g;
    s/ ([{}()])/$1/g;
    s/ ([{}()])(?!")/$1/g;
    s/\$(?!\()/\$\$/g;
    s/;}/}/g;

  3. René Uittenbogaard revised this gist Apr 16, 2021. 2 changed files with 3 additions and 3 deletions.
    4 changes: 2 additions & 2 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,7 @@

    .PHONY: help # See https://tinyurl.com/makefile-autohelp
    help: ## Print help for each target
    @awk -v tab=12 'BEGIN{FS=":.*## ";c="\033[36m";m="\033[0m";y=" ";a=2;h()}function t(s){gsub(/[ \t]+$$/,"",s);gsub(/^[ \t]+/,"",s);return s}function u(g,d){split(t(g),f," ");for(j in f)printf"%s%s%-"tab"s%s%s\n",y,c,t(f[j]),m,d}function h(){printf"\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n",y,c,m}/\\$$/{gsub(/\\$$/,"");b=b$$0;next}b{$$0=b$$0;b=""}/^[-a-zA-Z0-9*\/%_. ]+:.*## /{p=sprintf("\n%"(tab+a)"s"y,"");gsub(/\\n/,p);if($$1~/%/&&$$2~/^%:/){n=split($$2,q,/%:|:% */);for(i=2;i<n;i+=2){g=$$1;sub(/%/,q[i],g);u(g,q[i+1])}}else if($$1~/%/&&$$2~/%:[^%]+:[^%]+:%/){d=$$2;sub(/^.*%:/,"",d);sub(/:%.*/,"",d);n=split(d,q,/:/);for(i=1;i <= n;i++){g=$$1;d=$$2;sub(/%/,q[i],g);sub(/%:[^%]+:%/,q[i],d);u(g,d)}}else u($$1,$$2)}/^##@ /{gsub(/\\n/,"\n");printf"\n%s\n",substr($$0,5)}END{print""}' $(MAKEFILE_LIST) # v1.59
    @awk -v tab=12 'BEGIN{FS=":.*## ";c="\033[36m";m="\033[0m";y=" ";a=2;h()}function t(s){gsub(/[ \t]+$$/,"",s);gsub(/^[ \t]+/,"",s);return s}function u(g,d){split(t(g),f," ");for(j in f)printf"%s%s%-"tab"s%s%s\n",y,c,t(f[j]),m,d}function h(){printf"\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n",y,c,m}/\\$$/{gsub(/\\$$/,"");b=b$$0;next}b{$$0=b$$0;b=""}/^[-a-zA-Z0-9*\/%_. ]+:.*## /{p=sprintf("\n%"(tab+a)"s"y,"");gsub(/\\n/,p);if($$1~/%/&&$$2~/^%:/){n=split($$2,q,/%:|:% */);for(i=2;i<n;i+=2){g=$$1;sub(/%/,q[i],g);u(g,q[i+1])}}else if($$1~/%/&&$$2~/%:[^%]+:[^%]+:%/){d=$$2;sub(/^.*%:/,"",d);sub(/:%.*/,"",d);n=split(d,q,/:/);for(i=1;i<=n;i++){g=$$1;d=$$2;sub(/%/,q[i],g);sub(/%:[^%]+:%/,q[i],d);u(g,d)}}else u($$1,$$2)}/^##@ /{gsub(/\\n/,"\n");printf"\n%s\n",substr($$0,5)}END{print""}' $(MAKEFILE_LIST) # v1.60

    ############################################################################
    #
    @@ -170,6 +170,6 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.59
    # ' $(MAKEFILE_LIST) # v1.60


    2 changes: 1 addition & 1 deletion minimize.pl
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@
    $_ = join "", map { chomp; s/^# *//; $_ } grep { /^# \@awk/ .. 0 } <>;

    # remove whitespace around operators, statements and blocks
    s/ ([+=<>~]|\+=|-=|!~|&&|\|\|) /$1/g;
    s/ ([+=<>~]|[-+<>]=|!~|&&|\|\|) /$1/g;
    s/([;{}(),]) (?!#)/$1/g;
    s/ ([{}()])/$1/g;
    s/\$(?!\()/\$\$/g;
  4. René Uittenbogaard revised this gist Apr 16, 2021. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,7 @@

    .PHONY: help # See https://tinyurl.com/makefile-autohelp
    help: ## Print help for each target
    @awk -v tab=12 'BEGIN{FS=":.*## ";c="\033[36m";m="\033[0m";y=" ";a=2;h()}function t(s){gsub(/[ \t]+$$/,"",s);gsub(/^[ \t]+/,"",s);return s}function u(g,d){split(t(g),f," ");for(j in f)printf"%s%s%-"tab"s%s%s\n",y,c,t(f[j]),m,d}function h(){printf"\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n",y,c,m}/\\$$/{gsub(/\\$$/,"");b=b$$0;next}b{$$0=b$$0;b=""}/^[-a-zA-Z0-9*/%_. ]+:.*## /{p=sprintf("\n%"(tab+a)"s"y,"");gsub(/\\n/,p);if($$1~/%/&&$$2~/^%:/){n=split($$2,q,/%:|:% */);for(i=2;i<n;i+=2){g=$$1;sub(/%/,q[i],g);u(g,q[i+1])}}else if($$1~/%/&&$$2~/%:[^%]+:[^%]+:%/){d=$$2;sub(/^.*%:/,"",d);sub(/:%.*/,"",d);n=split(d,q,/:/);for(i=1;i <= n;i++){g=$$1;d=$$2;sub(/%/,q[i],g);sub(/%:[^%]+:%/,q[i],d);u(g,d)}}else u($$1,$$2)}/^##@ /{gsub(/\\n/,"\n");printf"\n%s\n",substr($$0,5)}END{print""}' $(MAKEFILE_LIST) # v1.58
    @awk -v tab=12 'BEGIN{FS=":.*## ";c="\033[36m";m="\033[0m";y=" ";a=2;h()}function t(s){gsub(/[ \t]+$$/,"",s);gsub(/^[ \t]+/,"",s);return s}function u(g,d){split(t(g),f," ");for(j in f)printf"%s%s%-"tab"s%s%s\n",y,c,t(f[j]),m,d}function h(){printf"\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n",y,c,m}/\\$$/{gsub(/\\$$/,"");b=b$$0;next}b{$$0=b$$0;b=""}/^[-a-zA-Z0-9*\/%_. ]+:.*## /{p=sprintf("\n%"(tab+a)"s"y,"");gsub(/\\n/,p);if($$1~/%/&&$$2~/^%:/){n=split($$2,q,/%:|:% */);for(i=2;i<n;i+=2){g=$$1;sub(/%/,q[i],g);u(g,q[i+1])}}else if($$1~/%/&&$$2~/%:[^%]+:[^%]+:%/){d=$$2;sub(/^.*%:/,"",d);sub(/:%.*/,"",d);n=split(d,q,/:/);for(i=1;i <= n;i++){g=$$1;d=$$2;sub(/%/,q[i],g);sub(/%:[^%]+:%/,q[i],d);u(g,d)}}else u($$1,$$2)}/^##@ /{gsub(/\\n/,"\n");printf"\n%s\n",substr($$0,5)}END{print""}' $(MAKEFILE_LIST) # v1.59

    ############################################################################
    #
    @@ -139,7 +139,7 @@ It will not be parsed by 'make help'.
    # $0 = buffer $0;
    # buffer = "";
    # }
    # /^[-a-zA-Z0-9*/%_. ]+:.*## / {
    # /^[-a-zA-Z0-9*\/%_. ]+:.*## / {
    # pad = sprintf("\n%" (tab + hang) "s" indent, "");
    # gsub(/\\n/, pad);
    # if ($1 ~ /%/ && $2 ~ /^%:/) {
    @@ -170,6 +170,6 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.58
    # ' $(MAKEFILE_LIST) # v1.59


  5. René Uittenbogaard revised this gist Oct 21, 2020. 3 changed files with 74 additions and 60 deletions.
    56 changes: 33 additions & 23 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@

    ############################################################################
    #
    # makefile-autohelp
    @@ -10,8 +9,8 @@
    #
    # DESCRIPTION
    #
    # This code adds a 'help' target to your Makefile, that automatically
    # creates a table of your Makefile's targets and short descriptions.
    # This code defines a 'help' target to add to your Makefile, that can auto-
    # matically create a list of your Makefile's targets, with short descriptions.
    #

    ############################################################################
    @@ -24,8 +23,7 @@

    .PHONY: help # See https://tinyurl.com/makefile-autohelp
    help: ## Print help for each target
    @awk -v tab=12 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; hang = 2; header(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (j in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[j]), nocolor, desc; } function header() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" (tab + hang) "s" indent, ""); gsub(/\\n/, pad); if ($$1 !~ /%/ || $$2 !~ /^%:/) { spout($$1, $$2); } else { n = split($$2, parts, /%:|:% */); for (i = 2; i < n; i += 2) { target = $$1; sub(/%/, parts[i], target); spout(target, parts[i + 1]); } } } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5); } END { print ""; }' $(MAKEFILE_LIST) # v1.57

    @awk -v tab=12 'BEGIN{FS=":.*## ";c="\033[36m";m="\033[0m";y=" ";a=2;h()}function t(s){gsub(/[ \t]+$$/,"",s);gsub(/^[ \t]+/,"",s);return s}function u(g,d){split(t(g),f," ");for(j in f)printf"%s%s%-"tab"s%s%s\n",y,c,t(f[j]),m,d}function h(){printf"\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n",y,c,m}/\\$$/{gsub(/\\$$/,"");b=b$$0;next}b{$$0=b$$0;b=""}/^[-a-zA-Z0-9*/%_. ]+:.*## /{p=sprintf("\n%"(tab+a)"s"y,"");gsub(/\\n/,p);if($$1~/%/&&$$2~/^%:/){n=split($$2,q,/%:|:% */);for(i=2;i<n;i+=2){g=$$1;sub(/%/,q[i],g);u(g,q[i+1])}}else if($$1~/%/&&$$2~/%:[^%]+:[^%]+:%/){d=$$2;sub(/^.*%:/,"",d);sub(/:%.*/,"",d);n=split(d,q,/:/);for(i=1;i <= n;i++){g=$$1;d=$$2;sub(/%/,q[i],g);sub(/%:[^%]+:%/,q[i],d);u(g,d)}}else u($$1,$$2)}/^##@ /{gsub(/\\n/,"\n");printf"\n%s\n",substr($$0,5)}END{print""}' $(MAKEFILE_LIST) # v1.58

    ############################################################################
    #
    @@ -35,7 +33,7 @@ help: ## Print help for each target
    #
    # Descriptions for each target should be added in the Makefile itself:
    #
    # '##' after a target is used for target descriptions
    # '##' after a target is used for target descriptions;
    # '##@' at the start of a line is used for header lines.

    ############################################################################
    @@ -48,7 +46,7 @@ help: ## Print help for each target
    ##@ Heading text may \
    span multiple lines.

    ##@ Heading text may contain\n- newlines\n- by specifying these with\n- backslash-n\n
    ##@ Heading text may contain\nnewlines by specifying\nthese with backslash-n

    # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.
    @@ -74,7 +72,7 @@ and its continuation, with prerequisites spanning lines

    double: prereq ## This will not be shown ## Sequential comments only show the latter

    newline: ## Comments may\ncontain newlines,\nentered as "backslash-n"
    newline: ## Comments may\ncontain newlines,\nspecified as "backslash-n"

    target1 target2: ## Multiple targets will be split across lines

    @@ -85,6 +83,8 @@ target-%: ## %:one:% Wildcard targets may be... %:two:% ...specified with indivi

    copy-%: ## %:here:% Copy things hither %:there:% Copy things thither

    test-%: ## Test the %:prod:stag:% environment

    ##@ Nothing should be printed from the lines below:

    noshow1: # This is just any comment, which will not be parsed by 'make help'
    @@ -106,7 +106,7 @@ It will not be parsed by 'make help'.

    ############################################################################
    #
    # Readable version of code, with '$' replaced with makefile-style '$$', but no trailing backslashes:
    # Readable version of code:
    #
    # @awk -v tab=12 '
    # BEGIN {
    @@ -119,7 +119,7 @@ It will not be parsed by 'make help'.
    # header();
    # }
    # function trim(str) {
    # gsub(/[ \t]+$$/, "", str);
    # gsub(/[ \t]+$/, "", str);
    # gsub(/^[ \t]+/, "", str);
    # return str;
    # }
    @@ -130,36 +130,46 @@ It will not be parsed by 'make help'.
    # function header() {
    # printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor;
    # }
    # /\\$$/ {
    # gsub(/\\$$/, "");
    # buffer = buffer $$0;
    # /\\$/ {
    # gsub(/\\$/, "");
    # buffer = buffer $0;
    # next;
    # }
    # buffer {
    # $$0 = buffer $$0;
    # $0 = buffer $0;
    # buffer = "";
    # }
    # /^[-a-zA-Z0-9*/%_. ]+:.*## / {
    # pad = sprintf("\n%" (tab + hang) "s" indent, "");
    # gsub(/\\n/, pad);
    # if ($$1 !~ /%/ || $$2 !~ /^%:/) {
    # spout($$1, $$2);
    # } else {
    # n = split($$2, parts, /%:|:% */);
    # if ($1 ~ /%/ && $2 ~ /^%:/) {
    # n = split($2, parts, /%:|:% */);
    # for (i = 2; i < n; i += 2) {
    # target = $$1;
    # target = $1;
    # sub(/%/, parts[i], target);
    # spout(target, parts[i + 1]);
    # }
    # }
    # } else if ($1 ~ /%/ && $2 ~ /%:[^%]+:[^%]+:%/) {
    # desc = $2;
    # sub(/^.*%:/, "", desc);
    # sub(/:%.*/, "", desc);
    # n = split(desc, parts, /:/);
    # for (i = 1; i <= n; i++) {
    # target = $1;
    # desc = $2;
    # sub(/%/, parts[i], target);
    # sub(/%:[^%]+:%/, parts[i], desc);
    # spout(target, desc);
    # }
    # } else spout($1, $2);
    # }
    # /^##@ / {
    # gsub(/\\n/, "\n");
    # printf "\n%s\n", substr($$0, 5);
    # printf "\n%s\n", substr($0, 5);
    # }
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.57
    #
    # ' $(MAKEFILE_LIST) # v1.58


    41 changes: 41 additions & 0 deletions minimize.pl
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,41 @@
    #!/usr/bin/env perl
    #
    # This script may be used to generate a minimized 'help' recipe
    # from the readable version of the code in the Makefile.
    #
    # Just pipe the entire Makefile through this script.

    $_ = join "", map { chomp; s/^# *//; $_ } grep { /^# \@awk/ .. 0 } <>;

    # remove whitespace around operators, statements and blocks
    s/ ([+=<>~]|\+=|-=|!~|&&|\|\|) /$1/g;
    s/([;{}(),]) (?!#)/$1/g;
    s/ ([{}()])/$1/g;
    s/\$(?!\()/\$\$/g;
    s/;}/}/g;

    # shorten variable names
    s/\bhang\b/a/g;
    s/\bbuffer\b/b/g;
    s/\bcolor\b/c/g;
    s/\bdesc\b/d/g;
    s/\bfields\b/f/g;
    s/\btarget\b(?!>)/g/g;
    s/\bheader\b/h/g;
    s/\bnocolor\b/m/g;
    s/\bpad\b/p/g;
    s/\bparts\b/q/g;
    s/\bstr\b/s/g;
    s/\btrim\b/t/g;
    s/\bspout\b/u/g;
    s/\bindent\b/y/g;

    # leftover corrections
    s/(printf?) /$1/g;
    s/ (tab) /$1/g;
    s/" y/"y/g;
    s/b \$/b\$/g;
    s/(BEGIN{[^{}]+;)b="";/$1/g;

    print;

    37 changes: 0 additions & 37 deletions minimize.sh
    Original file line number Diff line number Diff line change
    @@ -1,37 +0,0 @@
    #!/usr/bin/env bash
    #
    # This script may be used to minimize the 'help' recipe in the Makefile.
    # Just feed the recipe line, target or the entire Makefile through this script.

    perl -pe '
    if (/^\t\@awk/) {
    # remove whitespace around operators, statements and blocks
    s/ ([+=<>~]|\+=|-=|!~|&&|\|\|) /$1/g;
    s/([;{}(),]) (?!#)/$1/g;
    s/ ([{}()])/$1/g;
    s/;}/}/g;
    # shorten variable names
    s/\bhang\b/a/g;
    s/\bbuffer\b/b/g;
    s/\bcolor\b/c/g;
    s/\bdesc\b/d/g;
    s/\bfields\b/f/g;
    s/\btarget\b(?!>)/g/g;
    s/\bheader\b/h/g;
    s/\bnocolor\b/m/g;
    s/\bpad\b/p/g;
    s/\bparts\b/q/g;
    s/\bstr\b/s/g;
    s/\btrim\b/t/g;
    s/\bspout\b/u/g;
    s/\bindent\b/y/g;
    # leftover corrections
    s/(printf?) /$1/g;
    s/ (tab) /$1/g;
    s/" y/"y/g;
    s/b \$/b\$/g;
    s/(BEGIN{[^{}]+;)b="";/$1/g;
    }
    '
  6. René Uittenbogaard revised this gist Oct 21, 2020. 2 changed files with 41 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -24,13 +24,14 @@

    .PHONY: help # See https://tinyurl.com/makefile-autohelp
    help: ## Print help for each target
    @awk -v tab=12 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; hang = 2; header(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (j in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[j]), nocolor, desc; } function header() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" (tab + hang) "s" indent, ""); gsub(/\\n/, pad); if ($$1 !~ /%/ || $$2 !~ /^%:/) { spout($$1, $$2); } else { n = split($$2, parts, /%:|:% */); for (i = 2; i < n; i += 2) { target = $$1; sub(/%/, parts[i], target); spout(target, parts[i + 1]); } } } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5); } END { print ""; } ' $(MAKEFILE_LIST) # v1.56
    @awk -v tab=12 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; hang = 2; header(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (j in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[j]), nocolor, desc; } function header() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" (tab + hang) "s" indent, ""); gsub(/\\n/, pad); if ($$1 !~ /%/ || $$2 !~ /^%:/) { spout($$1, $$2); } else { n = split($$2, parts, /%:|:% */); for (i = 2; i < n; i += 2) { target = $$1; sub(/%/, parts[i], target); spout(target, parts[i + 1]); } } } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5); } END { print ""; }' $(MAKEFILE_LIST) # v1.57


    ############################################################################
    #
    # USAGE
    #
    # The awk option '-v tab=10' can be changed to change the indentation of the output.
    # The awk option '-v tab=12' can be changed to change the indentation of the output.
    #
    # Descriptions for each target should be added in the Makefile itself:
    #
    @@ -159,6 +160,6 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.56
    # ' $(MAKEFILE_LIST) # v1.57
    #

    37 changes: 37 additions & 0 deletions minimize.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,37 @@
    #!/usr/bin/env bash
    #
    # This script may be used to minimize the 'help' recipe in the Makefile.
    # Just feed the recipe line, target or the entire Makefile through this script.

    perl -pe '
    if (/^\t\@awk/) {
    # remove whitespace around operators, statements and blocks
    s/ ([+=<>~]|\+=|-=|!~|&&|\|\|) /$1/g;
    s/([;{}(),]) (?!#)/$1/g;
    s/ ([{}()])/$1/g;
    s/;}/}/g;
    # shorten variable names
    s/\bhang\b/a/g;
    s/\bbuffer\b/b/g;
    s/\bcolor\b/c/g;
    s/\bdesc\b/d/g;
    s/\bfields\b/f/g;
    s/\btarget\b(?!>)/g/g;
    s/\bheader\b/h/g;
    s/\bnocolor\b/m/g;
    s/\bpad\b/p/g;
    s/\bparts\b/q/g;
    s/\bstr\b/s/g;
    s/\btrim\b/t/g;
    s/\bspout\b/u/g;
    s/\bindent\b/y/g;
    # leftover corrections
    s/(printf?) /$1/g;
    s/ (tab) /$1/g;
    s/" y/"y/g;
    s/b \$/b\$/g;
    s/(BEGIN{[^{}]+;)b="";/$1/g;
    }
    '
  7. René Uittenbogaard revised this gist Oct 21, 2020. 1 changed file with 37 additions and 22 deletions.
    59 changes: 37 additions & 22 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -24,7 +24,7 @@

    .PHONY: help # See https://tinyurl.com/makefile-autohelp
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; hang = 2; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" (tab + hang) "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.55
    @awk -v tab=12 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; hang = 2; header(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (j in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[j]), nocolor, desc; } function header() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" (tab + hang) "s" indent, ""); gsub(/\\n/, pad); if ($$1 !~ /%/ || $$2 !~ /^%:/) { spout($$1, $$2); } else { n = split($$2, parts, /%:|:% */); for (i = 2; i < n; i += 2) { target = $$1; sub(/%/, parts[i], target); spout(target, parts[i + 1]); } } } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5); } END { print ""; } ' $(MAKEFILE_LIST) # v1.56

    ############################################################################
    #
    @@ -47,37 +47,44 @@ help: ## Print help for each target
    ##@ Heading text may \
    span multiple lines.

    ##@ Heading text may contain\n- newlines\n- by specifying them with\n- backslash-n\n
    ##@ Heading text may contain\n- newlines\n- by specifying these with\n- backslash-n\n

    # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    ##@ Examples of targets:

    double: prereq ## This will not be shown ## Sequential comments only show the latter

    newline: ## Comments may\ncontain newlines,\nentered as "backslash-n"

    target1 target2: ## Multiple targets will be split across lines

    show1: ## This is a description for show1, no prerequisites
    show1: ## Description for show1, no prerequisites

    show2: prereq1 prereq2 ## This is a description for show2, with compact prerequisites
    show2: prereq1 prereq2 ## Description for show2, with compact prerequisites

    show3: prereq1 \
    prereq2 ## This is a description for show3, with prerequisites spanning lines
    prereq2 ## Description for show3, with prerequisites spanning lines

    show4: ## This is a description for show4 \
    show4: ## Description for show4 \
    and its continuation, no prerequisites

    show5: prereq1 prereq2 ## This is a description for show5 \
    show5: prereq1 prereq2 ## Description for show5 \
    and its continuation, with compact prerequisites

    show6: prereq1 \
    prereq2 ## This is a description for show6 \
    prereq2 ## Description for show6 \
    and its continuation, with prerequisites spanning lines

    ##@ Nothing should be picked up from these lines:
    double: prereq ## This will not be shown ## Sequential comments only show the latter

    newline: ## Comments may\ncontain newlines,\nentered as "backslash-n"

    target1 target2: ## Multiple targets will be split across lines

    goal1 \
    goal2: ## Multiple targets spanning lines

    target-%: ## %:one:% Wildcard targets may be... %:two:% ...specified with individual descriptions

    copy-%: ## %:here:% Copy things hither %:there:% Copy things thither

    ##@ Nothing should be printed from the lines below:

    noshow1: # This is just any comment, which will not be parsed by 'make help'

    @@ -100,15 +107,15 @@ It will not be parsed by 'make help'.
    #
    # Readable version of code, with '$' replaced with makefile-style '$$', but no trailing backslashes:
    #
    # @awk -v tab=10 '
    # @awk -v tab=12 '
    # BEGIN {
    # FS = ":.*## ";
    # buffer = "";
    # color = "\033[36m";
    # nocolor = "\033[0m";
    # indent = " ";
    # hang = 2;
    # usage();
    # header();
    # }
    # function trim(str) {
    # gsub(/[ \t]+$$/, "", str);
    @@ -117,9 +124,9 @@ It will not be parsed by 'make help'.
    # }
    # function spout(target, desc) {
    # split(trim(target), fields, " ");
    # for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc;
    # for (j in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[j]), nocolor, desc;
    # }
    # function usage() {
    # function header() {
    # printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor;
    # }
    # /\\$$/ {
    @@ -134,7 +141,16 @@ It will not be parsed by 'make help'.
    # /^[-a-zA-Z0-9*/%_. ]+:.*## / {
    # pad = sprintf("\n%" (tab + hang) "s" indent, "");
    # gsub(/\\n/, pad);
    # spout($$1, $$2);
    # if ($$1 !~ /%/ || $$2 !~ /^%:/) {
    # spout($$1, $$2);
    # } else {
    # n = split($$2, parts, /%:|:% */);
    # for (i = 2; i < n; i += 2) {
    # target = $$1;
    # sub(/%/, parts[i], target);
    # spout(target, parts[i + 1]);
    # }
    # }
    # }
    # /^##@ / {
    # gsub(/\\n/, "\n");
    @@ -143,7 +159,6 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.55
    # ' $(MAKEFILE_LIST) # v1.56
    #


  8. René Uittenbogaard revised this gist Oct 19, 2020. 1 changed file with 4 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -24,7 +24,7 @@

    .PHONY: help # See https://tinyurl.com/makefile-autohelp
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.54
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; hang = 2; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" (tab + hang) "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.55

    ############################################################################
    #
    @@ -107,6 +107,7 @@ It will not be parsed by 'make help'.
    # color = "\033[36m";
    # nocolor = "\033[0m";
    # indent = " ";
    # hang = 2;
    # usage();
    # }
    # function trim(str) {
    @@ -131,7 +132,7 @@ It will not be parsed by 'make help'.
    # buffer = "";
    # }
    # /^[-a-zA-Z0-9*/%_. ]+:.*## / {
    # pad = sprintf("\n%" tab "s" indent, "");
    # pad = sprintf("\n%" (tab + hang) "s" indent, "");
    # gsub(/\\n/, pad);
    # spout($$1, $$2);
    # }
    @@ -142,7 +143,7 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.54
    # ' $(MAKEFILE_LIST) # v1.55
    #


  9. René Uittenbogaard revised this gist Sep 27, 2019. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion Makefile
    Original file line number Diff line number Diff line change
    @@ -16,7 +16,9 @@

    ############################################################################
    #
    # INSTALLATION: copy this block over to your own Makefile:
    # INSTALLATION
    #
    # Copy this block over to your own Makefile:

    .DEFAULT_GOAL:=help

  10. René Uittenbogaard revised this gist Sep 27, 2019. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion Makefile
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,10 @@
    # This code adds a 'help' target to your Makefile, that automatically
    # creates a table of your Makefile's targets and short descriptions.
    #
    # Installation: copy this block over to your own Makefile:

    ############################################################################
    #
    # INSTALLATION: copy this block over to your own Makefile:

    .DEFAULT_GOAL:=help

  11. René Uittenbogaard revised this gist Sep 27, 2019. 1 changed file with 78 additions and 64 deletions.
    142 changes: 78 additions & 64 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -1,29 +1,99 @@

    ############################################################################
    #
    # makefile-autohelp
    #
    # This file is at : https://tinyurl.com/makefile-autohelp
    # also known as : https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1

    ############################################################################
    #
    # DESCRIPTION
    #
    # This code adds a 'help' target to your Makefile, that automatically
    # creates a table of your Makefile's targets and short descriptions.
    #
    # Installation: copy this block over to your own Makefile:

    .DEFAULT_GOAL:=help

    .PHONY: help # See https://tinyurl.com/makefile-autohelp
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.54

    ############################################################################
    #
    # This code automatically creates a table of Makefile targets and short descriptions.
    # Descriptions should be added in the Makefile itself:
    # USAGE
    #
    # The awk option '-v tab=10' can be changed to change the indentation of the output.
    #
    # Descriptions for each target should be added in the Makefile itself:
    #
    # '##' after a target is used for target descriptions
    # '##@' at the start of a line is used for header lines.

    ############################################################################
    #
    # See the examples below.
    #
    # The awk option '-v tab=10' can be changed to indent the second column of the output.
    # EXAMPLES
    #

    ##@ This is heading text, which is shown on a separate line.

    ##@ Heading text may be \
    extended across lines.
    ##@ Heading text may \
    span multiple lines.

    ##@ Heading text may contain\n- newlines\n- by specifying them with\n- backslash-n\n

    # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    ##@ Examples of targets:

    double: prereq ## This will not be shown ## Sequential comments only show the latter

    newline: ## Comments may\ncontain newlines,\nentered as "backslash-n"

    target1 target2: ## Multiple targets will be split across lines

    show1: ## This is a description for show1, no prerequisites

    show2: prereq1 prereq2 ## This is a description for show2, with compact prerequisites

    show3: prereq1 \
    prereq2 ## This is a description for show3, with prerequisites spanning lines

    show4: ## This is a description for show4 \
    and its continuation, no prerequisites

    show5: prereq1 prereq2 ## This is a description for show5 \
    and its continuation, with compact prerequisites

    show6: prereq1 \
    prereq2 ## This is a description for show6 \
    and its continuation, with prerequisites spanning lines

    ##@ Nothing should be picked up from these lines:

    noshow1: # This is just any comment, which will not be parsed by 'make help'

    noshow2: prereq1 prereq2 # This is just any comment, which will not be parsed by 'make help'

    noshow3: prereq1 \
    prereq2 # This is just any comment, which will not be parsed by 'make help'

    noshow4: # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    noshow5: prereq1 prereq2 # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    noshow6: prereq1 \
    prereq2 # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    ############################################################################
    #
    # Readable version, with '$' replaced with makefile-style '$$':
    # Readable version of code, with '$' replaced with makefile-style '$$', but no trailing backslashes:
    #
    # @awk -v tab=10 '
    # BEGIN {
    @@ -68,62 +138,6 @@ It will not be parsed by 'make help'.
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.54

    ############################################################################
    #
    # Concise version. Copy this block over to your own Makefile:

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.54

    ############################################################################
    #
    ##@ Example targets:

    double: prereq ## This will not be shown ## Sequential comments only show the latter

    newline: ## Comments may\ncontain newlines,\nentered as "backslash-n"

    target1 target2: ## Multiple targets will be split across lines

    show1: ## This is a description for show1, no prerequisites

    show2: prereq1 prereq2 ## This is a description for show2, with compact prerequisites

    show3: prereq1 \
    prereq2 ## This is a description for show3, with continuation prerequisites

    show4: ## This is a description for show4 \
    and its continuation, no prerequisites

    show5: prereq1 prereq2 ## This is a description for show5 \
    and its continuation, with compact prerequisites

    show6: prereq1 \
    prereq2 ## This is a description for show6 \
    and its continuation, with continuation prerequisites

    ##@ None of these should be printed:

    noshow1: # This is just any comment, which will not be parsed by 'make help'

    noshow2: prereq1 prereq2 # This is just any comment, which will not be parsed by 'make help'

    noshow3: prereq1 \
    prereq2 # This is just any comment, which will not be parsed by 'make help'

    noshow4: # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    noshow5: prereq1 prereq2 # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    noshow6: prereq1 \
    prereq2 # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.


    # Makefile directives
    .DEFAULT_GOAL:=help

  12. René Uittenbogaard revised this gist Aug 27, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Makefile
    Original file line number Diff line number Diff line change
    @@ -67,7 +67,7 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.53
    # ' $(MAKEFILE_LIST) # v1.54

    ############################################################################
    #
  13. René Uittenbogaard revised this gist Aug 27, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Makefile
    Original file line number Diff line number Diff line change
    @@ -75,7 +75,7 @@ It will not be parsed by 'make help'.

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.54
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.54

    ############################################################################
    #
  14. René Uittenbogaard revised this gist Aug 27, 2019. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -55,7 +55,7 @@ It will not be parsed by 'make help'.
    # $$0 = buffer $$0;
    # buffer = "";
    # }
    # /^[-a-zA-Z0-9*%_. ]+:.*## / {
    # /^[-a-zA-Z0-9*/%_. ]+:.*## / {
    # pad = sprintf("\n%" tab "s" indent, "");
    # gsub(/\\n/, pad);
    # spout($$1, $$2);
    @@ -75,7 +75,7 @@ It will not be parsed by 'make help'.

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.53
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*/%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.54

    ############################################################################
    #
  15. René Uittenbogaard revised this gist May 17, 2019. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -35,9 +35,9 @@ It will not be parsed by 'make help'.
    # usage();
    # }
    # function trim(str) {
    # gsub(/[ \t]+$$/, "", str);
    # gsub(/^[ \t]+/, "", str);
    # return str;
    # gsub(/[ \t]+$$/, "", str);
    # gsub(/^[ \t]+/, "", str);
    # return str;
    # }
    # function spout(target, desc) {
    # split(trim(target), fields, " ");
  16. René Uittenbogaard revised this gist May 17, 2019. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -85,6 +85,8 @@ double: prereq ## This will not be shown ## Sequential comments only show the la

    newline: ## Comments may\ncontain newlines,\nentered as "backslash-n"

    target1 target2: ## Multiple targets will be split across lines

    show1: ## This is a description for show1, no prerequisites

    show2: prereq1 prereq2 ## This is a description for show2, with compact prerequisites
  17. René Uittenbogaard revised this gist May 17, 2019. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -40,7 +40,8 @@ It will not be parsed by 'make help'.
    # return str;
    # }
    # function spout(target, desc) {
    # printf "%s%s%-" tab "s%s%s\n", indent, color, trim(target), nocolor, desc;
    # split(trim(target), fields, " ");
    # for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc;
    # }
    # function usage() {
    # printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor;
    @@ -66,16 +67,15 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.52
    # ' $(MAKEFILE_LIST) # v1.53

    ############################################################################
    #
    # Concise version. Copy this block over to your own Makefile:

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, trim(target), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.52

    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { split(trim(target), fields, " "); for (i in fields) printf "%s%s%-" tab "s%s%s\n", indent, color, trim(fields[i]), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.53

    ############################################################################
    #
  18. René Uittenbogaard revised this gist May 17, 2019. No changes.
  19. René Uittenbogaard revised this gist May 17, 2019. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -83,6 +83,8 @@ help: ## Print help for each target

    double: prereq ## This will not be shown ## Sequential comments only show the latter

    newline: ## Comments may\ncontain newlines,\nentered as "backslash-n"

    show1: ## This is a description for show1, no prerequisites

    show2: prereq1 prereq2 ## This is a description for show2, with compact prerequisites
  20. René Uittenbogaard revised this gist May 15, 2019. 1 changed file with 5 additions and 3 deletions.
    8 changes: 5 additions & 3 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -54,7 +54,7 @@ It will not be parsed by 'make help'.
    # $$0 = buffer $$0;
    # buffer = "";
    # }
    # /^[-a-zA-Z0-9*%_. ]+:.*?## / {
    # /^[-a-zA-Z0-9*%_. ]+:.*## / {
    # pad = sprintf("\n%" tab "s" indent, "");
    # gsub(/\\n/, pad);
    # spout($$1, $$2);
    @@ -66,21 +66,23 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.51
    # ' $(MAKEFILE_LIST) # v1.52

    ############################################################################
    #
    # Concise version. Copy this block over to your own Makefile:

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, trim(target), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*?## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.51
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, trim(target), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.52


    ############################################################################
    #
    ##@ Example targets:

    double: prereq ## This will not be shown ## Sequential comments only show the latter

    show1: ## This is a description for show1, no prerequisites

    show2: prereq1 prereq2 ## This is a description for show2, with compact prerequisites
  21. René Uittenbogaard revised this gist May 9, 2019. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion Makefile
    Original file line number Diff line number Diff line change
    @@ -74,7 +74,6 @@ It will not be parsed by 'make help'.

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target

    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, trim(target), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*?## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.51


  22. René Uittenbogaard revised this gist May 3, 2019. 1 changed file with 9 additions and 4 deletions.
    13 changes: 9 additions & 4 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -34,9 +34,13 @@ It will not be parsed by 'make help'.
    # indent = " ";
    # usage();
    # }
    # function trim(str) {
    # gsub(/[ \t]+$$/, "", str);
    # gsub(/^[ \t]+/, "", str);
    # return str;
    # }
    # function spout(target, desc) {
    # gsub(/[ \t]+$$/, "", target);
    # printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc;
    # printf "%s%s%-" tab "s%s%s\n", indent, color, trim(target), nocolor, desc;
    # }
    # function usage() {
    # printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor;
    @@ -62,15 +66,16 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.50
    # ' $(MAKEFILE_LIST) # v1.51

    ############################################################################
    #
    # Concise version. Copy this block over to your own Makefile:

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { gsub(/[ \t]+$$/, "", target); printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*?## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.50

    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function trim(str) { gsub(/[ \t]+$$/, "", str); gsub(/^[ \t]+/, "", str); return str; } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, trim(target), nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*?## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.51


    ############################################################################
  23. René Uittenbogaard revised this gist May 3, 2019. 1 changed file with 4 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -35,7 +35,8 @@ It will not be parsed by 'make help'.
    # usage();
    # }
    # function spout(target, desc) {
    # printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc;
    # gsub(/[ \t]+$$/, "", target);
    # printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc;
    # }
    # function usage() {
    # printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor;
    @@ -61,15 +62,15 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.49
    # ' $(MAKEFILE_LIST) # v1.50

    ############################################################################
    #
    # Concise version. Copy this block over to your own Makefile:

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*?## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.49
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { gsub(/[ \t]+$$/, "", target); printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*?## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.50


    ############################################################################
  24. René Uittenbogaard revised this gist May 3, 2019. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -49,7 +49,7 @@ It will not be parsed by 'make help'.
    # $$0 = buffer $$0;
    # buffer = "";
    # }
    # /^[a-zA-Z0-9*%_.-]+:.*?## / {
    # /^[-a-zA-Z0-9*%_. ]+:.*?## / {
    # pad = sprintf("\n%" tab "s" indent, "");
    # gsub(/\\n/, pad);
    # spout($$1, $$2);
    @@ -61,15 +61,15 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.48
    # ' $(MAKEFILE_LIST) # v1.49

    ############################################################################
    #
    # Concise version. Copy this block over to your own Makefile:

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.48
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[-a-zA-Z0-9*%_. ]+:.*?## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.49


    ############################################################################
  25. René Uittenbogaard revised this gist Apr 26, 2019. 1 changed file with 20 additions and 7 deletions.
    27 changes: 20 additions & 7 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,15 @@
    ############################################################################
    #
    # This code automatically creates a table of Makefile targets and short descriptions.
    # Descriptions should be added in the Makefile itself, using '##' after the target.
    # Also '##@' lines are supported:
    # Descriptions should be added in the Makefile itself:
    #
    # '##' after a target is used for target descriptions
    # '##@' at the start of a line is used for header lines.
    #
    # See the examples below.
    #
    # The awk option '-v tab=10' can be changed to indent the second column of the output.
    #

    ##@ This is heading text, which is shown on a separate line.

    @@ -12,8 +21,8 @@ extended across lines.
    # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    # The awk option '-v tab=10' can be changed to indent the second column of the output.

    ############################################################################
    #
    # Readable version, with '$' replaced with makefile-style '$$':
    #
    # @awk -v tab=10 '
    @@ -41,7 +50,7 @@ It will not be parsed by 'make help'.
    # buffer = "";
    # }
    # /^[a-zA-Z0-9*%_.-]+:.*?## / {
    # pad = sprintf("\n%" tab "s" indent, "", $$2);
    # pad = sprintf("\n%" tab "s" indent, "");
    # gsub(/\\n/, pad);
    # spout($$1, $$2);
    # }
    @@ -52,15 +61,19 @@ It will not be parsed by 'make help'.
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.47
    # ' $(MAKEFILE_LIST) # v1.48

    ############################################################################
    #
    # Concise version. Copy this block over to your own Makefile:

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.47
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, ""); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.48


    ############################################################################
    #
    ##@ Example targets:

    show1: ## This is a description for show1, no prerequisites
  26. René Uittenbogaard revised this gist Apr 26, 2019. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@ It will not be parsed by 'make help'.

    # The awk option '-v tab=10' can be changed to indent the second column of the output.

    # readable version, with makefile-style '$$':
    # Readable version, with '$' replaced with makefile-style '$$':
    #
    # @awk -v tab=10 '
    # BEGIN {
    @@ -54,7 +54,7 @@ It will not be parsed by 'make help'.
    # }
    # ' $(MAKEFILE_LIST) # v1.47

    # concise version:
    # Concise version. Copy this block over to your own Makefile:

    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
  27. René Uittenbogaard revised this gist Apr 26, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Makefile
    Original file line number Diff line number Diff line change
    @@ -56,7 +56,7 @@ It will not be parsed by 'make help'.

    # concise version:

    .PHONY: help # https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    .PHONY: help # See https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.47

  28. René Uittenbogaard revised this gist Apr 25, 2019. 1 changed file with 5 additions and 2 deletions.
    7 changes: 5 additions & 2 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,8 @@ It will not be parsed by 'make help'.

    # The awk option '-v tab=10' can be changed to indent the second column of the output.

    # readable version:
    # readable version, with makefile-style '$$':
    #
    # @awk -v tab=10 '
    # BEGIN {
    # FS = ":.*## ";
    @@ -54,7 +55,8 @@ It will not be parsed by 'make help'.
    # ' $(MAKEFILE_LIST) # v1.47

    # concise version:
    .PHONY: help

    .PHONY: help # https://gist.github.com/ruittenb/5d2d281237385276f49652b9b9f6d5a1
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.47

    @@ -100,3 +102,4 @@ It will not be parsed by 'make help'.

    # Makefile directives
    .DEFAULT_GOAL:=help

  29. René Uittenbogaard revised this gist Apr 25, 2019. 1 changed file with 91 additions and 21 deletions.
    112 changes: 91 additions & 21 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -1,32 +1,102 @@
    # This code automatically creates a table of Makefile targets and short descriptions.
    # Descriptions should be added in the Makefile itself, as a '##' comment after the target:
    # Descriptions should be added in the Makefile itself, using '##' after the target.
    # Also '##@' lines are supported:

    ##@ This is heading text, which will show up as a header
    ##@ This is heading text, which is shown on a separate line.

    target1: prereq1 prereq2 ## This is comment text describing target1
    ##@ Heading text may be \
    extended across lines.

    target2: prereq1 \
    prereq2 ## This is comment text describing target2
    ##@ Heading text may contain\n- newlines\n- by specifying them with\n- backslash-n\n

    # The awk option '-v tab=10' can be changed to indent the second column of the output.
    # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    # The awk option '-v tab=10' can be changed to indent the second column of the output.

    # readable version:
    help2: ## print help for each target
    @awk -v tab=10 ' \
    function spout(target, comment) { printf indent color "%-" tab "s\033[0m%s\n", target, comment } \
    function usage() { printf "\nUsage:\n make " color "<target>\033[0m\n\nRecognized targets:\n" } \
    BEGIN { FS = fieldsep = ":.*## "; target = ""; color = "\033[36m"; indent = " "; usage() } \
    /^[a-zA-Z0-9*%_.-]+:.*\\$$/ { gsub(/:.*/, ""); target = $$0; FS="## "; next } \
    target && /\\$$/ { next } \
    target && /## / { spout(target, $$2); FS = fieldsep; target = "" } \
    /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2) } \
    /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } \
    END { print "" } \
    ' $(MAKEFILE_LIST) # v1.44
    # @awk -v tab=10 '
    # BEGIN {
    # FS = ":.*## ";
    # buffer = "";
    # color = "\033[36m";
    # nocolor = "\033[0m";
    # indent = " ";
    # usage();
    # }
    # function spout(target, desc) {
    # printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc;
    # }
    # function usage() {
    # printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor;
    # }
    # /\\$$/ {
    # gsub(/\\$$/, "");
    # buffer = buffer $$0;
    # next;
    # }
    # buffer {
    # $$0 = buffer $$0;
    # buffer = "";
    # }
    # /^[a-zA-Z0-9*%_.-]+:.*?## / {
    # pad = sprintf("\n%" tab "s" indent, "", $$2);
    # gsub(/\\n/, pad);
    # spout($$1, $$2);
    # }
    # /^##@ / {
    # gsub(/\\n/, "\n");
    # printf "\n%s\n", substr($$0, 5);
    # }
    # END {
    # print "";
    # }
    # ' $(MAKEFILE_LIST) # v1.47

    # concise version:
    .PHONY: help
    help: ## print help for each target
    @awk -v tab=10 'function spout(target, comment) { printf indent color "%-" tab "s\033[0m%s\n", target, comment } function usage() { printf "\nUsage:\n make " color "<target>\033[0m\n\nRecognized targets:\n" } BEGIN { FS = fieldsep = ":.*## "; cont = ""; color = "\033[36m"; indent = " "; usage() } /^[a-zA-Z0-9*%_.-]+:.*\\$$/ { gsub(/:.*/, ""); cont = $$0; FS="## "; next } cont && /\\$$/ { next } cont && /## / { spout(cont, $$2); FS = fieldsep; cont = "" } /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2) } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.44
    help: ## Print help for each target
    @awk -v tab=10 'BEGIN { FS = ":.*## "; buffer = ""; color = "\033[36m"; nocolor = "\033[0m"; indent = " "; usage(); } function spout(target, desc) { printf "%s%s%-" tab "s%s%s\n", indent, color, target, nocolor, desc; } function usage() { printf "\nUsage:\n%smake %s<target>%s\n\nRecognized targets:\n", indent, color, nocolor; } /\\$$/ { gsub(/\\$$/, ""); buffer = buffer $$0; next; } buffer { $$0 = buffer $$0; buffer = ""; } /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2); } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.47


    ##@ Example targets:

    show1: ## This is a description for show1, no prerequisites

    show2: prereq1 prereq2 ## This is a description for show2, with compact prerequisites

    show3: prereq1 \
    prereq2 ## This is a description for show3, with continuation prerequisites

    show4: ## This is a description for show4 \
    and its continuation, no prerequisites

    show5: prereq1 prereq2 ## This is a description for show5 \
    and its continuation, with compact prerequisites

    show6: prereq1 \
    prereq2 ## This is a description for show6 \
    and its continuation, with continuation prerequisites

    ##@ None of these should be printed:

    noshow1: # This is just any comment, which will not be parsed by 'make help'

    noshow2: prereq1 prereq2 # This is just any comment, which will not be parsed by 'make help'

    noshow3: prereq1 \
    prereq2 # This is just any comment, which will not be parsed by 'make help'

    noshow4: # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    noshow5: prereq1 prereq2 # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.

    noshow6: prereq1 \
    prereq2 # This is just any comment and its continuation. \
    It will not be parsed by 'make help'.


    .DEFAULT_GOAL:=help
    # Makefile directives
    .DEFAULT_GOAL:=help
  30. René Uittenbogaard revised this gist Apr 17, 2019. 1 changed file with 16 additions and 16 deletions.
    32 changes: 16 additions & 16 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -6,27 +6,27 @@
    target1: prereq1 prereq2 ## This is comment text describing target1

    target2: prereq1 \
    prereq2 ## This is comment text describing target2
    prereq2 ## This is comment text describing target2

    # The awk option '-v tab=10' can be changed to indent the second column of the output.

    # readable version:
    .PHONY: help
    help: ## print help for each target
    @awk -v tab=10 ' \
    function spout(target, comment) { printf indent color "%-" tab "s\033[0m%s\n", target, comment } \
    function usage() { printf "\nUsage:\n make " color "<target>\033[0m\n\nRecognized targets:\n" } \
    BEGIN { FS = fieldsep = ":.*## "; target = ""; color = "\033[36m"; indent = " "; usage() } \
    /^[a-zA-Z0-9*%_.-]+:.*\\$$/ { gsub(/:.*/, ""); target = $$0; FS="## "; next } \
    target && /\\$$/ { next } \
    target && /## / { spout(target, $$2); FS = fieldsep; target = "" } \
    /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2) } \
    /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } \
    END { print "" } \
    ' $(MAKEFILE_LIST) # v1.44
    help2: ## print help for each target
    @awk -v tab=10 ' \
    function spout(target, comment) { printf indent color "%-" tab "s\033[0m%s\n", target, comment } \
    function usage() { printf "\nUsage:\n make " color "<target>\033[0m\n\nRecognized targets:\n" } \
    BEGIN { FS = fieldsep = ":.*## "; target = ""; color = "\033[36m"; indent = " "; usage() } \
    /^[a-zA-Z0-9*%_.-]+:.*\\$$/ { gsub(/:.*/, ""); target = $$0; FS="## "; next } \
    target && /\\$$/ { next } \
    target && /## / { spout(target, $$2); FS = fieldsep; target = "" } \
    /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2) } \
    /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } \
    END { print "" } \
    ' $(MAKEFILE_LIST) # v1.44

    # concise version:
    .PHONY: help
    help: ## print help for each target
    @awk -v tab=10 'function spout(target, comment) { printf indent color "%-" tab "s\033[0m%s\n", target, comment } function usage() { printf "\nUsage:\n make " color "<target>\033[0m\n\nRecognized targets:\n" } BEGIN { FS = fieldsep = ":.*## "; cont = ""; color = "\033[36m"; indent = " "; usage() } /^[a-zA-Z0-9*%_.-]+:.*\\$$/ { gsub(/:.*/, ""); cont = $$0; FS="## "; next } cont && /\\$$/ { next } cont && /## / { spout(cont, $$2); FS = fieldsep; cont = "" } /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2) } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.44
    @awk -v tab=10 'function spout(target, comment) { printf indent color "%-" tab "s\033[0m%s\n", target, comment } function usage() { printf "\nUsage:\n make " color "<target>\033[0m\n\nRecognized targets:\n" } BEGIN { FS = fieldsep = ":.*## "; cont = ""; color = "\033[36m"; indent = " "; usage() } /^[a-zA-Z0-9*%_.-]+:.*\\$$/ { gsub(/:.*/, ""); cont = $$0; FS="## "; next } cont && /\\$$/ { next } cont && /## / { spout(cont, $$2); FS = fieldsep; cont = "" } /^[a-zA-Z0-9*%_.-]+:.*?## / { pad = sprintf("\n%" tab "s" indent, "", $$2); gsub(/\\n/, pad); spout($$1, $$2) } /^##@ / { gsub(/\\n/, "\n"); printf "\n%s\n", substr($$0, 5) } END { print "" }' $(MAKEFILE_LIST) # v1.44

    .DEFAULT_GOAL:=help
    .DEFAULT_GOAL:=help