# Makefile for the Linux iSCSI driver
# Copyright (C) 2001 Cisco Systems, Inc.
# maintained by linux-iscsi-devel@lists.sourceforge.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# See the file COPYING included with this distribution for more details.

#
# 
ifneq ($(KERNELRELEASE),)
obj-m				:=	iscsi_sfnet.o
iscsi_sfnet-objs		:= 	iscsi-initiator.o 
iscsi_sfnet-objs		+=	iscsi-attr.o \
					iscsi-probe.o \
					iscsi-login.o \
					iscsiAuthClient.o \
					iscsiAuthClientGlue.o \
					iscsi-crc.o \
					iscsi-session.o \
					iscsi-timer.o \
					iscsi-task.o \
					iscsi-portal.o \
					iscsi-ioctl.o \
					iscsi-network.o \
					iscsi-recv-pdu.o \
					iscsi-xmit-pdu.o \
					iscsi-recovery.o


ISCSI_MODFLAGS :=
#
# This helps with some of the portability ifdefs in the code.
# 
ISCSI_MODFLAGS += -DLINUX=1 -I$(obj) -Idrivers/scsi -Werror

ifeq ($(CONFIG_ISCSI_DEBUG),y)
ISCSI_MODFLAGS += -DDEBUG=1
endif

EXTRA_CFLAGS    += $(ISCSI_MODFLAGS)

## THE KERNEL MAKEFILE ENDS HERE!!!
else
## THE USER MAKEFILE BEGINS !!!

# for compiling the daemon and utils
OS:=$(shell uname)
ARCH:=$(shell uname -m)
OSTYPE:=linux

# Where to install files that must be relative to the root dir.
# This is a prefix prepended before the pathname, and is
# normally unset.  It would be set for such things as diskless
# clients, where the driver is being installed on the server
# for a client.
ROOT:=
export ROOT

# Where to install the relocatable files (daemon, utilities, and man pages)
BASEDIR:=/
export BASEDIR

# We need to have the kernel headers installed in order to compile.
# You can specify a TOPDIR for your Linux kernel here, or if you don't
# we'll look for it in a few likely places later.
TOPDIR:=

# We also need the pathname of the kernel .config file to use.
# You can specify a .config for your Linux kernel here, or if you don't
# we'll look for it in a few likely places later.
KERNEL_CONFIG:=

# The rest of this Makefile shouldn't need to be modified

# record the version of the running kernel
KERNEL_VPSE:=$(shell uname -r)

# Try to find the top of the Linux kernel source tree for the running kernel
ifeq ($(TOPDIR),)
  ifeq ($(wildcard /lib/modules/$(KERNEL_VPSE)/build/.),/lib/modules/$(KERNEL_VPSE)/build/.)
    TOPDIR:=/lib/modules/$(KERNEL_VPSE)/build
  endif
  ifeq ($(TOPDIR),)
    $(warning Linux kernel source must be installed to compile this code.)
    $(error Could not find the top of the linux kernel source tree.)
  endif
endif

# record the kernel source version
KERNEL_VERSION:=$(shell awk -F"[ \t]*=[ \t]*" '$$1 == "VERSION" { print $$2 }' $(TOPDIR)/Makefile | sed -e 's/[ \t\n]*//g')
KERNEL_PATCHLEVEL:=$(shell awk -F"[ \t]*=[ \t]*" '$$1 == "PATCHLEVEL" {print $$2}' $(TOPDIR)/Makefile | sed -e 's/[ \t\n]*//g')
KERNEL_SUBLEVEL:=$(shell awk -F"[ \t]*=[ \t]*" '$$1 == "SUBLEVEL" {print $$2 }' $(TOPDIR)/Makefile | sed -e 's/[ \t\n]*//g')
KERNEL_EXTRAVERSION:=$(shell awk -F"[ \t]*=[ \t]*" '$$1 == "EXTRAVERSION" {print $$2 }' $(TOPDIR)/Makefile | sed -e 's/[ \t\n]*//g')
KERNEL_SRC_VPSE:=$(KERNEL_VERSION).$(KERNEL_PATCHLEVEL).$(KERNEL_SUBLEVEL)$(KERNEL_EXTRAVERSION)

## THE USER MAKEFILE ENDS !!!

# Try to find the kernel's config if the user didn't tell us where to find it.
# People who compile their own kernels will have a .config, as will some
# distributions that only ship one kernel binary, or that use separate
# kernel source for each kernel binary.  Redhat uses the same kernel source
# for multiple kernel binaries.

# the standard config file location is $(TOPDIR)/.config
ifeq ($(wildcard $(TOPDIR)/.config),$(TOPDIR)/.config)
  KERNEL_CONFIG:=$(TOPDIR)/.config
endif


# for compiling the daemon and utils 
CC:=gcc
CFLAGS:= -Wall -Wstrict-prototypes -O2 -DLINUX=1
LDFLAGS:= 
# Override path below if you have installed libsysfs on any other path.
SYSFS_LIB_PATH:= /usr/local/lib
LIBSYSFS:= -lsysfs
# the module gets most flags from the kernel Makefile, but we must add a few as well
ISCSIMODFLAGS:=-DLINUX=1 -I$(TOPDIR)/drivers/scsi

PWD         := $(shell pwd)

# assume object dirs should go under the current directory, unless told
# otherwise
OBJ:=$(CURDIR)

ifdef DEBUG
OBJDIR:=$(OBJ)/$(OS)-$(ARCH)/dbg-obj
KOBJDIR:=$(PWD)
CLEANDIRS:=$(OBJ)/$(OS)-$(ARCH)/dbg-obj 
CFLAGS += -g -DDEBUG
LDFLAGS += -g
ISCSIMODFLAGS += -DDEBUG=1
ifdef ATTR_DEBUG
CFLAGS += -g -DDEBUG -DATTR_DEBUG
ISCSIMODFLAGS += -DDEBUG=1 -DATTR_DEBUG=1
endif
else
KOBJDIR:=$(PWD)
OBJDIR:=$(OBJ)/$(OS)-$(ARCH)/obj
CLEANDIRS:=$(OBJ)/$(OS)-$(ARCH)/obj 
CFLAGS += -fomit-frame-pointer
endif

.PHONY: all module daemons utils tools kernel user permissions clean tar dist release \
         checklocal version newversion install remove uninstall dirs

# default target
all:: dirs module daemons utils tools permissions checkkernel checkscsi checkcrypto
module: dirs checkkernel 
daemons:  dirs $(OBJDIR)/iscsid
utils: dirs $(OBJDIR)/iscsi-device $(OBJDIR)/iscsi-iname $(OBJDIR)/iscsi-ls $(OBJDIR)/init $(OBJDIR)/iscsi-id
#
test: dirs $(OBJDIR)/bindings

# distributors usually want these targets when building packages
user: dirs daemons utils permissions
kernel: dirs checkkernel checkscsi checkcrypto module

endif

export OBJDIR
export KOBJDIR

.SUFFIXES:

MODULE_SRCS:=iscsi-initiator.c iscsi-attr.c iscsi-probe.c iscsi-login.c iscsiAuthClient.c iscsiAuthClientGlue.c iscsi-crc.c iscsi-session.c iscsi-timer.c iscsi-task.c iscsi-portal.c iscsi-ioctl.c iscsi-network.c iscsi-recv-pdu.c iscsi-xmit-pdu.c iscsi-recovery.c
DAEMON_SRCS:=iscsid.c iscsi-linux.c iscsi-login.c iscsi-io.c iscsi-config.c iscsi-discovery.c iscsi-bindings.c \
               string-buffer.c iscsiAuthClient.c iscsiAuthClientGlue.c md5.c
#Install openslp release 1.1.4 and onwards on the system and uncomment the follo
#wing line to enable SLP discovery for iSCSI.
#ENABLE_SLP:= 1
ifeq ($(ENABLE_SLP),1)
CFLAGS+=-DSLP_ENABLE=1
LDFLAGS+=-lslp
DAEMON_SRCS += iscsi-slp-discovery.c
endif

UTIL_SRCS:=iscsi-iname.c md5.c iscsi-device.c iscsi-ls.c init.c iscsi-network-boot.c iscsi-id.c
UTIL_OBJS:=$(UTIL_SRCS:%.c=$(OBJDIR)/%.o)
DAEMON_OBJS:=$(DAEMON_SRCS:%.c=$(OBJDIR)/%.o)
KDIR        := /lib/modules/$(shell uname -r)/build

export ISCSIMODFLAGS
# Make all objects depend on the Makefile
$(DAEMON_OBJS): Makefile
$(UTIL_OBJS): Makefile

install: module daemons utils
	@./install.sh

remove uninstall:
	@./remove.sh

echomodsrcs:
	@echo $(MODULE_SRCS)

# warn the user if the running kernel version
# doesn't match the $TOPDIR/Makefile version
checkkernel:
	@printf "\nNote: using kernel source from $(TOPDIR)\ncontaining kernel version $(KERNEL_SRC_VPSE)\n\n" | fmt -
	@if [ "$(KERNEL_CONFIG)" ] ; then \
                printf "Note: using kernel config from $(KERNEL_CONFIG)\n\n" | fmt - ; \
        else \
	   ( printf "Warning: failed to find a kernel config file for $(KERNEL_SRC_VPSE).\n" ; \
             printf "The iSCSI kernel module may fail to load or run properly.\n\n"; ) | fmt - ; \
        fi
        @if [ "$(KERNEL_VERSION).$(KERNEL_PATCHLEVEL)" = "2.4" ] ; then \
            ( printf "\nError: this iSCSI driver does not support 2.4 kernels.\n" ; \
              printf "You must upgrade your kernel to 2.6 or later\n" ; \
              printf "in order to use this driver.\n\n" ; ) | fmt - ; \
            exit 1; \
        fi
	@if [ "$(KERNEL_SRC_VPSE)" != "$(KERNEL_VPSE)" ] ; then\
            (   echo "Warning: $(TOPDIR) contains kernel version $(KERNEL_SRC_VPSE)," ; \
                echo "but kernel version $(KERNEL_VPSE) is currently running.";\
                echo "This mismatch may prevent the iSCSI module from loading onthe"; \
                echo "running kernel due to unresolved symbols, or may cause problems" ; \
                echo "during the operation of the iSCSI driver.  The iSCSI driver will" ; \
                echo "be built for kernel version $(KERNEL_SRC_VPSE)." ; \
                echo "If you wish to build the iSCSI driver for the kernel that is" ; \
                echo "currently running, you must install the appropriate kernelsource"; \
                echo "and rebuild the iSCSI driver."; \
                echo ; ) | fmt - ; \
        fi;

# Error out if there is no scsi support in the kernel
checkscsi:
	@if [ -n "$(KERNEL_CONFIG)" ] ; then \
	SCSI=`grep 'CONFIG_SCSI=' $(KERNEL_CONFIG)|awk -F'=' '{print $$2}'`; \
	if [ "$$SCSI" != "y" -a "$$SCSI" != "m" -a "$$SCSI" != "unknown" ] ; then \
		echo ; \
		echo "Error: your kernel does not appear to support SCSI." ; \
		echo "For iSCSI to function, you must rebuild your kernel with either" ; \
		echo "SCSI support compiled into the kernel, or with SCSI support as a module." ; \
		echo ; \
		exit 1;\
	fi \
	fi

checkcrypto:
	@if [ -n "$(KERNEL_CONFIG)" ] ; then \
	CRYPTO=`grep 'CONFIG_CRYPTO=' $(KERNEL_CONFIG)|awk -F'=' '{print $$2}'`; \
	MD5=`grep 'CONFIG_CRYPTO_MD5=' $(KERNEL_CONFIG)|awk -F'=' '{print $$2}'` ; \
	if [ "$$CRYPTO" != "y" -a "$$CRYPTO" != "unknown" ]; then \
		echo ; \
		echo "Error: your kernel does not appear to support CRYPTO API." ; \
		echo "For iSCSI to function, you must rebuild your kernel with" ; \
		echo "CRYPTO API support compiled into the kernel." ; \
		echo ; \
		exit 1;\
	elif [ "$$MD5" != "y" -a "$$MD5" != "m" -a "$$MD5" != "unknown" ]; then \
		echo; \
		echo "Error: your kernel does not appear to support MD5." ; \
		echo "For iSCSI to function, you must rebuild your kernel with" ; \
		echo "MD5 support compiled into the kernel." ; \
		echo ; \
		exit 1;\
	fi \
	fi

# compile daemon/utility code and auto-generate dependencies (and make missing prereqs cause a rebuild,
# not an error)
$(OBJDIR)/%.o : %.c
	@mkdir -p $(OBJDIR)
	$(CC) $(CFLAGS) -MMD -c -o $(OBJDIR)/$*.o $*.c
	@if [ ! -f $(OBJDIR)/$*.d -a -f $*.d ] ; then \
		printf "$(OBJDIR)/" > $(OBJDIR)/$*.d ; \
		cat $*.d >> $(OBJDIR)/$*.d && rm -f $*.d ; \
	fi
	@cp -f $(OBJDIR)/$*.d $(OBJDIR)/$*.dep
	@sed -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' -e 's/^ *//' -e '/^$$/ d' -e 's/$$/:/' < $(OBJDIR)/$*.d >> $(OBJDIR)/$*.dep


$(OBJDIR)/iscsid: $(DAEMON_OBJS)
	$(CC) $(LDFLAGS)  $(DAEMONFLAGS) -o $@ $^
# includes TOPDIR/include/scsi/scsi_ioctl.h
$(OBJDIR)/iscsi-device: iscsi-device.c Makefile
	$(CC) $(CFLAGS) -I$(TOPDIR)/include -o $@ $<

$(OBJDIR)/iscsi-id: $(OBJDIR)/iscsi-id.o
	$(CC) $(CFLAGS) -L $(SYSFS_LIB_PATH) -o $@ -static $< $(LIBSYSFS)

$(OBJDIR)/iscsi-ls: iscsi-ls.c Makefile
	$(CC) $(CFLAGS) -I$(TOPDIR)/include -o $@ $<

# Link the iscsi-iname utility
$(OBJDIR)/iscsi-iname: $(OBJDIR)/iscsi-iname.o $(OBJDIR)/md5.o
	$(CC) $(CFLAGS) -o $@ $^

# Make the init utility. This needs to be statically compiled for initrd.
$(OBJDIR)/init: $(OBJDIR)/init.o $(OBJDIR)/iscsi-network-boot.o
	$(CC) $(CFLAGS) -static -o $@ $^

dirs:
	@mkdir -p $(OBJDIR) 

permissions:
	@chmod 744 rc.iscsi
	@chmod 744 mkinitrd.iscsi
	@chmod 744 install.sh
	@chmod 744 remove.sh
	@chmod 744 iscsi-mountall
	@chmod 744 iscsi-umountall
clean:
	rm -rf $(OBJDIR) $(CLEANDIRS) *.o *.ko *.mod.c

module: 
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules;

