# Makefile
#
# The makefile expects the following override make variables to be specified
# by the caller:
#
# TARGET_SYSTEM
#	The target platform to compile the CodeMirror for.  If this is not
#	defined, then the this makefile will recursively invoke itself with
#	all available target system IDs.
#
# HOST_SYSTEM
#	The host system to compile for.  If this is not specified, then a
#	script is executed to determine the host system automatically.
#
# Valid values for host and target systems : 
#   - LINUX_X86(_64) 32bit/64bit linux host/target 
#   - WIN32/WIN64 32bit/64bit windows host/target


# Determine the host system.
ifndef HOST_SYSTEM
  HOST_SYSTEM = auto
endif
ifeq ($(HOST_SYSTEM),auto)
  HOST_SYSTEM := $(shell ./HostSystem.sh)
endif
ifeq ($(HOST_SYSTEM),)
  $(error Host system not recognized)
endif

BASEDIR = .

# List of supported target systems.

# Determine the TARGET_SYSTEM for LINUX hosts
ifneq (,$(findstring LINUX,$(HOST_SYSTEM)))
  ifeq ($(shell uname -m),x86_64)
    TARGET_SYSTEMS += LINUX_X86_64
    PIC = -fpic
  else
    TARGET_SYSTEMS += LINUX_X86
    # PIC does not work on x86 because of TTMATH asm code.
    PIC =
  endif
endif

# Determine the TARGET_SYSTEM for Win32/Win64 hosts
ifneq (,$(findstring WIN,$(HOST_SYSTEM)))
    TARGET_SYSTEMS += WIN32 WIN64
endif

include Defs.mk

CM_CC_SOURCES = \
	Value.cc ValueBinary.cc Property.cc Hash.cc \
        Code.cc CodeUtil.cc CodeMirror.cc CodeParse.cc CodeFile.cc File.cc \
	Common.cc Util.cc RipeMD160.cc Number.cc Transform.cc PathMap.cc \
        Scan.cc ILUtil.cc ILHash.cc ILTransform.cc ProgText.cc

CM_SWIG_SOURCES = CM.swg

CMBUILD_CC_SOURCES = \
        CMBuild/Package.cc CMBuild/Scan.cc CMBuild/Project.cc

# EDG C++ frontend

EDG_C_SOURCES = \
	attribute.c c_gen_be.c cfe.c class_decl.c cmd_line.c const_ints.c \
	cp_gen_be.c debug.c decl_inits.c decl_spec.c declarator.c \
	decls.c def_arg.c disambig.c error.c expr.c exprutil.c extasm.c \
	fe_init.c fe_wrapup.c fixed_pt.c float_pt.c folding.c func_def.c \
	host_envir.c il.c il_alloc.c il_display.c il_read.c il_to_str.c \
	il_walk.c il_write.c inline.c layout.c lexical.c literals.c \
	lookup.c lower_c99.c lower_eh.c lower_il.c \
	lower_init.c lower_name.c macro.c mem_manage.c ms_attrib.c \
	overload.c pch.c pragma.c preproc.c scope_stk.c \
	src_seq.c statements.c symbol_ref.c symbol_tbl.c sys_predef.c \
	target.c templates.c trans_copy.c trans_corresp.c trans_unit.c \
	types.c

ifdef TARGET_SYSTEM

ALL_TARGETS = \
        $(CM_BUILD_DIR)/a.out \
        $(CM_BUILD_DIR)/code_dump \
        $(CM_BUILD_DIR)/CM.so \
        $(CM_LIB) \
        $(CMBUILD_LIB)

all: $(ALL_TARGETS)
	$(ECHO) executing all

$(foreach c,$(EDG_C_SOURCES),$(eval $(call compile_EDG,$(c))))

$(eval $(call compile_mk_errinfo,))

# CodeMirror targets

CC_SOURCES = $(CM_CC_SOURCES) Main.cc CodeDumpMain.cc

CC_SWIG_SOURCES = \
	$(patsubst %.swg,$(CM_BUILD_DIR)/%_wrap.cc,$(CM_SWIG_SOURCES)) \

$(foreach cc,$(CC_SOURCES),$(eval $(call compile_cc,$(cc))))
$(foreach cc,$(CC_SWIG_SOURCES),$(eval $(call compile_cc_swig,$(cc))))
$(foreach cc,$(CMBUILD_CC_SOURCES),$(eval $(call compile_cc_cb,$(cc))))

CM_OBJECTS = \
	$(patsubst %.cc,$(CM_BUILD_DIR)/%.$(OBJ_EXT),$(CM_CC_SOURCES)) \
	$(patsubst %.swg,$(CM_BUILD_DIR)/%_wrap.$(OBJ_EXT),$(CM_SWIG_SOURCES)) \
	$(patsubst %.c,$(EDG_BUILD_DIR)/%.$(OBJ_EXT),$(EDG_C_SOURCES))

CMBUILD_OBJECTS = \
	$(patsubst %.cc,$(CM_BUILD_DIR)/%.$(OBJ_EXT),$(CMBUILD_CC_SOURCES))

$(CM_BUILD_DIR)/a.out: $(CM_BUILD_DIR)/Main.$(OBJ_EXT) $(CM_LIB) $(NUMBER_LIB)
	$(CXX) -o $@ $^ $(CM_LIBS)

$(CM_BUILD_DIR)/code_dump: \
                $(CM_BUILD_DIR)/CodeDumpMain.$(OBJ_EXT) $(CM_LIB) $(NUMBER_LIB)
	$(CXX) -o $@ $^ $(CM_LIBS)

$(CM_BUILD_DIR)/CM.so: $(CM_OBJECTS)
	$(CXX) -shared -o $@ $^ $(CM_LIBS)

$(CM_LIB): $(CM_OBJECTS)
	@ $(RM) $@
	$(AR) qcs $@ $^

$(CMBUILD_LIB): $(CMBUILD_OBJECTS)
	@ $(RM) $@
	$(AR) qcs $@ $^

mapm/libmapm.a:
	$(MAKE) -C mapm libmapm.a

clean:
	$(RM) $(filter %.$(OBJ_EXT),$(CM_OBJECTS))
	$(RM) $(CM_BUILD_DIR)/a.out
	$(RM) $(CM_BUILD_DIR)/CM.so
	$(RM) $(CM_BUILD_DIR)/Main.$(OBJ_EXT)
	$(RM) $(CM_LIB)
	$(RM) $(CC_SWIG_SOURCES)
	$(MAKE) -C testing \
          HOST_SYSTEM=$(HOST_SYSTEM) TARGET_SYSTEM=$(TARGET_SYSTEM) clean

distclean: clean
	$(RM) $(EDG_ERROR_FILES)
	$(RM) $(patsubst %.$(OBJ_EXT),%.d,$(filter %.$(OBJ_EXT),$(CM_OBJECTS)))
	$(RM) $(CM_BUILD_DIR)/Main.d
	$(RM) $(EDG_BUILD_DIR)/mk_errinfo
	$(RM) $(EDG_BUILD_DIR)/error_files
	$(MAKE) -C testing \
          HOST_SYSTEM=$(HOST_SYSTEM) TARGET_SYSTEM=$(TARGET_SYSTEM) distclean
	-rmdir $(EDG_BUILD_DIR)
	-rmdir $(CM_BUILD_DIR)

test: $(CM_LIB) $(CMBUILD_LIB)
	$(MAKE) -C testing \
          HOST_SYSTEM=$(HOST_SYSTEM) TARGET_SYSTEM=$(TARGET_SYSTEM) test

else
# TARGET_SYSTEM not defined, recurse over TARGET_SYSTEMS.

define build_target
$(1):
	+@ $(foreach target_system,$(TARGET_SYSTEMS),\
          $(MAKE) HOST_SYSTEM=$(HOST_SYSTEM) TARGET_SYSTEM=$(target_system) \
          $(1) &&) :
endef
$(foreach target,all clean distclean test,\
	$(eval $(call build_target,$(target))))

endif # TARGET_SYSTEM not defined

$(CM_BUILD_DIR)/%_wrap.cc: %.swg
	@ $(RM) $@
	$(SWIG) -c++ -lua -o $@ $^

tags:
	@ $(RM) tags
	$(CTAGS) --extra=fq -R . $(EDG_DIR)

etags:
	@ $(RM) TAGS
	$(CTAGS) -ea --extra=+q --fields=+fksaiSz -R . $(EDG_DIR)

docs: 
	@ mkdir -p docs
	@ rm -rf docs/*
	doxygen codemirror.dox

expand:
	@ $(RM) expand.backup.tar
	tar cf expand.backup.tar testing include mapm ttmath $(EDG_DIR)
	for f in `\
	    find . -name '*.h'; \
	    find . -name '*.c'; \
	    find . -name '*.cc'; \
	    find $(EDG_DIR) -name '*.h'; \
	    find $(EDG_DIR) -name '*.c'`; \
	do \
	  expand -i $$f >$$f.expand; \
	  if ! cmp -s $$f $$f.expand; then \
	    mv $$f.expand $$f; \
	    echo $$f expanded.; \
	  else \
	    rm $$f.expand; \
	  fi; \
	done

wc:
	@ wc -l \
          $(CM_CC_SOURCES) \
          $(CM_SWIG_SOURCES) \
          $(CMBUILD_CC_SOURCES) \
          $(BASEDIR)/include/CM/*.h \
          $(BASEDIR)/include/CM/*/*.h \
          $(BASEDIR)/include/CMBuild/*.h

.PHONY: all etags tags clean docs expand

