Check out my first novel, midnight's simulacra!

GNU Make

From dankwiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Important Special Targets

.DELETE_ON_ERROR

  • Generally, if make fails to build a target, and the target corresponds to a file, you want that file removed.
    • Why might this happen? Ctrl-c being pressed during a build. Multiple statements in a build recipe. Memory allocation failure during build. Any number of things.
  • By adding .DELETE_ON_ERROR to the Makefile, this becomes the default behavior.
    • kill -9'ing make will prevent this from happening! :/
  • gcc and some other tools will clean up on error, for some cases. Use .DELETE_ON_ERROR to be safe.

.PHONY:

  • GNU Make manual section 4.6, "Phony Targets"
  • clean, all, test targets ought almost always be .PHONY

.DEFAULT:

Make and subversion

  • After running make in a pristine tree, the output of svn status ought be empty. Use svn:ignore properties to ignore your generated files.
    • Most importantly, svn status should not show any entries in the 'M'odified state. This indicates either generated files being checked into source control, or the build process modifying source in-place (the same thing, really)
    • If svn:ignore is properly used, the following rule suffices as a project-independent clean target, assuming the presence of xmlstarlet:
      svn --xml --no-ignore status | xmlstarlet sel -t -m //entry -i "wc-status[@item='ignored']" -v @path -n | xargs rm -rf

bash interactions

  • The shell to use can be specified via $(SHELL). By default, /bin/sh is used
    • Unlike most variables, it cannot be inherited from the environment (except on Windows, where it is)
    • It is not exported by default to sub-Makes, but it can be
  • Arguments to the shell can be specified via .SHELLFLAGS
    • By default, it's -c, or -ec in POSIX mode
  • Remember that errors in the body of a shell loop don't set the overall return value:
target:
        while true ; do false ; done

This recipe cannot be successfully completed! You can use

target:
        set -e ; while true ; do false ; done

or

target:
        while true ; do false || exit ; done

The former is probably nicer, since you can then use ; in the place of &&, but it deviates from expected gmake semantics. In general, you don't want to be doing this kind of thing anyway; it's useful for cases like running unit testing on a set of inputs, where outputs won't be generated.