Search code examples
makefilescons

Wrap a scons build process in a Makefile


I've written a scons build chain form a little C project, but I'm afraid users won't like to be told "You should install SCons first. Besides, it's really cool!" (expecially my professor, as he's kind of from the old guard).

Is there a way I can set up a Makefile that will wrap scons, not requiring it to be installed on the target system?


Solution

  • After looking for such a solution some time ago, I ended up writing a Makefile for this purpose.

    Because SCons also comes as a drop-in userspace package scons-local (see the download page), one can fetch in and run it. Here is a dissectioned and commented version of my Makefile, which I also uploaded as a gist.

    all: get_scons
           @$(SCONS_EXE)
    

    ↑ The default action depends on scons being available, and simply runs the scons command (set later in the script) (the @ symbol prevents make from printing the command)

    SCONS_VERSION=2.3.4
    
    scons-local-%.tar.gz:
        curl -L http://sourceforge.net/projects/scons/files/scons-local/$(SCONS_VERSION)/scons-local-$(SCONS_VERSION).tar.gz > scons-local-$(SCONS_VERSION).tar.gz
        touch scons-local-$(SCONS_VERSION).tar.gz
    
    scons-local: scons-local-$(SCONS_VERSION).tar.gz
        mkdir -p scons-local
        tar xzf scons-local-$(SCONS_VERSION).tar.gz --directory scons-local
        touch scons-local
    

    ↑ Set up the rules for fetching the tarball and unpack it into the scons-local directory

    NATIVE_SCONS=$(strip $(shell which scons 2>/dev/null))
    
    ifeq ($(NATIVE_SCONS),)
    SCONS_EXE=python2 ./scons-local/scons.py
    get_scons: scons-local
        @echo "Couldn't find an installation of SCons, using a local copy"
    else
    SCONS_EXE=$(NATIVE_SCONS)
    get_scons:
        @echo "Found SCons installation at $(SCONS_EXE)"
    endif
    

    ↑ Look for the scons executable in the search path (using the which command): if it is available, set up the get-scons target to simply print it is available. If, instead, it is not available, create the get-scons target instructing it to depend on the scons-local target defined earlier.

    clean:
        $(SCONS_EXE) -c
        rm -rf scons-local
        rm -f scons-local-*.tar.gz
    
    .PHONY: all clean get_scons
    

    ↑ Finally, set-up the clean target that delegates to scons and deletes the local installation afterwards. The .PHONY rule tells make that the following rules do not correspond to files being created.

    At this point, one could add more proxy rules of the kind:

    mytarget: get_scons
        @$(SCONS_EXE) mytarget
    

    Which will invoke scons with the corresponding target.

    Hope this is useful, feel free to correct me in case there's something wrong (I'm actually not a Makefile expert, and I'm trying not to become one by using SCons instead :P )