# Myer makefile                             -*- coding: latin-1 -*-
#
# 2003 by Jonathan Yavner <jyavner@member.fsf.org>
# GPL license; see file COPYING for details.
#

# This is where you've downloaded your copy of gcc
GCC_SRC=/usr/local/src/gcc-3.3.2

# Change to "gcc-3.2.patch" if your developemnt copy is of gcc-3.2
GCC_PATCH=gcc-3.3.2.patch

# This is where your gcc system files are.  Change this if you want to
# install Myer and get rid of the gcc_patch directory.
GCC_SYSINCLUDE=gcc_patch/ginclude
#GCC_SYSINCLUDE=/usr/lib/gcc-lib/i386-redhat-linux/3.2/include

# Change this if your installed compiler is not gcc-3
CC=gcc

# Myer stuff
MYER_OBJECTS = myerenv.o myer.o myertoken.o myermerge.o myersum.o myercalc.o myerhtml.o

# Enable -DLEAK_CHECK to deallocate all memory at end of P6, when checking
# for memory leaks (e.g., with valgrind/0
#DEBUG += -DLEAK_CHECK
DEBUG += -g
#OPT += -O2

CFLAGS=${DEBUG} ${OPT} -std=gnu99 -Werror -W -Wall -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -I${GCC_SRC}/include

all: myer gcc_patch/cc1 myer_cc1 myer_sysinclude

myer: ${MYER_OBJECTS} ${GCC_SRC}/libiberty/libiberty.a
	${CC} ${DEBUG} -o $@ ${MYER_OBJECTS} -lm ${GCC_SRC}/libiberty/libiberty.a

${MYER_OBJECTS}: myer.h

myerhtml.o: myerhtml.h

# Standard command-line #defines for this host system.  This file isn't very
# interesting for gcc-3.2, but contains lots of defines for gcc-3.2.
myerenv.c: gcc_patch/cc1
	(export PATH=.:$${PATH} && \
		cd gcc_patch && \
		xgcc --verbose -E ${CFLAGS} -o /dev/null -iprefix ./ ../myer.c 2>&1) \
	| egrep '(cpp0|cc1)' \
	| tr ' ' '\012' \
	| grep -- "^-D" \
	> myerenv.def
	echo "/* Generated file */" >$@
	echo "int myerenv_count = "`wc -l myerenv.def | cut -c1-7`";" >>$@
	echo "char *myerenv_list[] = {" >>$@
	sed 's/.*/"&",/' <myerenv.def >>$@
	echo "};" >>$@

myer_cc1:
	ln -s gcc_patch/cc1 $@

myer_sysinclude:
	ln -s ${GCC_SYSINCLUDE} $@

# Use the $(wildcard) operator to postpone checking the gcc_patch directory
# until after it is constructed by the next rule.
gcc_patch/cc1: gcc_patch/patch.time myerparse.c $(wildcard gcc_patch/*.[ch])
	cd gcc_patch && make CC="gcc ${OPT}" cc1 xgcc
	touch gcc_patch/cc1

PATCH_FILES = $(shell \
	grep "^diff " ${GCC_PATCH} \
	| sed -e "s|diff \(-[^ ]* \)*[^ ]* \./||")

# Create the gcc_patch directory, populate it with soft-links to the GCC
# base, except copy the files that will be patched.  Patch the desired
# files.  Don't link the s-* files, which are make-dependency timestamps.
# Create fake <limits.h> to make /usr/include/limits.h happy.
gcc_patch/patch.time: ${GCC_PATCH}
	rm -rf gcc_patch include libiberty
	ln -s ${GCC_SRC}/include .
	ln -s ${GCC_SRC}/libiberty .
	mkdir gcc_patch
	ln -s ../myerparse.c gcc_patch
	ln -s ../myerparse.h gcc_patch
	(cd gcc_patch; \
	 for x in ${GCC_SRC}/gcc/*; do \
		ln -s $$x .; \
	 done; \
	 rm -rf $(PATCH_FILES) $(PATCH_FILES:%=%.o) ginclude s-* stmp-* tmp-* cc1; \
	 cp -r ${GCC_SRC}/gcc/ginclude ginclude; \
	 echo "#define CHAR_BIT 8" >ginclude/limits.h; \
	 echo "#define INT_MAX 2147483647" >>ginclude/limits.h; \
	 echo "#define INT_MIN (-INT_MAX-1)" >>ginclude/limits.h; \
	 echo "#define UINT_MAX (INT_MAX*2U+1)" >>ginclude/limits.h; \
	 cp $(PATCH_FILES:%=${GCC_SRC}/gcc/%) .)
	cd gcc_patch && patch <../${GCC_PATCH}
	touch $@

# Create the example directory that README-commentary is talking about.
# Note: This rule expectedly prints lots of "No information about" messages,
# about every header in /usr/include that is not referenced by Myer.
Example_myer: myer
	rm -f *.o *.myer2
	make CC=./myer ${MYER_OBJECTS}
	./myer -o $@/ *.myer2 *.h include/*.h /usr/include/*.h

# Example of Myer output: the gcc compiler.  You'll need 211 MB of RAM+swap
# to run this phase.
Example_gcc: gcc_forexample/gcc.myer3
	./myer -v -o $@/ gcc_forexample/gcc.myer3

# Combine the analyses for each gcc file.  This rule expectedly prints lots
# of "No information about" and "File does not have same contents" messages.
# This phase needs about 140 MB of RAM+swap.
gcc_forexample/gcc.myer3: gcc_forexample/gcc.myer2
	./myer -v -P3 -o $@ gcc_forexample/*.myer2 gcc_forexample/*.h

# Build all the .myer2 files for gcc.  This is messy, and got a lot messier
# in gcc-3.3.2.  We can't use the 'make CC=myer' approach here because of
# complex dependencies in gcc's Makefile.  We can't deal with c-common.c and
# timevar.c (and also gengtype.c and diagnostic.c for gcc-3.3.2) because
# they use #include inside a function body, which Myer currently doesn't
# support.  We can't deal with tradcif.c (gcc-3.2 only) and gengtype-yacc.c
# (gcc-3.3.2 only) because they use a macro YYSTACK_ALLOC to select the name
# of another macro (alloca) that takes arguments.  We have to pre-touch the
# entire gengtype subproject so the gengtype-yacc problem doesn't cause make
# to abort.
TO_SKIP=c-common\.o|timevar\.o|gengtype\.o|diagnostic\.o|tradcif\.o|gengtype-yacc\.o
TO_BE_TOUCHED=auto-host.h hconfig.h gtyp-gen.h genrtl.h genrtl.c
gcc_forexample/gcc.myer2: myer gcc_forexample/c-parse.in
	(cd gcc_patch; \
	ALLOBJ=`echo *.o | tr ' ' '\012' | egrep -v '($(TO_SKIP))'`; \
	cd ../gcc_forexample; \
	rm -f ${TO_BE_TOUCHED}; \
	cp ${TO_BE_TOUCHED:%=../gcc_patch/%} .; \
	make -t genrtl.h genrtl.c gengtype; \
	make -t gengtype; \
	make -k CC=${PWD}/myer $${ALLOBJ}; \
	rm -f c-common.myer2 diagnostic.myer2 timevar.myer2)

# Create the temp directory containing a copy of gcc, minus the .o files (so
# make will run Myer trying to recreate them).
gcc_forexample/c-parse.in: gcc_patch/c-parse.in
	rm -rf gcc_forexample
	mkdir -p gcc_forexample
	(cd gcc_patch; \
	 find . ! -name '*.o' -print | cpio -pdm ../gcc_forexample)

# Maintainers: create a new tar archive for Myer.
TAR_FILES=COPYING Makefile *.patch *.c *.h *.html README-commentary
tar:
	DATE=`date +%Y%m%d`; \
	ln -s . myer-$${DATE}; \
	tar zcvfh myer-$${DATE}.tgz ${TAR_FILES:%=myer-$${DATE}/%}; \
	rm myer-$${DATE}

# Maintainers: Create a new patch file
gcc-new.patch::
	-(cd gcc_patch \
	    && diff -ur --exclude="c-parse.[cy]" \
			--exclude="libgcc.mk" \
		    ${GCC_SRC}/gcc . ) \
	  > $@

clean:
	rm -rf myer myer_cc1 myerenv.c myerenv.def *.o *.myer? \
		include libiberty gcc_patch gcc_forexample \
		Example_gcc Example_myer Myer myer_Myer
