Building Starkits and Starpacks using a Makefile 2

The gorilla example, Building Starkits and Starpacks using a Makefile, was great, but it rebuilds the whole shebang every time. I was looking for a Makefile that would let me make local changes, rebuild, and test before checking the source back in.

I removed the dependency on the local Tcl installation from my earlier version, because that became impossible to maintain. All the required files now get checked out to a well-known tree rooted at SUPPORT.

Much simplified from earlier version. This will build on Linux and Windows platforms (tested on Redhat and Suse and XP.) For example, you can cross-compile a Linux binary on XP using:

 $make ARCH=LINUX

See also cross-building a starkit, for a cross-build that starts with a starkit and builds for several platforms.

LV 2009-11-18 So on Windows, what files are needed to support this Makefile process?

dcd 2009-12-10 You need, obviously, a tclkitsh built for Windows and gnu make, cp, rm and mkdir; preferably a recent version of make. I use a cygwin environment, but you could just grab unix-utils and stay with your dos shell; untested, but I'm pretty sure you could make that work and avoid the overhead of a full cygwin install.


# Support for Linux and Windows XP platforms
# This builds from the app.tcl source, not a kit
#
# SUPPORT is the base for the runtimes and tcl libraries
SUPPORT := ../support/tcl
WINRT := $(SUPPORT)/win/bin/tclkitsh-win32.upx.exe
LINRT := $(SUPPORT)/unix/bin/tclkitsh-linux
TCLLIB := $(SUPPORT)/lib

SDXKIT := $(SUPPORT)/sdx.kit

# OS is defined on Windows, not on Linux
ifndef OS
OS := LINUX
else
OS := WIN
endif

# pick the correct tclkit to run sdx.kit
ifeq ($(OS),WIN)
SDX = $(WINRT) $(SDXKIT)
else
SDX = $(LINRT) $(SDXKIT)
endif

# if not defined
# set the target architecture to the build machine
ifndef ARCH
ARCH = $(OS)
endif

# point to the correct runtime
# and to the location of the platform specific binaries
# and get the application extension set
ifeq ($(ARCH),WIN)
LIBTCL := $(SUPPORT)/win/lib
RUNTIME = $(WINRT)
APPEXT = .exe
else
ifeq ($(ARCH),LINUX)
LIBTCL := $(SUPPORT)/unix/lib
RUNTIME = $(LINRT)
APPEXT = 
endif
endif

# TCLLIBS, here, means pure tcl packages, not just from Tcllib
# each lib here should be in its own directory in $(SUPPORT)/lib
TCLLIBS := uri

# each package in BINLIBS s.b. in its own platform specific library
BINLIBS :=  tnc tdom0.8.2 Tcldom2.6 Tclxml2.6

APP := myapp

EXE := $(patsubst %,%$(APPEXT),$(APP))

VFS = $(APP).vfs
VFSLIB = $(VFS)/lib
# a list of files you want copied into the application
PACKAGES = $(TCLLIBS) $(BINLIBS) dtd.xml

all: $(EXE)

# it appears that windows or sdx doesn't like copying the runtime
# if it is the same runtime that is executing sdx.kit
# so the copy / remove dance is necessary
%$(APPEXT) : %.vfs $(PACKAGES)
        cp $(RUNTIME) ./runtime
        $(SDX) wrap $@ -runtime runtime
        rm runtime
        chmod +x $@

# this prevents make from trying, and failing, to delete
# the vfs directory, which is not a regular file
.SECONDARY : $(patsubst %,%.vfs,$(APP))

# make 3.81 doesn't require this workaround

export PACKAGES

%.vfs : %.tcl
        if [ ! -d $@ ]; \
        then $(SDX) qwrap $<; $(SDX) unwrap $*.kit; fi; \
        cp $< $@/lib/app-$*/

# put packages here, they may each have different idiosyncracies

.PHONY : $(PACKAGES)

$(PACKAGES) : $(VFS)

$(TCLLIBS): $(APP).vfs
        if [ ! -d $(VFSLIB)/$@ ] ; then \
          mkdir $(VFSLIB)/$@ ; fi
        cp $(TCLLIB)/$(@)/*.tcl $(VFSLIB)/$@

dtd.xml: $(APP).vfs
        cp $(APP)/$@ $<

$(BINLIBS): $(APP).vfs
        if [ ! -d $(VFSLIB)/$@ ] ; then \
          mkdir $(VFSLIB)/$@ ; fi
        cp $(LIBTCL)/$(@)/* $(VFSLIB)/$@

clean:
        rm -f $(APP) $(patsubst %,%.kit,$(APP)) $(patsubst %,%.exe,$(APP)); \
        rm -rf $(patsubst %,%.vfs,$(APP))