# 
# Copyright (C) 2012, Edimax Technology Co. LTD. All Rights Reserved.
# 
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
# 
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

ifneq (true,$(parallel))
  .NOTPARALLEL:
endif

CONF_FILE = $(shell [ -f .config ] && echo .config)

ifeq ($(CONF_FILE),)
XCUR = $(shell echo $(CURDIR) | sed 's/\//\\\//g')

menuconfig all release: .config

.config:
	@sed 's/@TOP@/$(XCUR)/g' config.in > $@
	@echo ==========================================
	@echo generate .config
	@echo Please make again
	@echo ==========================================

distclean clean:

help:
	@echo '    all           -- Build all binaries'
	@echo '    distclean     -- Cleaning files before distribution'
	@echo '    clean         -- Cleaning created files'
else
#
# Here is the main Makefile
#
include .config

BUILD_BASE = Build.base

$(if $(wildcard $(BUILD_BASE)),,$(error "$(BUILD_BASE) is missing, bye bye."))

TOP = $(shell /bin/pwd)

include $(BUILD_BASE)

BUILD_DIR = $(SRCBASE)

SUB_BUILD_BASE = .sub_build.base

export MAKEFLAGS ?= -w

#LINUX_VERSION ?= 2_4
#MAKE_ARGS ?=
#MAKE_ARGS = -I$(TOP)/$(SRCBASE)

export LINUX_VERSION

ifneq ($(LINUX_DIR),"")
export 	LINUXDIR := $(LINUX_DIR)
export 	KBUILD_VERBOSE := 1
endif

COMP = lzma
VMLINUX = $(LINUX_DIR)/vmlinux
KERNELZ = $(BUILD_IMAGE_DIR)/zImage
#
# Install and target directories
#

export PLATFORMDIR := $(TOP)/$(PLATFORM)
export INSTALLDIR := $(PLATFORMDIR)/install

define STRIP_DEBUG_SYMBOLS
	@dbgsymf=$(basename $(1))_dbgsym$(suffix $(1)); \
	if [ "$(1)" -nt "$${dbgsymf}" ]; then \
	   echo "#- $0"; \
	   ls -ln $1 | awk '{printf "Orig  size: %10d bytes, %s\n",$$5,$$NF}'; \
	   cp -p -v $1 $$dbgsymf; $(STRIP) -d $(1); touch $$dbgsymf; \
	   ls -ln $1 | awk '{printf "Strip size: %10d bytes, %s\n",$$5,$$NF}'; \
	fi
endef

ROMFS_DIRS = \
	bin \
	sbin \
	lib \
	ro ro/etc ro/var/spool \
	etc \
	tmp \
	dev dev/pts \
	proc \
	usr/bin usr/sbin \
	mnt \
	var \
	home 

# EDX, SJC
export FULL_VERSION=$(CONFIG_EDX_VERSION)_$(BUILD_CODE)
#export FULL_VERSION=$(CONFIG_EDX_VERSION)

#
# SJC:
# The following lines are good reference
# I dont wanna remove them for the sake of keeping them for my further reference
#
#obj-clean := $(foreach obj,$(obj-y) $(obj-n),$(obj)-clean)
#obj-install := $(foreach obj,$(obj-y),$(obj)-install)
#
## separate the libraries which need to be built first
#obj-prelibs =$(filter nvram libbcmcrypto shared netconf libupnp libz libid3tag ffmpeg libbcm, $(obj-y)) 
## remaining libraries that are built next
#obj-postlibs := $(filter-out $(obj-prelibs), $(obj-y))

#
# Basic rules
#
all: not4release check_tool_chain check_kernel_config env burn
release: 4release menuconfig check_tool_chain check_kernel_config env burn

#$(TARGET_MP_DIR)/$(TARGET_MP): $(TARGET_UPG_DIR)/$(TARGET_UPG) boot_bin

#burn: upg boot_bin
burn: upg

boot_bin:
	$(Q)$(MAKE) $(MAKEFLAGS) -C $(BOOT_DIR)

upg: $(TARGET_UPG_DIR)/$(TARGET_UPG)

$(TARGET_UPG_DIR)/$(TARGET_UPG): tools_bin romfs kernel_bin 
	$(Q)$(MAKE) $(MAKEFLAGS) -C $(BUILD_IMAGE_DIR)

tools_bin:
	$(Q)$(MAKE) $(MAKEFLAGS) -C $(TOOLS_DIR)/src

#
# kernel Start
#
kernel_bin: check_kernel_config
	$(Q)$(MAKE) $(MAKEFLAGS) -C $(LINUX_DIR)

modules_bin:
	$(Q)$(MAKE) $(MAKEFLAGS) -C $(LINUX_DIR) modules
#	$(Q)$(MAKE) $(MAKEFLAGS) -C $(EDX_MODULES_DIR) 
#
# kernel End
#

#
# romfs Start
#
.PHONY: romfs
SYS_LIBS	= \
	ld-uClibc.so.0 \
	libcrypt.so.0 \
	libc.so.0 \
	libdl.so.0 \
	libm.so.0 \
	libnsl.so.0 \
	libpthread.so.0 \
	libresolv.so.0 \
	librt.so.0 \
	libutil.so.0

romfs: romfs_dirs modules_bin user_bin sys_libs
	mknod -m666 $(ROMFS_DIR)/dev/console    c   5  1
	$(Q)echo "FW "$(CUS_VERSION) > $(ROMFS_DIR)/ro/etc/version
	$(Q)echo "MODEL "$(CUS_MODEL_NAME) >> $(ROMFS_DIR)/ro/etc/version
	$(Q)echo "BOOT "$(BOOT_VERSION) >> $(ROMFS_DIR)/ro/etc/version
	$(Q)echo "BUILD "$(BUILD_CODE) >> $(ROMFS_DIR)/ro/etc/version
	$(Q)echo "FW_HEADER "$(FW_HEADER) >> $(ROMFS_DIR)/ro/etc/version
	$(Q)echo "WEB_HEADER "$(WEB_HEADER) >> $(ROMFS_DIR)/ro/etc/version
	#$(Q)find $(ROMFS_DIR) -name .svn -print | xargs rm -rf
	$(TOOLS_DIR)/nvcfg $(TOOLS_DIR)/$(DEFAULT_CONFIG_TXT) $(ROMFS_DIR)/$(ETC_RO)/$(DEFAULT_CONFIG_BIN) 1024 128
	$(Q)for dir in $($(BUILD_DIR)) ; do \
		$(MAKE) $(MAKEFLAGS) -C $$dir pre_romfs || exit $$?; \
	done && \
	$(Q)find $(ROMFS_DIR) -name .svn -print | xargs rm -rf
	$(MAKE) $(MAKEFLAGS) -C $(LINUXDIR)/../ pre_romfs
	#$(MAKE) $(MAKEFLAGS) -C $(LINUXDIR)/../ pre_romfs && \
	#$(TOOLS_DIR)/nvcfg $(TOOLS_DIR)/$(DEFAULT_CONFIG_TXT) $(ROMFS_DIR)/$(ETC_RO)/$(DEFAULT_CONFIG_BIN) 1024 128

romfs_dirs:
	$(Q)mkdir -p $(TARGET_UPG_DIR) && \
	mkdir -p $(TARGET_MP_DIR) && \
	rm -rf $(ROMFS_DIR) && \
	mkdir -p $(ROMFS_DIR) && \
	for i in $(ROMFS_DIRS); do \
		[ -d $(ROMFS_DIR)/$$i ] || mkdir -p $(ROMFS_DIR)/$$i; \
	done

sys_libs:
	$(Q)for i in $(SYS_LIBS); do \
		cp -f $(TOOL_CHAIN_DIR)/lib/$$i $(ROMFS_DIR)/lib || exit $$?; \
	done

#
# romfs End
#

#
# user_bin Start
#
user_bin: kernel_bin
	$(Q)$(MAKE) $(MAKEFLAGS) -C $(APPS_DIR) && \
	$(MAKE) $(MAKEFLAGS) -C $(APPS_DIR) pre_romfs || exit $$?
#
# user_bin End
#

#
# Start
#
CONFIG_LIST = \
	$(TOP)/srcbase/apps/src/ppp-2.4.2/pppd/plugins/pptp_plugin \
	$(TOP)/srcbase/apps/src/bridge-utils \
	$(TOP)/srcbase/apps/src/iptables-1.4.10 \
	$(TOP)/srcbase/apps/src/libpcap-0.7.2 \
	$(TOP)/srcbase/apps/src/busybox \
	$(TOP)/srcbase/apps/src/libupnp-1.6.18 \
	$(TOP)/srcbase/apps/src/igmpproxy-0.1 \
	$(TOP)/srcbase/apps/src/ez-ipupdate-3.0.10 \
	$(TOP)/srcbase/apps/src/dnrd-2.20.3 \
	$(TOP)/srcbase/apps/src/fping-2.4b2_to

ifeq ($(_IPV6_),y)
CONFIG_LIST += $(TOP)/srcbase/apps/src/openssl-0.9.7d
CONFIG_LIST += $(TOP)/srcbase/apps/src/radvd-1.7
endif

MAKE_ENV = \
	$(LINUX_DIR) \
	srcbase	\
	image/build_image \
	tools \
	srcbase/boot

env: $(SUB_BUILD_BASE) check_tool_chain
	$(Q)for dir in $(CONFIG_LIST) ; do \
		echo =================================; \
		echo Checking configuration for $$dir; \
		echo =================================; \
		echo ; \
		cd $$dir && ./EdxConfig.sh || exit $$?; \
		cd $(CURDIR); \
	done && \
	cd $(TOP) && \
	$(call BUILD_SUB_DIR,$(CURDIR),$(MAKE_ENV),make_env)

$(SUB_BUILD_BASE): $(BUILD_BASE) .config
	$(Q)echo "" > $(TOP)/$(SUB_BUILD_BASE) ; \
	echo "export TOP=$(TOP)" >> $(TOP)/$(SUB_BUILD_BASE) ; \
	echo "export _SUB_BUILD_BASE_=1" >> $(TOP)/$(SUB_BUILD_BASE) ; \
	echo "export GPL_BUILD=y" >> $(TOP)/$(SUB_BUILD_BASE) ; \
	echo "include $(TOP)/.config" >> $(TOP)/$(SUB_BUILD_BASE) ; \
	echo "include $(TOP)/$(BUILD_BASE)" >> $(TOP)/$(SUB_BUILD_BASE)

$(BUILD_BASE):
	######################################################################
	# Fatal error: missing $(BUILD_BASE)
	######################################################################
	@false

check_tool_chain: $(TOOL_CHAIN_DIR)/bin/$(CROSS_COMPILE)gcc
	$(Q)$(MAKE) $(MAKEFLAGS) -C $(shell dirname $(TOOL_CHAIN_DIR))
#
# End
#

# Preserve the debug versions of these and strip for release
#	$(call STRIP_DEBUG_SYMBOLS,$(LINUXDIR)/vmlinux)

DISTCLEAN = \
	$(BUILD_DIR) \
	tools \
	config \
	image/build_image \
	srcbase/kernel/modules/src

distclean: clean
	$(Q)for dir in $(DISTCLEAN) ; do \
		$(MAKE) $(MAKEFLAGS) -C $$dir distclean ; \
	done && \
	$(MAKE) $(MAKEFLAGS) -C tools distclean && \
	rm -rf $(IMAGE_DIR) .config $(SUB_BUILD_BASE) && \
	echo
#	find . -name $(SUB_BUILD_FILE) -print | xargs rm -f

clean:
	$(Q)for dir in $(BUILD_DIR) ; do \
		$(MAKE) $(MAKEFLAGS) -C $$dir clean ; \
	done && \
	$(MAKE) $(MAKEFLAGS) -C config clean && \
	rm -rf $(ROMFS_DIR) && \
	$(MAKE) $(MAKEFLAGS) -C $(BUILD_IMAGE_DIR) clean

conf mconf:
	+$(MAKE) -C config
	@./config/$@ ./config/Config.in
	# Also configure kernel
	#
	# SJC remark this to get rid of make menuconfig for kernel
	#
#	+$(MAKE) k$@

oldconf: .config
	+$(MAKE) -C config
	@./config/conf -o ./config/Config.in
	# Also configure kernel
	#
	# SJC remark this to get rid of make menuconfig for kernel
	#

#	+$(MAKE) k$@

kconf:
	+$(MAKE) -C $(LINUXDIR) config

kmconf: check_kernel_config 
	+$(MAKE) -C $(LINUXDIR) menuconfig

koldconf: check_kernel_config
	+$(MAKE) -C $(LINUXDIR) oldconfig

# Convenience
config: conf

menuconfig: mconf

oldconfig: oldconf

# Default configurations
#ifneq ("$(LINUX_VERSION)","2_6")
#.config:
#	cp config/defconfig $@
#	+$(MAKE) oldconfig
#else
#.config:
#	cp config/defconfig-2.6 $@
#	+$(MAKE) oldconfig
#endif

$(LINUXDIR)/.config:
ifeq ($(SKU11810),y)
	$(Q)cp -f $(LINUXDIR)/defconfig-Hawking $(LINUXDIR)/.config
else ifeq ($(SKU11820),y)
	$(Q)cp -f $(LINUXDIR)/defconfig-Airlive $(LINUXDIR)/.config
else
	$(Q)cp -f $(LINUXDIR)/defconfig $(LINUXDIR)/.config
endif

#ifneq ("$(LINUX_VERSION)","2_6")
#$(LINUXDIR)/.config:
#	cp $(LINUXDIR)/arch/mips/defconfig-bcm947xx $@
#else
#$(LINUXDIR)/.config:
#	cp $(LINUXDIR)/arch/mips/defconfig-2.6-bcm947xx $@
#endif

# Overwrite Kernel .config
check_kernel_config:
ifeq ($(SKU11810),y)
	cp -f $(LINUXDIR)/defconfig-Hawking $(LINUXDIR)/.config
else ifeq ($(SKU11820),y)
	$(Q)cp -f $(LINUXDIR)/defconfig-Airlive $(LINUXDIR)/.config
else
	cp -f $(LINUXDIR)/defconfig $(LINUXDIR)/.config
endif
	@if [ -n "$(_ROOTFS_IN_RAM_)" ]; then \
		./set_kernel_config.sh $(LINUXDIR) _ROOTFS_IN_RAM_ $(TOP)/romfs; \
		cp $(LINUXDIR)/.config $(LINUXDIR)/.config.bk; \
		$(Q)sed 's,CONFIG_INITRAMFS_SOURCE=.*,CONFIG_INITRAMFS_SOURCE="$(TOP)/romfs",g' $(LINUXDIR)/.config.bk > $(LINUXDIR)/.config; \
		rm $(LINUXDIR)/.config.bk; \
	elif [ -n "$(_ROOTFS_IN_FLASH_)" ]; then \
		./set_kernel_config.sh $(LINUXDIR) _ROOTFS_IN_FLASH_; \
		cp $(LINUXDIR)/.config $(LINUXDIR)/.config.bk; \
		$(Q)sed 's,CONFIG_MTD_KERNEL_PART_SIZ=.*,CONFIG_MTD_KERNEL_PART_SIZ=$(KERNEL_PART_SIZE),g' $(LINUXDIR)/.config.bk > $(LINUXDIR)/.config; \
		rm $(LINUXDIR)/.config.bk; \
	fi
	cp $(LINUXDIR)/.config $(LINUXDIR)/.config.tmp
	# Make kernel config again if changed
	$(if $(shell [ ! cmp ${LINUXDIR}/.config ${LINUXDIR}/.config.tmp >/dev/null 2>&1 ] && echo "y"), \
	+$(MAKE) -C ${LINUXDIR} oldconfig < /dev/null \
	)

# Check release command
XCUR = $(shell echo $(CURDIR) | sed 's/\//\\\//g')
#
# Generic rules
#

%:
	+$(if $(wildcard $*/),$(MAKE) -C $*,@true)

%-clean:
	[ ! -d $* ] || $(MAKE) -C $* clean

%-install:
	+$(if $(wildcard $*/), \
	  $(MAKE) -C $* install INSTALLDIR=$(INSTALLDIR)/$*, \
	  @true \
	 )

$(obj-y) $(obj-n) $(obj-clean) $(obj-install): dummy

.PHONY: all clean distclean install package check_kernel_config
.PHONY: dummy
help:
	@echo '    all           -- Build all binaries'
	@echo '    boot_bin      -- Build boot code only'
	@echo '    upg_bin       -- Build upgrade binary file only'
	@echo '    tools_bin     -- Build tools only'
	@echo '    modules_bin   -- Build modules only'
	@echo '    kernel_bin    -- Build kernel only'
	@echo '    romfs         -- Create romfs'
	@echo '    private_bin   -- Build private part only'
	@echo '    env           -- Checking environment and create necessary link'
	@echo '    tool_chain    -- Build tool chain only'
	@echo '    distclean     -- Cleaning files before distribution'
	@echo '    clean         -- Cleaning created files'
	@echo '    config        -- Text line base configuration'
	@echo '    menuconfig    -- ncurses base configuration'
	@echo '    oldconfig     -- Re-run old configuration'
	
endif

