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:
1 SW_DIR= $(shell pwd | sed 's/\/cygdrive\/c\//C:\\\\/' | sed 's/\//\\\\/g')
2 SW_DIR_CYG= $(shell pwd)
3 CFLAGS_Z80=-mz80
4 CFLAGS_GENERIC=-c -DNDEBUG
5 AFLAGS=-o
6 LFLAGS= -mz80 --no-std-crt0 --nostdlib --code-loc 0x100 --data-loc 0x8000
7 INCLUDES=-I${SW_DIR}/include -I${SW_DIR}/app/include
8 INCLUDES_CYG=-I${SW_DIR_CYG}/include -I${SW_DIR_CYG}/app/include
9 TOOLDIR=/cygdrive/c/Program\ Files/SDCC/bin
10 LIBDIR=lib
11
12 MAKEARGS="CFLAGS_Z80=${CFLAGS_Z80}" "CFLAGS_GENERIC=${CFLAGS_GENERIC}" "INCLUDES=${INCLUDES}" "AFLAGS=${AFLAGS}" "TOOLDIR=${TOOLDIR}" "LIBDIR=../${LIBDIR}" "BASEDIR=.." "LFLAGS=${LFLAGS}" "INCLUDES_CYG=${INCLUDES_CYG}"
13
14
15 # This makefile is the top level makefile that calls down to all the submakes
16 # It will get the current directory, basic flags, and then drill down
17 # includes are
18 #
19
20 #
21
22 .PHONY: all c bsp clean depends clean_bsp clean_app clean_c clean_lib
23
24 all:
25 cd app ; ${MAKE} all ${MAKEARGS} "DIRS=test" "PROG=mainRW"
26 # cd app ; ${MAKE} all ${MAKEARGS} "DIRS=menu" "PROG=menu"
27
28 c:
29 cd c_src ; ${MAKE} all ${MAKEARGS}
30
31 bsp:
32 cd bsp ; ${MAKE} all ${MAKEARGS} "DIRS=crt0 diag flash gpio interrupt membank spi tick uart" "LIB=bsp"
33 cd app ; ${MAKE} all ${MAKEARGS} "DIRS=idle intelHex ringBuffer timer" "LIB=bsp"
34
35 clean: clean_bsp clean_app clean_c clean_lib
36
37 clean_bsp:
38 cd bsp ; ${MAKE} clean ${MAKEARGS} "DIRS=crt0 diag flash gpio interrupt membank spi tick uart" "LIB=bsp"
39
40 clean_app:
41 cd app ; ${MAKE} clean ${MAKEARGS} "DIRS=idle intelHex ringBuffer test timer menu test" "LIB=bsp"
42
43 clean_c:
44 cd c_src; ${MAKE} clean ${MAKEARGS}
45
46 clean_lib:
47 cd lib ; rm -f *.lib; rm -f *.rel
48
49 depends:
50 cd app ; ${MAKE} depends ${MAKEARGS}
51
52 test:
53 cd bsp; pwd; make test ${MAKEARGS}
SW/common.inc:
1 COMMON=INCUDED
2
3 MAKEARGS="CFLAGS_Z80=${CFLAGS_Z80}" "CFLAGS_GENERIC=${CFLAGS_GENERIC}" "INCLUDES=${INCLUDES}" "AFLAGS=${AFLAGS}" "TOOLDIR=${TOOLDIR}" "LIBDIR=../${LIBDIR}" "BASEDIR=../${BASEDIR}"
SW/subdirs.inc:
1 SUBDIRS=INCUDED
2
3 .PHONY: all clean
4
5 all:
6 echo ${DIRS}
7 @for i in ${DIRS} ; do \
8 cd $$i; \
9 make all ${MAKEARGS}; \
10 cd ..; \
11 done
12
13 clean:
14 echo ${DIRS}
15 @for i in ${DIRS} ; do \
16 cd $$i; \
17 make clean ${MAKEARGS}; \
18 cd ..; \
19 done
SW/generate.inc:
1 CC=${TOOLDIR}/sdcc.exe
2 AS=${TOOLDIR}/sdasz80.exe
3 AR=${TOOLDIR}/sdcclib.exe
4
5 C_SOURCES=$(wildcard *.c)
6 S_SOURCES=$(wildcard *.s)
7 REL_C=$(patsubst %.c,%.rel, ${C_SOURCES})
8 REL_S=$(patsubst %.s,%.rel ,${S_SOURCES})
9
10 all: ${REL_C} ${REL_S}
11
12 # - keeps it from crashing out if no *.d file
13 -include *.d
14
15 clean:
16 rm -f *.d
17 rm -f *.lib
18 rm -f *.rel
19 rm -f *.asm
20 rm -f *.lst
21 rm -f *.sym
22
23 %.rel : %.s
24 ${AS} -g ${AFLAGS} $<
25 ${AR} r ${LIBDIR}/${LIB}.lib $@
26
27 %.rel : %.c
28 ${CC} ${CFLAGS_Z80} ${CFLAGS_GENERIC} ${INCLUDES} $<
29 ${AR} r ${LIBDIR}/${LIB}.lib $@
30
31 %.d : %.c
32 gcc ${CFLAGS_GENERIC} ${INCLUDES_CYG} -MM $< > $*.d
The Makefiles found in directories with no code:
1 include ${BASEDIR}/common.inc
2 include ${BASEDIR}/subdirs.inc
The Makefiles found in directories with code:
1 include ${BASEDIR}/common.inc
2 include ${BASEDIR}/generate.inc
SW/bsp/crt0 has a special makefile since crt0 isn’t archived but copied to SW/lib:
1 include ${BASEDIR}/common.inc
2
3 # 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
4 CC=${TOOLDIR}/sdcc.exe
5 AS=${TOOLDIR}/sdasz80.exe
6 AR=${TOOLDIR}/sdcclib.exe
7
8 C_SOURCES=$(wildcard *.c)
9 S_SOURCES=$(wildcard *.s)
10 REL_C=$(patsubst %.c,%.rel, ${C_SOURCES})
11 REL_S=$(patsubst %.s,%.rel ,${S_SOURCES})
12
13 all: ${REL_C} ${REL_S}
14
15 clean:
16 rm -f *.d
17 rm -f *.lib
18 rm -f *.rel
19 rm -f *.asm
20 rm -f *.lst
21 rm -f *.sym
22
23 %.rel : %.s
24 ${AS} -g ${AFLAGS} $<
25 # ${AR} rc ${LIBDIR}/${LIB} $@
26 cp crt0.rel ${LIBDIR}/
27
28 %.rel : %.c
29 ${CC} ${CFLAGS_Z80} ${CFLAGS_GENERIC} ${INCLUDES} $<
30 # ${AR} rc ${LIBDIR}/${LIB}.ar $@
And the common C directory also has a special Makefile:
1 include ${BASEDIR}/common.inc
2
3 CC=${TOOLDIR}/sdcc.exe
4 AS=${TOOLDIR}/sdasz80.exe
5 AR=${TOOLDIR}/sdcclib.exe
6
7
8 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
9
10 # _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
11
12 C_LONG_LONG_SOURCES= _divslonglong.c _divulonglong.c _modslonglong.c _modulonglong.c _mullonglong.c _rlslonglong.c _rlulonglong.c _rrslonglong.c _rrulonglong.c atoll.c
13
14 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
15
16 REL_C_SOURCES=$(patsubst %.c,%.rel, ${C_SOURCES})
17 REL_C_LONG_LONG_SOURCES=$(patsubst %.c,%.rel, ${C_LONG_LONG_SOURCES})
18 REL_C_FLOAT_SOURCES=$(patsubst %.c,%.rel, ${C_FLOAT_SOURCES})
19 REL_S=$(patsubst %.s,%.rel ,${S_SOURCES})
20
21 .PHONY: all z80
22
23 all: c_lib float_lib longlong_lib z80
24
25 z80:
26 cd z80; make all ${MAKEARGS} "LIB=c"
27
28 c_lib: ${REL_C_SOURCES} ${REL_S}
29 ${AR} r ${LIBDIR}/c.lib ${REL_C_SOURCES} ${REL_S}
30
31 float_lib: ${REL_C_FLOAT_SOURCES}
32 ${AR} r ${LIBDIR}/float.lib ${REL_C_FLOAT_SOURCES}
33
34 longlong_lib: ${REL_C_LONG_LONG_SOURCES}
35 ${AR} r ${LIBDIR}/longlong.lib ${REL_C_LONG_LONG_SOURCES}
36
37 %.rel : %.s
38 ${AS} -g ${AFLAGS} $<
39
40 %.rel : %.c
41 ${CC} ${CFLAGS_Z80} ${CFLAGS_GENERIC} ${INCLUDES} $<
42
43 clean:
44 rm -f *.d
45 rm -f *.lib
46 rm -f *.rel
47 rm -f *.asm
48 rm -f *.lst
49 rm -f *.sym
50 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.