Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
#######
#
# E-scripts on Make.
#
# Note 1: use the eev command (defined in eev.el) and the
# ee alias (in my .zshrc) to execute parts of this file.
# Executing this file as a whole makes no sense.
# An introduction to eev can be found here:
#
#   (find-eev-quick-intro)
#   http://angg.twu.net/eev-intros/find-eev-quick-intro.html
#
# Note 2: be VERY careful and make sure you understand what
# you're doing.
#
# Note 3: If you use a shell other than zsh things like |&
# and the for loops may not work.
#
# Note 4: I always run as root.
#
# Note 5: some parts are too old and don't work anymore. Some
# never worked.
#
# Note 6: the definitions for the find-xxxfile commands are on my
# .emacs.
#
# Note 7: if you see a strange command check my .zshrc -- it may
# be defined there as a function or an alias.
#
# Note 8: the sections without dates are always older than the
# sections with dates.
#
# This file is at <http://angg.twu.net/e/make.e>
#           or at <http://angg.twu.net/e/make.e.html>.
#        See also <http://angg.twu.net/emacs.html>,
#                 <http://angg.twu.net/.emacs[.html]>,
#                 <http://angg.twu.net/.zshrc[.html]>,
#                 <http://angg.twu.net/escripts.html>,
#             and <http://angg.twu.net/>.
#
#######




# «.debian»			(to "debian")
# «.page»			(to "page")
# «.environment»		(to "environment")
# «.shell_functions»		(to "shell_functions")
# «.call_function»		(to "call_function")
# «.intermediate_files»		(to "intermediate_files")
# «.makefile_toposort»		(to "makefile_toposort")
# «.makefile_addtrace»		(to "makefile_addtrace")
# «.cp-av-and-touch»		(to "cp-av-and-touch")
# «.phony-targets»		(to "phony-targets")
# «.remake»			(to "remake")
# «.lua-support»		(to "lua-support")
# «.tup»			(to "tup")
# «.clean»			(to "clean")
# «.cmake»			(to "cmake")
# «.managing-projects-with»	(to "managing-projects-with")
# «.patsubst»			(to "patsubst")
# «.functions»			(to "functions")
# «.variables»			(to "variables")
# «.showvar»			(to "showvar")
# «.graph-output»		(to "graph-output")
# «.ignoring-errors»		(to "ignoring-errors")





#####
#
# debian
# 2019mar02
#
#####

# «debian» (to ".debian")
# (find-zsh "installeddebs | sort | grep make")
# (find-zsh "availabledebs | sort | grep make")
# (find-status   "make")
# (find-vldifile "make.list")
# (find-udfile   "make/")
# (find-status   "make-doc")
# (find-vldifile "make-doc.list")
# (find-udfile   "make-doc/")
# (find-udfile "make-doc/make.html/" " index.html")
# (find-fline "/usr/share/doc/make-doc/make.html/" " index.html")
# file:///usr/share/doc/make-doc/make.html/index.html

# (find-udfile "make/AUTHORS")
# (find-udfile "make/Explanations.gz")
# (find-udfile "make/NEWS.Debian.gz")
# (find-udfile "make/NEWS.gz")
# (find-udfile "make/README.Debian-Source")
# (find-udfile "make/README.customs.gz")
# (find-udfile "make/README.gz")
# (find-udfile "make/changelog.Debian.gz")
# (find-udfile "make/copyright")
# (find-man "1 make-first-existing-target")
# (find-man "1 make")
# (find-fline "/usr/bin/make-first-existing-target")
# (find-fline "/usr/bin/make")
# (find-fline "/usr/include/gnumake.h")







#####
#
# rewriting my page's makefiles
# 2000jun22
#
#####

# «page»  (to ".page")

# (find-fline "~/TH/" "Makefile")
# (find-fline "~/TH/Makefile")
# (find-fline "~/TH/Makefile.auto")
# (find-fline "~/TH/Makefile.th")
# (find-fline "~/TH/Makefile0")

# (find-node "(make)Conditional Example")
# (find-node "(make)Conditional Syntax")
# (find-node "(make)Recursion")
# (find-node "(make)Environment")
# (find-node "(make)Variables/Recursion")

# (find-node "(make)Concept Index" ":=")
# (find-node "(make)Flavors")
# (find-node "(make)Flavors" "simply expanded variables")
# (find-node "(make)Flavors" "?=")
# (find-node "(make)Origin Function")

# (find-node "(make)Setting")
# (find-node "(make)Running")

# Is there some way to call Make with "inner targets" that are all
# passed to child Makes?

# (find-node "(make)Using Variables")

# (find-node "(make)Goals")
# (find-node "(make)Goals" "MAKECMDGOALS")
# (find-node "(make)Quick Reference" "MAKECMDGOALS")


#*
make -f - <<'---'
test:
	@echo $(SUFFIXES)
---

#*
echo 'test:\n\t@echo $(SUFFIXES)' | make -f -

#*
function showmakevar () {
  echo "test:\n\t@echo \$($1)" | make -f - $*[2,-1]
}
showmakevar SUFFIXES
showmakevar CFLAGS
showmakevar LDFLAGS

#*




#####
#
# searching the Make info docs
# 2000jun22
#
#####

# (find-status "make")
# (find-vldifile "make.list")
# (find-fline "/usr/doc/make/")

# (find-angg ".zshrc" "zcatinfo")
zcatinfo /usr/share/info/make > /tmp/make.info
# (find-fline "/tmp/make.info")

# Old:

rm -Rv ~/tmp/make/
mkdir  ~/tmp/make/
cd     ~/tmp/make/
cp -v /usr/share/info/make.info* .
gzip -dv *

# (find-fline "~/tmp/make/")





#####
#
# Difference between make XXX=yyy and XXX=yyy make
# 2000sep07
#
#####

# «environment»  (to ".environment")
# (find-node "(make)Overriding")
# (find-node "(make)Options Summary" "--environment-overrides")
# (find-node "(make)Environment")
# (find-node "(make)Environment" "variable `SHELL'")
# (find-node "(make)Setting" "FOO ?= bar")
# (find-node "(make)Variables/Recursion" "`export'")
# (find-node "(make)Origin Function")

# More explanations for the
# "XXX=yyy command" syntax:
#
# (find-node "(bash)Simple Command Expansion" "variable assignments")
# (find-node "(bash)Simple Command Expansion" "If no command name results")

#*
echo $FOO
make -f - <<'---'
FOO="not overriden"
test:
	# FOO is $(FOO)
---

make -f - FOO=parameter <<'---'
FOO="not overriden"
test:
	# FOO is $(FOO)
---

FOO=environment make -f - <<'---'
FOO=not overriden
test:
	# FOO is $(FOO)
---

#*
# Obs: ":=" seems to work identically to "=" in this respect.






#####
#
# Intermediate files
# 2000sep18
#
#####

# «intermediate_files»  (to ".intermediate_files")
# (find-node "(make)Chained Rules" ".INTERMEDIATE")
# (find-node "(make)Automatic" "$^")
# (find-angg "LATEX/Makefile" "edrxnotes")
#*

rm -Rv /tmp/make/
mkdir  /tmp/make/
cd     /tmp/make/
cat > Makefile <<'---'

%.auto.dnt:
	date > $@
%.tex:
	date > $@
%.dvi: %.tex
	echo $^ > $@

.INTERMEDIATE: 00apr10.auto.dnt 00apr29.auto.dnt

00apr10.dvi: 00apr10.tex 00apr10.auto.dnt
00apr29.dvi: 00apr29.tex 00apr29.auto.dnt
00feb24.dvi: 00feb24.tex 00feb24.auto.dnt
00feb25.dvi: 00feb25.tex
00jan03.dvi: 00jan03.tex
---
make 00apr10.dvi 00apr29.dvi 00feb24.dvi 00feb25.dvi 00jan03.dvi
#*





#####
#
# Defining make functions that call the shell
# 2000sep18
#
#####

# «shell_functions»  (to ".shell_functions")
#*
# (find-angg ".zshrc" "TeX")
cd ~/LATEX/
dvitype -output-level=1 feb98.dvi \
  | grep PSfile \
  | perl -nle 'print m/"(.*)"/' \
  | sort | uniq
#*

# (find-node "(make)Text Functions")
# (find-node "(make)Shell Function")

# «call_function»  (to ".call_function")
# (find-node "(make)Call Function" "reverse = $(2) $(1)")
# (find-fline "/usr/doc/make/NEWS.gz" "$(call ...)")

# Big oops: $(call ...) was introduced in make 3.78 and one of the
# mirrors of my page is based on RedHat 6.1, that has only make 3.77;
# so my portable makefiles will have to avoid using $(call ...) for
# this moment.

#*
cat > /tmp/Makefile <<'---'
listepsfiles =				\
  $(shell dvitype -output-level=1 $(1)	\
	| grep PSfile			\
	| perl -nle 'print m/"(.*)"/'	\
	| sort | uniq)
demo:
	echo $(call listepsfiles, feb98.dvi)			> /dev/null
%-dvi.tgz:
	echo tar -cvzf $@ $*.dvi $(call listepsfiles, $*.dvi)	> /dev/null
---
cd ~/LATEX/
make -f /tmp/Makefile
make -f /tmp/Makefile feb98-dvi.tgz
#*



$(patsubst PATTERN,REPLACEMENT,TEXT)'





#####
#
# topological sort on makefiles
# 2000dec26
#
#####

# «makefile_toposort»  (to ".makefile_toposort")
# (find-es "kernel" "make-kpkg_rules")
# (find-es "lua" "toposort")
# (find-es "perl" "reading_a_file_at_once")
#*
cat /usr/share/kernel-package/rules \
  | perl -e 'undef $/; $_ = <>; s/\\\n//g; print' \
  | tee ~/o \
  | perl -nle 'if (m/^[^\t][^#:=]*:([^=]|$)/) { print }' \
  | tee ~/o2 \
  | lua ~/LUA/toposort.lua
# (find-fline "~/o" "debian:")
# (find-fline "~/o2" "debian:")
#*
cat /usr/share/kernel-package/rules \
  | perl -e 'undef $/; $_ = <>; s/\\\n//g; print' \
  | perl -nle 'if (m/^[^\t][^#:=]*:([^=]|$)/) { print }' \
  | tee ~/o2 \
  | lua ~/LUA/toposort.lua
#*
# (find-angg ".zshrc" "make")
cat /usr/share/kernel-package/rules \
  | makefile_getdeps \
  | lua ~/LUA/toposort.lua
#*




#####
#
# Adding "trace" lines to makefiles
# 2000dec26
#
#####

# «makefile_addtrace»  (to ".makefile_addtrace")
# (find-angg ".zshrc" "make")
# (find-node "(make)Automatic")
# (find-es "kernel" "make-kpkg_rules")
#*
cat /usr/share/kernel-package/rules \
  | perl -e 'undef $/; $_ = <>; s/\\\n//g; print' \
  | perl -nle '
      print;
      if ( m/^[^\t][^#:=]*:([^=]|$)/ ) {
	$n++; printf "\t# Dbg %d/%d  \$\@: \$^\n", $n, $n+$.
      };
    ' \
  | l +/Dbg
#*
cat /usr/share/kernel-package/rules \
  | makefile_addtrace \
  | l +/Dbg
#*




#####
#
# pmake (the BSD make) on Debian
# 2001jul24
#
#####

# (find-status "pmake")
# (find-vldifile "pmake.list")
# (find-fline "/usr/doc/pmake/")
gv /usr/doc/pmake/tutorial.ps.gz &

zcat /usr/doc/pmake/tutorial.asc.gz \
  | l '+/2.7.  Invoking PMake' 

#*
# (find-fline "/usr/share/mk/")
# (find-fline "/freebsd/usr/share/mk/")
cd /usr/share/mk/; ls | tee /tmp/olusm
cd /freebsd/usr/share/mk/; ls | tee /tmp/olfusm
diff /tmp/olusm /tmp/olfusm

#*
rm -Rv /tmp/psd/
cd /netbsd/usr/share/doc/
cp -diPpvR psd /tmp/
cd /tmp/psd/
#*
# (find-es "bsd" "ports")
# (find-fline "/freebsd/usr/ports/lang/tcl82/")
# (find-fline "/freebsd/usr/share/mk/bsd.port.mk")
# (find-fline "/freebsd/usr/ports/Mk/bsd.port.mk")
# (find-fline "/freebsd/usr/ports/Mk/bsd.port.mk" "\nSED?=")

rm -Rv /tmp/ports/
cd /freebsd/usr/
cp -diPpvR ports/lang/tcl82/ /tmp/
cd /tmp/ports/lang/tcl82/
pmake	|& tee opm1

cd /tmp/ports/lang/tcl82/
cp -v /freebsd/usr/ports/Mk/bsd.port* .
cp -v /freebsd/usr/ports/Mk/bsd.sites* .
pmake -I `pwd` \
  -d j \
  SED=/bin/sed \
  ARCH=$(uname -m) OPSYS=$(uname -s) OSREL=$(uname -r | sed -e 's/[-(].*//') \
  OSVERSION=4.1 \
  |& tee opm2

# -d mst
# "-p 2" is mentioned in the tutorial but is not accepted.

# (find-fline "/tmp/ports/lang/tcl82/")
# (find-fline "/tmp/ports/lang/tcl82/opm2")




#####
#
# the problem with cp -av in make
# 2005jan09
#
#####

# «cp-av-and-touch»  (to ".cp-av-and-touch")
#*
# (find-node "(make)Automatic" "$^")
# (find-node "(coreutils)stat invocation")
# (find-man "1 stat")
# Try to comment out either cp -av or touch

cd /tmp/
touch file1; sleep 1; touch file2
cat > Makefile <<'%%%'
file1: file2
	@echo $@ is older than $<
	cp -av $< $@
	stat file1 file2
	touch $@
	stat file1 file2
%%%
make
make

#*



#####
#
# .PHONY targets
# 2006jul19
#
#####

# «phony-targets»  (to ".phony-targets")
# (find-node "(make)Phony Targets")
# (find-es "lua5" "install-5.1.1")
# (find-lua51file "src/Makefile")
# (find-lua51file "src/Makefile" ".PHONY:")
# (find-dn4 "Makefile")
# (find-dn4 "examples/Makefile")



#####
#
# remake
# 2008nov20
#
#####

# «remake»  (to ".remake")
http://make.paulandlesley.org/
http://downloads.sourceforge.net/bashdb/remake-3.81+dbg-0.1.tar.bz2


#####
#
# patch to add Lua support to make
# 2008nov20
#
#####

# «lua-support»  (to ".lua-support")
# http://lists.gnu.org/archive/html/help-make/2006-10/msg00018.html
# http://lists.gnu.org/archive/html/help-make/2006-10/msg00021.html
# http://lua-users.org/lists/lua-l/2006-10/msg00523.html



#####
#
# tup
# 2011feb26
#
#####

# «tup»  (to ".tup")
# http://groups.google.com/group/tup-users/files
# http://gittup.org/tup/build_system_rules_and_algorithms.pdf
# http://gittup.org/tup/

* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
rm -Rv ~/usrc/tup/
cd     ~/usrc/
git clone git://gittup.org/tup.git
tar -cvzf ~/tmp/tug.tgz tup/

cd     ~/usrc/tup/
./bootstrap.sh   |& tee ob

# (code-c-d "tup" "~/usrc/tup/")
# (find-tupfile "")
# (find-tupfile "docs/")
# (find-woman "~/usrc/tup/tup.1")




#####
#
# Techniques for "make clean"
# 2019may18
#
#####

# «clean» (to ".clean")
# (find-THLgrep "grep --color -nH -e clean $(find * | grep Makefile)")
# (find-THLsh "find * | grep Makefile | grep -v html | tee /tmp/o")
# (find-THLsh "find * | grep Makefile | grep -v html | gsub.lua '.+' '(find-angg \"%1\")'")




#####
#
# cmake
# 2019aug09
#
#####

# «cmake» (to ".cmake")
# (find-status   "cmake")
# (find-vldifile "cmake.list")
# (find-udfile   "cmake/")
# (find-status   "cmake-data")
# (find-vldifile "cmake-data.list")
# (find-udfile   "cmake-data/")
# (find-status   "cmake-doc")
# (find-vldifile "cmake-doc.list")
# (find-udfile   "cmake-doc/")
# (find-udfile "cmake-data/html/_sources/command/")
# file:///usr/share/doc/cmake-data/html/module/FindICU.html

# (find-zsh "installeddebs | sort | grep cmake")
# (find-zsh "availabledebs | sort | grep cmake")
# (find-sh "apt-file search cmake")




#####
#
# Managing Projects with GNU make, Third Edition
# 2008nov20
#
#####

# «managing-projects-with»  (to ".managing-projects-with")
# (find-books "__comp/__comp.el" "make")





#####
#
# patsubst
# 2022jan04
#
#####

# «patsubst»  (to ".patsubst")
# (find-node "(make)Text Functions" "patsubst")



#####
#
# functions
# 2022jan04
#
#####

# «functions»  (to ".functions")
# (find-node "(make)Call Function")
# (find-node "(make)Eval Function")

# (info "(make)Eval Function")





#####
#
# variables
# 2022jan04
#
#####

# «variables»  (to ".variables")
# (find-node "(make)Automatic Variables")

$@   The file name of the target of the rule
$%   The target member name
$<   The name of the first prerequisite
$?   The names of all the prerequisites that are newer than the target
$^   The names of all the prerequisites
$+   This is like '$^', but prerequisites listed more than once are
     duplicated in the order they were listed in the makefile
$|   The names of all the order-only prerequisites
$*   The stem with which an implicit rule matches




#####
#
# showvar
# 2022jan05
#
#####

# «showvar»  (to ".showvar")
# (find-anggfile "MAKE/demo-2.gnumake")
# (find-anggfile "MAKE/demo-2.gnumake" "%.showvar:")




#####
#
# graph-output
# 2022jan10
#
#####

# «graph-output»  (to ".graph-output")
# https://news.ycombinator.com/item?id=29851156 Proposal to add build graph output to GNU Make (2020) (jonasdn.blogspot.com)
# http://jonasdn.blogspot.com/2020/10/proposal-to-add-build-graph-output-to.html




#####
#
# ignoring-errors
# 2022dec16
#
#####

# «ignoring-errors»  (to ".ignoring-errors")
# (find-node "(make)Errors" "clean:" "-rm -f *.o")









# twb, 2006aug27
#
MAKEFILES := $(patsubst %.map,%.mk,$(wildcard *.map))
include $(MAKEFILES)
%.mk: %.map map2mk.sh
        sh map2mk.sh $* <$< >$@




# Recursive Make Considered Harmful:
# http://miller.emu.id.au/pmiller/books/rmch/
# http://aegis.sourceforge.net/auug97.pdf

https://stackoverflow.com/questions/1755550/what-is-the-reasoning-behind-the-makefile-whitespace-syntax


https://news.ycombinator.com/item?id=29717028 Redo: A recursive, general-purpose build system (redo.readthedocs.io) ***
https://news.ycombinator.com/item?id=32438616 The Unreasonable Effectiveness of Makefiles (matt-rickard.com)



Something about auto dependencies (2006oct16; can I use that for TH?):
http://make.paulandlesley.org/autodep.html

https://news.ycombinator.com/item?id=32477212 Tup – an instrumenting file-based build system (gittup.org)
https://news.ycombinator.com/item?id=32541016 An opinionated approach to GNU Make (davis-hansson.com)
https://news.ycombinator.com/item?id=32896051 Content based change detection with Make (andydote.co.uk)

https://news.ycombinator.com/item?id=33409075 GNU Make 4.4 released (lwn.net)
https://cloudflare.tv/shows/the-gnu-make-course
https://blog.jgc.org/2013/02/updated-list-of-my-gnu-make-articles.html
https://blog.jgc.org/search/label/gnu%20make
https://gmsl.jgc.org/ GNU Make Standard Library

https://news.ycombinator.com/item?id=34330198 Makefiles for web work (rosszurowski.com)
https://news.ycombinator.com/item?id=34342901 Why Use Make (2013) (ocks.org)
https://news.ycombinator.com/item?id=34413375 New make --shuffle mode (trofi.github.io)
https://news.ycombinator.com/item?id=35676825 Piper: A proposal for a graphy pipe-based build system (mattsanetra.uk)
https://news.ycombinator.com/item?id=35936665 Learn Makefiles with the Tastiest Examples (makefiletutorial.com)
https://makefiletutorial.com/#top tastiest
https://text.causal.agency/001-make.txt you don't need to write a Makefile to use it
https://news.ycombinator.com/item?id=38774165 Using Make – writing less Makefile (causal.agency)





#  Local Variables:
#  coding:               utf-8-unix
#  End: