# -*- Makefile -*-
# CYCDIR must be defined by the environment for this file to work correctly.
#
# This file is normally invoked recursively by the top-level Cyclone
# Makefile, which exports CYCDIR, so all is well.
#
# This file should be called from the directory where you want the results
# of building the Cyclone library and/or compiler to be put.
# By using flags, variables, etc., this file can be used to build
# bootstrap iterations, compilers for other targets, debug/profile versions, etc

include $(CYCDIR)/Makefile.inc
VPATH=$(CYCDIR)/lib $(CYCDIR)/src $(CYCDIR)
export CYCFLAGS
ifndef UPDATEARCH
UPDATEARCH:=$(ARCH)
endif

# For bootstrapping, may want to override these with something appropriate
CYCC:=$(CYCDIR)/bin/$(CYCCOMP)
CYCLEX:=$(CYCDIR)/bin/cyclex$(EXE)
CYCBISON:=$(CYCDIR)/bin/cycbison$(EXE)
INC_PATH:=. include $(CYCDIR)/lib $(CYCDIR)/src $(CYCDIR)/include
LIB_PATH:=$(CYCDIR)/lib
LIBR:=$(CYCLIB)

# Note, the -B arguments ensure that we use the correct cyc_include.h.
#   If cyc_include.h is being changed, the new version should be in
#   lib/cyc_include.h; the -B$(LIB_PATH) makes sure we use that one.
#   On the other hand if there is no lib/cyc_include.h, then a rule
#   below will copy bin/lib/cyc-lib/cyc_include.h to the current
#   directory, and the -B. ensures we use that one.
override CYCFLAGS += $(addprefix -I, $(INC_PATH)) -B. -B$(LIB_PATH) -save-c 

# cross compilation -- will be changed to use -b shortly
ifneq ($(UPDATEARCH),$(ARCH))
override CYCFLAGS += -use-cpp '$(addprefix $(CYCDIR)/config/, cyccpp arch/$(ARCH) arch/$(UPDATEARCH))'
endif

CYC_SRCS := $(addsuffix .cyc, $(CYCLONE_SRCS))

all: libs $(CYCCOMP) cycdoc$(EXE) buildlib$(EXE) 

libs: $(CYCLIB) nogc.a $(RUNTIME).$(O)

cfiles: cstubs.c $(C_SRCS) cycdoc.c buildlib.c $(C_LIBS) $(RUNTIME).c nogc.c precore_c.h

cstubs.c cycstubs.cyc: libc.cys
	-mkdir include
	tar -z -xf $(CYCDIR)/bin/genfiles/$(UPDATEARCH).headers.tgz -C include
	$(CYCDIR)/bin/buildlib -d include -finish $<
	find include -name '\*.i[BC]' -exec rm \{\} \;
	mv include/cstubs.c .
	mv include/cycstubs.cyc .

libc.cys:
	(test -e $(CYCDIR)/lib/libc.cys && cp $(CYCDIR)/lib/libc.cys $@) || cp $(CYCDIR)/bin/cyc-lib/libc.cys $@

$(CYCCOMP): $(O_SRCS) $(LIBR) install_path.$(O)
ifdef MS
#FIX: Ignore fewer flags.
	cl /Fe$@ $(CYC_LIB_PATH)/snprintf.obj $^ $(CYCDIR)/bin/lib/cyc-lib/gc.lib
else
	$(CYCC) $(CYCFLAGS) -v -L. -B. -B$(CYCDIR)/bin/lib/cyc-lib -o $@ $^ $(LDFLAGS)
endif

# The -L. makes sure that we pick up the libcyc.a of the current
# directory.  The -B. makes sure we use the runtime_cyc.o of the
# current directory, and the second -B makes sure we pick up the gc.a
# of the current $(CYCDIR), and we avoid the libcyc.a and gc.a of any
# version of Cyclone currently installed in the usual place.
# Why don't these use $(CYCFLAGS) -- because that has -save-c which is
#   irrelevant and the -B flags used there are to find cyc_include.h,
#   not the .a files.
cycdoc$(EXE): $(addsuffix .$(O), $(CYCDOC_SRCS))
	$(CYCC) -v -L. -B. -B$(CYCDIR)/bin/lib/cyc-lib -o $@ $^ $(LDFLAGS)

buildlib$(EXE): $(addsuffix .$(O), $(BUILDLIB_SRCS)) install_path.$(O)
	$(CYCC) -v -L. -B. -B$(CYCDIR)/bin/lib/cyc-lib -o $@ $^ $(LDFLAGS)

install_path.c: $(CYCDIR)/.version $(CYCDIR)/Makefile.inc
	 (echo "char *Carch = \"$(ARCH)\";"; \
	  echo "char *Cdef_inc_path = \"$(INC_INSTALL)\";"; \
	  echo "char *Cdef_lib_path = \"$(LIB_INSTALL)\";"; \
	  echo "char *Ccomp = \"$(CC)\";"; \
	  version=`cat $<`; \
	  echo "char *Cversion = \"$$version\";") > $@

$(CYCLIB): $(O_LIBS) cstubs.$(O)
ifdef MS
	lib /out:$@ $^
else
	-$(RM) -f $@
ifdef LC_FLAG
	$(CYCC) $(LC_FLAG) -o $@ $^
else
	ar rc $@ $^
	@echo Trying ranlib, if not found, probably ok to ignore error messages
	-ranlib $@
endif
endif

nogc.a: nogc.o
	ar rc $@ $^
	@echo Trying ranlib, if not found, probably ok to ignore error messages
	-ranlib $@

cyc_include.h: $(CYCDIR)/bin/lib/cyc-lib/cyc_include.h
	cp $< $@

core.h: $(CYCDIR)/include/core.h
	cp $< $@

precore_c.h: core.h $(CYCC) cyc_include.h
	$(CYCC) $(CYCFLAGS) -stopafter-toc -pp -D_CYC_GENERATE_PRECORE_C_ -nocyc -noremoveunused -noexpandtypedefs -o $@ -x cyc $<

%.cyc: %.cyl $(CYCLEX)
	$(CYCLEX) $< $@
%_tab.cyc: %.y $(CYCBISON)
	$(CYCBISON) -d $< -o $@
%_tab.h: %.y $(CYCBISON)
	$(CYCBISON) -d $< -o $(patsubst %.h,%.cyc,$@)
%.c: %.cyc $(CYCC) cyc_include.h
	$(CYCC) $(CYCFLAGS) -D__FILE2__=\"$(notdir $<)\" -c -o $@ -stopafter-toc $<
%.$(O): %.cyc $(CYCC) cyc_include.h
	$(CYCC) $(CYCFLAGS) -D__FILE2__=\"$(notdir $<)\" -c -o $@ $<
# For runtime_cyc.c and nogc.c and cstubs.c
%.$(O): %.c precore_c.h cyc_include.h
	$(CC) $(CFLAGS) -I. -c -o $@ $<

ifdef MS
%.obj: %.c precore_c.h cyc_include.h
	cl /I$(CYCDIR) /Dinline=__inline /c /w /nologo /Fo$@ $^
endif

# Always use the original compiler to avoid circularities
# Note: In most cases, it would be correct to share .d files
# Note: depends on cstubs.c so header files get built first
%.d: %.cyc cstubs.c
	$(CYCDIR)/bin/$(CYCCOMP) -M -MG $(CYCFLAGS) $< > $@

ifndef NODEPS
-include $(addsuffix .d, $(CYCLONE_LIBS) $(CYCLONE_SRCS) cycdoc buildlib)
endif
