##*****************************************************************************
##                             INTEL CONFIDENTIAL
## Copyright(C) 2001-2010 Intel Corporation. All Rights Reserved.
## The source code contained  or  described herein and all documents related to
## the source code ("Material") are owned by Intel Corporation or its suppliers
## or licensors.  Title to the  Material remains with  Intel Corporation or its
## suppliers and licensors. The Material contains trade secrets and proprietary
## and  confidential  information of  Intel or its suppliers and licensors. The
## Material  is  protected  by  worldwide  copyright  and trade secret laws and
## treaty  provisions. No part of the Material may be used, copied, reproduced,
## modified, published, uploaded, posted, transmitted, distributed or disclosed
## in any way without Intel's prior express written permission.
## No license  under any  patent, copyright, trade secret or other intellectual
## property right is granted to or conferred upon you by disclosure or delivery
## of the Materials,  either expressly, by implication, inducement, estoppel or
## otherwise.  Any  license  under  such  intellectual property  rights must be
## express and approved by Intel in writing.
##
##*****************************************************************************
## Content:
##     Intel(R) Math Kernel Library C-style DFT examples creation and run
##*****************************************************************************

help:
	@echo "To run DFTC examples:"
	@echo "  make {lib32|so32|libem64t|soem64t|lib64|so64}"
	@echo "       [compiler=compiler_name]"
	@echo "       [interface=interface_name]"
	@echo "       [threading=threading_name]"
	@echo "       [omp=omp_name]"
	@echo "       [parallel=parallel_name]"
	@echo "       [function=name]"
	@echo
	@echo "To get report on run examples:"
	@echo "  make report"
	@echo
	@echo "To clean results:"
	@echo "  make clean"
	@echo
	@echo "To get help just run make or:"
	@echo "  make help"
	@echo
	@echo "Where:"
	@echo "  lib% targets for static and so% for dynamic linkage"
	@echo
	@echo "  compiler_name  - {gnu|pgi|intel}"
	@echo "                   Default value is intel"
	@echo "                   Intel(R) C Compiler as default"
	@echo
	@echo "  interface_name - {lp64|ilp64} (only for Intel(R) 64 and IA64)"
	@echo "                   Default value is lp64"
	@echo
	@echo "  threading_name - {parallel|sequential}"
	@echo "                   Default value is parallel"
	@echo
	@echo "  omp_name       - {iomp5|guide} (if parallel=intel)"
	@echo "                   {iomp5|gomp}  (if parallel=gnu)"
	@echo "                   pgmp          (if parallel=pgi)"
	@echo "                   Default value is iomp5"
	@echo
	@echo "  parallel_name  - intel (default value)"
	@echo "                   pgi   (only if compiler=pgi)"
	@echo "                   gnu   (if compiler=gnu)"
	@echo
	@echo "  name           - function name"
	@echo "                   Please see dftc.lst file"
	@echo
	@echo "Additional macros:"
	@echo "  MKLROOT        - MKL root directory to be used for compilation"
	@echo "                   of examples"
	@echo "                   Default value is current MKL root directory"
	@echo "                   located at ../.."
	@echo
	@echo "  MKLRUNLIB_PATH - MKL lib directory to be used to run examples"
	@echo "                   in case of dynamic linkage"
	@echo "                   Default value is current MKL libs located at"
	@echo '                   $$(MKLROOT)/lib/$$(IA)'
	@echo
	@echo "  LIB_PATH       - If you are using gnu or pgi threading layer,"
	@echo "                   specify path to libraries: libgomp, libpgmp"
	@echo "                   or add needed path to LD_LIBRARY_PATH"
	@echo
	@echo "N.B. To run lib32 or so32 examples on Pentium(R) III"
	@echo "  using Intel 11.x compiler (or earler) add to make-arguments:"
	@echo "       TARGET_ARCH=-xK"
	@echo "  Please refer to GNU, PGI and Intel compilers documentation"
	@echo "  for more details about target architecture specific options"
	@echo

##-----------------------------------------------------------------------------
## examples of using:
##
## make lib32 function=complex_1d_single_ex1
##     - build by Intel(R) C Compiler (as default) and
##       run COMPLEX_1D_SINGLE_EX1 example for 32-bit
##       applications, static linking
##
## make so32 compiler=gnu
##     - build by GNU C compiler and run all examples
##       of MKL for 32-bit applications, dynamic linking
##
## make lib64 compiler=gnu
##     - build by GNU C compiler and run all examples
##       of MKL for Intel(R) Itanium(R) processor family
##       applications, static linking
##
## make so64
##     - build by Intel(R) C Compiler (as default) and run
##       all examples of MKL for Intel(R) Itanium(R)
##       processor family applications, dynamic linking
##-----------------------------------------------------------------------------

MY_MAKEFILE := $(MAKEFILE_LIST)

ifeq (,$(RUN)$(IA))
  target := $(filter lib% so%,$(MAKECMDGOALS))
else
  target = $(RUN)$(IA)
endif

MY_WAY := $(findstring target-specific,$(.FEATURES))

ifndef MKLROOT
  MKLROOT = ../..
endif

DFTC = $(MKLROOT)/examples/dftc

include $(DFTC)/dftc.lst

COMMON = dfti_example_support.c dfti_example_status_print.c

RES_DIRNAME = _results

ifndef function
  function = $(DFT)
endif

RES = $(addsuffix .res,$(function))

ifeq (,$(filter gnu pgi,$(compiler)))
  override compiler = intel
  override parallel = intel
endif

ifeq (,$(filter lp64 ilp64,$(interface)))
  override interface = lp64
endif
ifeq (,$(findstring 32,$(target)))
  iface = $(interface)_
else
  override interface =
endif

ifeq (,$(filter parallel sequential,$(threading)))
  override threading = parallel
endif

ifeq (,$(filter gomp pgmp,$(omp)))
  override omp = iomp5
endif

ifeq (,$(filter gnu pgi,$(parallel)))
  override parallel = intel
  ifneq ($(omp),guide)
    override omp = iomp5
  endif
else
  ifeq ($(compiler)-$(parallel),gnu-gnu)
    ifneq ($(omp),gomp)
      override omp = iomp5
    endif
  else
    ifeq ($(compiler)-$(parallel),pgi-pgi)
      override omp = pgmp
    else
      override omp = iomp5
    endif
  endif
endif

ifeq ($(compiler),gnu)
  CC = gcc
  COPTS.32 = -m32
  COPTS.em64t = -m64
else
  ifeq ($(compiler),pgi)
    CC = pgcc
    COPTS.em64t = -tp x64
  else
    CC = icc
  endif
endif

IFACE_COMP_PART = intel

ifeq ($(compiler)-$(parallel),gnu-gnu)
  IFACE_THREADING_PART = gnu
else
  ifeq ($(compiler)-$(parallel),pgi-pgi)
    IFACE_THREADING_PART = pgi
  else
    IFACE_THREADING_PART = intel
  endif
endif

IFACE_LIB.32 = mkl_$(IFACE_COMP_PART)
ifeq ($(interface),ilp64)
  IFACE_LIB.em64t = mkl_$(IFACE_COMP_PART)_ilp64
  COPTS.em64t += -DMKL_ILP64
  IFACE_LIB.64 = mkl_$(IFACE_COMP_PART)_ilp64
  COPTS.64 += -DMKL_ILP64
else
  IFACE_LIB.em64t = mkl_$(IFACE_COMP_PART)_lp64
  IFACE_LIB.64 = mkl_$(IFACE_COMP_PART)_lp64
endif
IFACE_LIB = $(IFACE_LIB.$(IA))

COPTS = -w $(COPTS.$(IA))

ifeq ($(threading),sequential)
  threadname = $(threading)
  THREADING_LIB = mkl_sequential
  OMP_LIB =
else
  threadname = $(threading)_$(omp)
  THREADING_LIB = mkl_$(IFACE_THREADING_PART)_thread
  ifeq ($(omp),iomp5)
    OMP_LIB = -l$(omp)
  else
    ifneq ($(LIB_PATH),)
      OMP_LIB = -L$(LIB_PATH)
    endif
    OMP_LIB += -l$(omp)
  endif
endif

CORE_LIB = mkl_core

ifeq ($(compiler)-$(IFACE_THREADING_PART),pgi-pgi)
  COPTS += -mp -pgf90libs
endif

ifeq ($(compiler),pgi)
  COPTS += -Mnokeepobj
endif

ifeq ($(compiler),intel)
  COPTS += -vec-report0
endif

MKL_PATH = $(MKLROOT)/lib/$(IA)

ifndef MKLRUNLIB_PATH
  MKLRUNLIB_PATH = $(MKLROOT)/lib/$(IA)
endif

RES_DIR = $(RES_DIRNAME)/$(compiler)_$(iface)$(threadname)_$(target)

COMMON.obj = $(COMMON:%.c=$(RES_DIR)/%.o)

ifdef VERBOSE
  $(info )
  $(info MAKELEVEL=$(MAKELEVEL) target=$(target))
  $(info MKLROOT=$(MKLROOT) RES_DIR=$(RES_DIR))
  $(info compiler=$(compiler) interface=$(interface) threading=$(threading) \
         parallel=$(parallel) omp=$(omp))
endif

#------------------------------------------------------------------------------

.PHONY: lib32 so32 libem64t soem64t lib64 so64 \
	help run mkdir clean report \
	FORCE

.SUFFIXES:
.SUFFIXES: .c .o .res

vpath %.c $(DFTC)/source

ifeq ($(MY_WAY),target-specific$(RECURSION))

lib%: RUN = lib
so%: RUN = so

%32: IA = 32
%em64t: IA = em64t
%64: IA = 64

ifneq ($(LIB_PATH),)
lib%: RUNENV = LD_LIBRARY_PATH=$(MKLRUNLIB_PATH):$(LIB_PATH):$(LD_LIBRARY_PATH)
else
lib%: RUNENV = LD_LIBRARY_PATH=$(MKLRUNLIB_PATH):$(LD_LIBRARY_PATH)
endif
lib%: MKL_LIBS = $(MKL_PATH)/lib$(IFACE_LIB).a
lib%: MKL_LIBS += -Wl,--start-group
lib%: MKL_LIBS += $(MKL_PATH)/lib$(THREADING_LIB).a $(MKL_PATH)/lib$(CORE_LIB).a
lib%: MKL_LIBS += -Wl,--end-group

ifneq ($(LIB_PATH),)
so%: RUNENV = LD_LIBRARY_PATH=$(MKLRUNLIB_PATH):$(LIB_PATH):$(LD_LIBRARY_PATH)
else
so%: RUNENV = LD_LIBRARY_PATH=$(MKLRUNLIB_PATH):$(LD_LIBRARY_PATH)
endif
so%: MKL_LIBS = -l$(IFACE_LIB) -l$(THREADING_LIB) -l$(CORE_LIB)

lib32 so32 libem64t soem64t lib64 so64: run

else # using recursive MAKE if target-specific targets are unsupported

ifeq ($(RUN),so)
  ifneq ($(LIB_PATH),)
    RUNENV = LD_LIBRARY_PATH=$(MKLRUNLIB_PATH):$(LIB_PATH):$(LD_LIBRARY_PATH)
  else
    RUNENV = LD_LIBRARY_PATH=$(MKLRUNLIB_PATH):$(LD_LIBRARY_PATH)
  endif
  MKL_LIBS = -l$(IFACE_LIB) -l$(THREADING_LIB) -l$(CORE_LIB)
else
  ifneq ($(LIB_PATH),)
    RUNENV = LD_LIBRARY_PATH=$(MKLRUNLIB_PATH):$(LIB_PATH):$(LD_LIBRARY_PATH)
  else
    RUNENV = LD_LIBRARY_PATH=$(MKLRUNLIB_PATH):$(LD_LIBRARY_PATH)
  endif
  MKL_LIBS = $(MKL_PATH)/lib$(IFACE_LIB).a
  MKL_LIBS += -Wl,--start-group
  MKL_LIBS += $(MKL_PATH)/lib$(THREADING_LIB).a $(MKL_PATH)/lib$(CORE_LIB).a
  MKL_LIBS += -Wl,--end-group
endif

lib32:
	$(MAKE) -f $(MY_MAKEFILE) run IA=32 RUN=lib

so32:
	$(MAKE) -f $(MY_MAKEFILE) run IA=32 RUN=so

libem64t:
	$(MAKE) -f $(MY_MAKEFILE) run IA=em64t RUN=lib

soem64t:
	$(MAKE) -f $(MY_MAKEFILE) run IA=em64t RUN=so

lib64:
	$(MAKE) -f $(MY_MAKEFILE) run IA=64 RUN=lib

so64:
	$(MAKE) -f $(MY_MAKEFILE) run IA=64 RUN=so

endif

run: mkdir $(COMMON.obj) $(RES)

mkdir: FORCE
	@echo
	@mkdir -p $(RES_DIR)
	@echo See results in $(RES_DIR)
	@echo

$(RES_DIR)/%.o: %.c
	$(CC) $(COPTS) $(CFLAGS) $(TARGET_ARCH) \
	  -I$(MKLROOT)/include -c $< -o $@

%.res: %.c FORCE
	@echo
	# compile $*.c
	$(CC) $(COPTS) $(CFLAGS) $(LDOPTS) $(LDFLAGS) $(TARGET_ARCH) \
	  -I$(MKLROOT)/include \
	  $< \
	  $(COMMON.obj) \
	  -L$(MKL_PATH) $(MKL_LIBS) \
	  $(OMP_LIB) -lpthread -lm -o $(RES_DIR)/$*.out
	@echo
	# run $*.out
	$(RUNENV) \
	  $(RES_DIR)/$*.out $(DFTC)/data/$*.d > $(RES_DIR)/$@

report: FORCE
	@mkdir -p $(RES_DIRNAME)
	@echo
	@echo There are `ls $(DFTC)/source/*_ex[0-9]*.c | wc -l` \
	  examples in $(DFTC)/source
	@echo
	@for D in `ls -d $(RES_DIRNAME)/* 2>/dev/null`; do \
	  echo -n "In   $$D	Total run examples:" \
	    "`ls -d $$D/*.res 2>/dev/null | wc -l`"; \
	  echo -n "	and Passed: "; \
	  cat /dev/null $$D/*.res 2>/dev/null | grep -c PASSED | cat; \
	done

clean: FORCE
	rm -rf $(RES_DIRNAME)

FORCE: ;

#------------------------------------------------------------------------------
