Building Steven Simpson's software

Most of my compilable software expects a quasi-Unix environment including GNU Make. In case I haven't explained this expectation fully in each package, here are its general aspects and principles.

The Makefile of a package such as react (for example) will try to load a file called react-env.mk from a list of directories, and include the file's declarations in its own, but continues silently if not found. Settings in the file can override defaults in Makefile, so by providing the file in one of the listed directories, you can tailor the build to your environment. Typically, one should override the following:

  • PREFIX should be set to the directory where one wants the software to be finally installed. The default is /usr/local.

  • CPPFLAGS, CFLAGS, CXXFLAGS and LDFLAGS should be set according to the GNU Make documentation.

    Specifying -O2 -g is probably a good idea for most packages.

The default locations for file inclusion are not very convenient, so I set my environment to point make at some additional locations by setting the environment variable MAKEFLAGS. For example:

MAKEFLAGS="-I$$HOME/config"

Perhaps surprisingly, make does not recognize any path variable for file-inclusion directories. To emulate a colon-separated MAKEPATH, I've been using this in my ~/.bash_aliases:

# ~/.bash_aliases
function make_with_path () {
    local EXTRAS
    local index=1
    local copy="$$MAKEPATH"
    local old
    while [ -n "$$copy" ] ; do
        EXTRAS=("$${EXTRAS[@]}" -I "$${copy%%:*}")
        old="$$copy"
        copy="$${copy#*:}"
        if [ "$$old" == "$$copy" ] ; then break ; fi
    done
    `which make` "$${EXTRAS[@]}" "$$@"
}

alias make=make_with_path

Note that this sort of thing isn't going to work with sudo make install, as that doesn't execute the Bash function, so you can only really install as root in the default location, usually /usr/local. If you need to install as root to another location (or with any other overrides), you might be better off with something that sets MAKEFLAGS more persistently. The following converts $$MAKEPATH elements into arguments for make, and combines them with $$STATIC_MAKEFLAGS to form MAKEFLAGS:

function set_make_flags () {
    local EXTRAS
    local index=1
    local copy="$$MAKEPATH"
    local old
    while -n "$$copy" ; do
        EXTRAS=("$${EXTRAS@}" -I "$${copy%%:*}")
        old="$$copy"
        copy="$${copy#*:}"
        if "$$old" == "$$copy" ; then break ; fi
    done
    export MAKEFLAGS="$${STATIC_MAKEFLAGS} $${EXTRAS@}"
}

Now you update MAKEFLAGS manually whenever you change MAKEPATH:

export MAKEPATH="$$MAKEPATH:$HOME/.local/include"
set_make_flags

…and ensure the environment is passed via sudo:

sudo -E make install