#===============================================================================
# Copyright 2006 Intel Corporation.
#
# This software and the related documents are Intel copyrighted  materials,  and
# your use of  them is  governed by the  express license  under which  they were
# provided to you (License).  Unless the License provides otherwise, you may not
# use, modify, copy, publish, distribute,  disclose or transmit this software or
# the related documents without Intel's prior written permission.
#
# This software and the related documents  are provided as  is,  with no express
# or implied  warranties,  other  than those  that are  expressly stated  in the
# License.
#===============================================================================

##  Content:
##      Makefile for Intel(R) oneMKL FFTW2 MPI wrapper library.
##      This library allows to use Intel(R) oneMKL CDFT routines through MPI FFTW interface.
##******************************************************************************

help:
	@echo
	@echo "Usage: make libintel64 [<options>]"
	@echo
	@echo "Intel(R) oneAPI DPC++/C++ Compiler is the default compiler."
	@echo
	@echo "  libintel64"
	@echo "      A makefile target to build FFTW2 MPI interfaces to"
	@echo "      Intel(R) oneMKL for Intel(R) 64 architecture."
	@echo
	@echo "  <options>"
	@echo
	@echo "    mpi={intelmpi|mpich2|openmpi}"
	@echo "        Intel(R) MPI, MPICH, or Open MPI implementation of MPI will"
	@echo "        be used."
	@echo "        Default: intelmpi"
	@echo
	@echo "    compiler={intel|gnu}"
	@echo "        The C compiler 'icx' or 'gcc' will be used."
	@echo "        Default: intel"
	@echo
	@echo "    fname={a_name_|a_name|a_name__|A_NAME}"
	@echo "        The pattern for Fortran wrapper names, for example, we will have"
	@echo "            fftw_f77_mpi_()  when specifying 'fname=a_name_';"
	@echo "            fftw_f77_mpi()   when specifying 'fname=a_name';"
	@echo "            fftw_f77_mpi__() when specifying 'fname=a_name__';"
	@echo "            FFTW_F77_MPI()   when specifying 'fname=A_NAME'."
	@echo "        With no special options,"
	@echo "            g77 uses the pattern 'a_name__';"
	@echo "            ifx on Linux and gfortran use the pattern 'a_name_';"
	@echo "            ifx on Windows uses the pattern 'A_NAME'."
	@echo "        Default: a_name_"
	@echo
	@echo "    PRECISION={MKL_DOUBLE|MKL_SINGLE}"
	@echo "        The library will be built for double- or single-precision"
	@echo "        floating-point data type."
	@echo "        Default: MKL_DOUBLE"
	@echo
	@echo "    interface={lp64|ilp64}"
	@echo "        The lp64 interface uses the 32-bit integer type, while the"
	@echo "        ilp64 interface uses the 64-bit integer type."
	@echo "        Default: lp64"
	@echo
	@echo "    MKLROOT=<path>"
	@echo "        Intel(R) oneMKL installation directory."
	@echo "        Default: ../../../.."
	@echo
	@echo "    INSTALL_DIR=<path>"
	@echo "        The built library will be installed in <path>."
	@echo "        Default: \$$(MKLROOT)/lib"
	@echo
	@echo "    INSTALL_LIBNAME=<name>"
	@echo "        The name of the built library without the '.a' extension."
	@echo "        The default value depends on 'PRECISION' and 'interface' in use,"
	@echo "        for example, 'libfftw2x_cdft_DOUBLE_lp64'."
	@echo
	@echo "    mpidir=<path>"
	@echo "        MPI installation directory. MPI scripts are taken from"
	@echo "        \$$(mpidir)/bin. You need to set this variable only if the"
	@echo "        MPI scripts cannot be found in PATH. When using MPICH, make"
	@echo "        sure that the compiler in use is the same one that built MPICH."
	@echo "        This variable is not predefined."
	@echo
	@echo "    CFLAGS=<flags>"
	@echo "        Additional compilation flags."
	@echo "        This variable is not predefined."
	@echo
	@echo "    CPPFLAGS=<flags>"
	@echo "        Additional preprocessor flags."
	@echo "        This variable is not predefined."
	@echo
	@echo "    TARGET_ARCH=<flags>"
	@echo "        Additional architecture-specific flags."
	@echo "        This variable is not predefined."
	@echo
	@echo "    AR=<program>"
	@echo "        The specified archive-maintaining program will be used."
	@echo "        Default: $(AR)"
	@echo
	@echo "    ARFLAGS=<flags>"
	@echo "        The specified modifier flags will be given to \$$(AR)."
	@echo "        Default: $(ARFLAGS)"
	@echo
	@echo
	@echo "Usage example:"
	@echo
	@echo "  make libintel64"
	@echo "      This command builds double-precision FFTW2 MPI interfaces to"
	@echo "      Intel(R) oneMKL for Intel(R) 64 architecture using Intel(R) MPI"
	@echo "      and Intel(R) oneAPI DPC++/C++ Compiler. The built library"
	@echo "      'libfftw2x_cdft_DOUBLE_lp64.a' is installed in ../../../../lib."
	@echo "      The names of the interfaces are of lowercase letters with a"
	@echo "      trailing underscore, and the built library uses the 32-bit"
	@echo "      integer type."
	@echo

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

include fftw2x_cdft.lst

## Please use the command line parameters to override the values below
fname = a_name_
PRECISION = MKL_DOUBLE
MKLROOT = ../../../..
CFLAGS += -Wall -Werror -std=c99

ifeq ($(PRECISION),MKL_DOUBLE)
    PRE = _DOUBLE
else
    PRE = _SINGLE
endif

ifndef mpi
    mpi = intelmpi
else
    ifeq (,$(findstring $(mpi),intelmpi mpich2 openmpi))
        $(error "Set mpi to one of: intelmpi mpich2 openmpi")
    endif
endif

_DEF_FNAME = $(_DEF_FNAME_$(fname))

_DEF_FNAME_a_name   = -D_FNAME_NOUNDERSCORE
_DEF_FNAME_a_name_  =
_DEF_FNAME_a_name__ = -D_FNAME_SECOND_UNDERSCORE
_DEF_FNAME_A_NAME   = -D_FNAME_UPPERCASE

ifndef compiler
    compiler = intel
else
    ifeq (,$(findstring $(compiler),intel gnu))
        $(error "Set compiler to one of: intel gnu")
    endif
endif

ifeq ($(interface),ilp64)
    ILP_OPTS = -DMKL_ILP64
    ILP_EXT = _ilp64
else
    ILP_OPTS =
    ILP_EXT  = _lp64
endif

ifndef INSTALL_DIR 
INSTALL_DIR = $(MKLROOT)/lib
obj_path = ./obj$(PRE)_$(_IA)$(ILP_EXT)
else
obj_path = $(INSTALL_DIR)/obj$(PRE)_$(_IA)$(ILP_EXT)
endif

ifeq ($(mpi),intelmpi)
    ifdef mpidir
        _BD = $(mpidir)/bin/
    endif
    ifeq ($(compiler),intel)
        _CS = $(_BD)mpiicx
    endif
    ifeq ($(compiler),gnu)
        _CS = $(_BD)mpicc
    endif
endif

ifeq ($(mpi),mpich2)
    ifdef mpidir
        _BD = $(mpidir)/bin/
    endif
    ifeq ($(compiler),intel)
        _CS = $(_BD)mpicc -cc=icx
    endif
    ifeq ($(compiler),gnu)
        _CS = $(_BD)mpicc -cc=gcc
    endif
endif

ifeq ($(mpi),openmpi)
    ifdef mpidir
        _BD = $(mpidir)/bin/
    endif
    ifeq ($(compiler),intel)
        _CS = OMPI_CC=icx $(_BD)mpicc
    endif
    ifeq ($(compiler),gnu)
        _CS = OMPI_CC=gcc $(_BD)mpicc
    endif
endif

ifdef INSTALL_LIBNAME
    WRAPLIB_FFTW2X_CDFT = $(INSTALL_LIBNAME).a
else
    WRAPLIB_FFTW2X_CDFT = libfftw2x_cdft$(PRE)$(ILP_EXT).a
endif

.PHONY: libintel64

libintel64:
	$(MAKE) clean mkobjdir wraplib ILP_EXT=$(ILP_EXT) _IA=intel64

##---------------------------------------------------------------------------------
## Nested makefile
##---------------------------------------------------------------------------------

ifdef _IA

objs    = $(addsuffix .o ,$(WRAP))
objects = $(addprefix $(obj_path)/,$(objs))

ifeq (,$(findstring x$(interface),x xlp64 xilp64))
    $(warning "Using interface=lp64 instead of unknown $(interface)")
    ILP_OPTS =
    ILP_EXT  = _lp64
endif

.SUFFIXES:
.SUFFIXES: .c .o

vpath %.c wrappers

$(obj_path)/%.o: %.c
	$(_CS) -c $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $(ILP_OPTS) \
		$(_DEF_FNAME) -D$(PRECISION) -I$(MKLROOT)/include -I$(MKLROOT)/include/fftw $< -o $@

wraplib: $(objects)
	$(AR) $(ARFLAGS) $(INSTALL_DIR)/$(WRAPLIB_FFTW2X_CDFT) $^

mkobjdir:
	-mkdir -p $(obj_path)
	-mkdir -p $(INSTALL_DIR)

clean:
	-rm -rf $(obj_path)
	-rm -f $(INSTALL_DIR)/$(WRAPLIB_FFTW2X_CDFT)

endif
