Saturday, September 12, 2015

Taming The Make System

I've never enjoyed gnu make. Most people I know don't, but it's a necessary evil. So I took some time out to finally get it into some shape. So, now I have a new SW structure. Here is my new directory structure:


And here are my makefiles and includes:

SW/Makefile:


SW_DIR= $(shell pwd | sed 's/\/cygdrive\/c\//C:\\\\/' | sed 's/\//\\\\/g')
SW_DIR_CYG= $(shell pwd)
CFLAGS_Z80=-mz80
CFLAGS_GENERIC=-c -DNDEBUG
AFLAGS=-o
LFLAGS= -mz80 --no-std-crt0 --nostdlib --code-loc 0x100 --data-loc 0x8000
INCLUDES=-I${SW_DIR}/include -I${SW_DIR}/app/include
INCLUDES_CYG=-I${SW_DIR_CYG}/include -I${SW_DIR_CYG}/app/include
TOOLDIR=/cygdrive/c/Program\ Files/SDCC/bin
LIBDIR=lib

MAKEARGS="CFLAGS_Z80=${CFLAGS_Z80}" "CFLAGS_GENERIC=${CFLAGS_GENERIC}" "INCLUDES=${INCLUDES}" "AFLAGS=${AFLAGS}" "TOOLDIR=${TOOLDIR}" "LIBDIR=../${LIBDIR}" "BASEDIR=.." "LFLAGS=${LFLAGS}" "INCLUDES_CYG=${INCLUDES_CYG}"


# This makefile is the top level makefile that calls down to all the submakes
# It will get the current directory, basic flags, and then drill down
# includes are 
#

#

.PHONY: all c bsp clean depends clean_bsp clean_app clean_c clean_lib

all:
 cd app ; ${MAKE} all ${MAKEARGS} "DIRS=test" "PROG=mainRW"
# cd app ; ${MAKE} all ${MAKEARGS} "DIRS=menu" "PROG=menu"

c:
 cd c_src ; ${MAKE} all ${MAKEARGS}

bsp:
 cd bsp ; ${MAKE} all ${MAKEARGS} "DIRS=crt0  diag  flash  gpio  interrupt  membank  spi  tick  uart" "LIB=bsp"
 cd app ; ${MAKE} all ${MAKEARGS} "DIRS=idle intelHex ringBuffer timer" "LIB=bsp"

clean: clean_bsp clean_app clean_c clean_lib

clean_bsp:
 cd bsp ; ${MAKE} clean ${MAKEARGS} "DIRS=crt0  diag  flash  gpio  interrupt  membank  spi  tick  uart" "LIB=bsp"

clean_app:
 cd app ; ${MAKE} clean ${MAKEARGS} "DIRS=idle intelHex ringBuffer  test  timer menu test" "LIB=bsp"

clean_c:
 cd c_src; ${MAKE} clean ${MAKEARGS}

clean_lib:
 cd lib ; rm -f *.lib; rm -f *.rel
 
depends:
 cd app ; ${MAKE} depends ${MAKEARGS}

test:
 cd bsp; pwd; make test ${MAKEARGS}



SW/common.inc:


COMMON=INCUDED

MAKEARGS="CFLAGS_Z80=${CFLAGS_Z80}" "CFLAGS_GENERIC=${CFLAGS_GENERIC}" "INCLUDES=${INCLUDES}" "AFLAGS=${AFLAGS}" "TOOLDIR=${TOOLDIR}" "LIBDIR=../${LIBDIR}" "BASEDIR=../${BASEDIR}"


SW/subdirs.inc:


SUBDIRS=INCUDED

.PHONY: all clean

all:
 echo ${DIRS}
 @for i in ${DIRS} ; do \
        cd $$i; \
  make all ${MAKEARGS}; \
  cd ..; \
    done

clean:
 echo ${DIRS}
 @for i in ${DIRS} ; do \
        cd $$i; \
  make clean ${MAKEARGS}; \
  cd ..; \
    done


SW/generate.inc:


CC=${TOOLDIR}/sdcc.exe
AS=${TOOLDIR}/sdasz80.exe
AR=${TOOLDIR}/sdcclib.exe

C_SOURCES=$(wildcard *.c)
S_SOURCES=$(wildcard *.s)
REL_C=$(patsubst %.c,%.rel, ${C_SOURCES})
REL_S=$(patsubst %.s,%.rel ,${S_SOURCES})

all: ${REL_C} ${REL_S}

# - keeps it from crashing out if no *.d file
-include *.d

clean:
 rm -f *.d
 rm -f *.lib
 rm -f *.rel
 rm -f *.asm
 rm -f *.lst
 rm -f *.sym

%.rel : %.s
 ${AS} -g ${AFLAGS} $<
 ${AR} r ${LIBDIR}/${LIB}.lib $@

%.rel : %.c
 ${CC} ${CFLAGS_Z80} ${CFLAGS_GENERIC} ${INCLUDES} $<
 ${AR} r ${LIBDIR}/${LIB}.lib $@

%.d : %.c
 gcc ${CFLAGS_GENERIC} ${INCLUDES_CYG} -MM $< > $*.d


The Makefiles found in directories with no code:


include ${BASEDIR}/common.inc
include ${BASEDIR}/subdirs.inc


The Makefiles found in directories with code:


include ${BASEDIR}/common.inc
include ${BASEDIR}/generate.inc


SW/bsp/crt0 has a special makefile since crt0 isn't archived but copied to SW/lib:


include ${BASEDIR}/common.inc

# This makefile is unique because the crt0 isn't archived. Rather it must be the first item in the list of rel/ar given to the linker
CC=${TOOLDIR}/sdcc.exe
AS=${TOOLDIR}/sdasz80.exe
AR=${TOOLDIR}/sdcclib.exe

C_SOURCES=$(wildcard *.c)
S_SOURCES=$(wildcard *.s)
REL_C=$(patsubst %.c,%.rel, ${C_SOURCES})
REL_S=$(patsubst %.s,%.rel ,${S_SOURCES})

all: ${REL_C} ${REL_S}

clean:
 rm -f *.d
 rm -f *.lib
 rm -f *.rel
 rm -f *.asm
 rm -f *.lst
 rm -f *.sym

%.rel : %.s
 ${AS} -g ${AFLAGS} $<
# ${AR} rc ${LIBDIR}/${LIB} $@
 cp crt0.rel ${LIBDIR}/

%.rel : %.c
 ${CC} ${CFLAGS_Z80} ${CFLAGS_GENERIC} ${INCLUDES} $<
# ${AR} rc ${LIBDIR}/${LIB}.ar $@

And the common C directory also has a special Makefile:


include ${BASEDIR}/common.inc

CC=${TOOLDIR}/sdcc.exe
AS=${TOOLDIR}/sdasz80.exe
AR=${TOOLDIR}/sdcclib.exe


C_SOURCES= _calloc.c _divslong.c _divulong.c _free.c _heap.c _itoa.c _ltoa.c _malloc.c _memchr.c _memcmp.c _memcpy.c _memset.c _modslong.c _modulong.c _mullong.c _realloc.c _startup.c _strcat.c _strchr.c _strcmp.c _strcspn.c _strncat.c _strncmp.c _strncpy.c _strpbrk.c _strrchr.c _strspn.c _strstr.c _strtok.c assert.c atoi.c atol.c errno.c gets.c isalnum.c isalpha.c isblank.c iscntrl.c isdigit.c isgraph.c islower.c isprint.c ispunct.c isspace.c isupper.c isxdigit.c labs.c puts.c rand.c sprintf.c strxfrm.c time.c tolower.c toupper.c vprintf.c 

# _divschar.c _modschar.c _mulschar.c _setjmp.c _strcpy.c abs.c _memmove.c _strlen.c _modsint.c _moduint.c _mulint.c _divsint.c _divuint.c

C_LONG_LONG_SOURCES= _divslonglong.c _divulonglong.c _modslonglong.c _modulonglong.c _mullonglong.c _rlslonglong.c _rlulonglong.c _rrslonglong.c _rrulonglong.c atoll.c

C_FLOAT_SOURCES= _atof.c _fs2schar.c _fs2sint.c _fs2slong.c _fs2uchar.c _fs2uint.c _fs2ulong.c _fsadd.c _fscmp.c _fsdiv.c _fseq.c _fsget1arg.c _fsget2args.c _fsgt.c _fslt.c _fsmul.c _fsneq.c _fsnormalize.c _fsreturnval.c _fsrshift.c _fssub.c _fsswapargs.c _logexpf.c _schar2fs.c _sint2fs.c _slong2fs.c _uchar2fs.c _uint2fs.c _ulong2fs.c acosf.c asincosf.c asinf.c atan2f.c atanf.c ceilf.c cosf.c coshf.c cotf.c expf.c fabsf.c floorf.c frexpf.c ldexpf.c log10f.c logf.c modff.c powf.c sincosf.c sincoshf.c sinf.c sinhf.c sqrtf.c tancotf.c tanf.c tanhf.c

REL_C_SOURCES=$(patsubst %.c,%.rel, ${C_SOURCES})
REL_C_LONG_LONG_SOURCES=$(patsubst %.c,%.rel, ${C_LONG_LONG_SOURCES})
REL_C_FLOAT_SOURCES=$(patsubst %.c,%.rel, ${C_FLOAT_SOURCES})
REL_S=$(patsubst %.s,%.rel ,${S_SOURCES})

.PHONY: all z80

all: c_lib float_lib longlong_lib z80

z80:
 cd z80; make all ${MAKEARGS} "LIB=c"

c_lib: ${REL_C_SOURCES} ${REL_S}
 ${AR} r ${LIBDIR}/c.lib ${REL_C_SOURCES} ${REL_S}
 
float_lib: ${REL_C_FLOAT_SOURCES}
 ${AR} r ${LIBDIR}/float.lib ${REL_C_FLOAT_SOURCES}
 
longlong_lib: ${REL_C_LONG_LONG_SOURCES}
 ${AR} r ${LIBDIR}/longlong.lib ${REL_C_LONG_LONG_SOURCES}
 
%.rel : %.s
 ${AS} -g ${AFLAGS} $<

%.rel : %.c
 ${CC} ${CFLAGS_Z80} ${CFLAGS_GENERIC} ${INCLUDES} $<

clean:
 rm -f *.d
 rm -f *.lib
 rm -f *.rel
 rm -f *.asm
 rm -f *.lst
 rm -f *.sym
 cd z80; make clean ${MAKEARGS}


And this is how I make a clean build of the program I'm working with:


$> make clean
$> make all


It's not perfect. It's probably not even good. But it's better than the ad hoc Makefiles I had before because it's more scalable and extensible.

No comments:

Post a Comment