diff --git a/package/Makefile.in b/package/Makefile.in
index ab5ea48..943017b 100644
--- a/package/Makefile.in
+++ b/package/Makefile.in
@@ -299,6 +299,8 @@ else
 SHARED_STATIC_LIBS_OPTS=--enable-static --enable-shared
 endif
 
+include package/pkg-utils.mk
+include package/pkg-download.mk
 include package/pkg-autotargets.mk
 include package/pkg-cmaketargets.mk
-include package/Makefile.package.in
+include package/pkg-gentargets.mk
diff --git a/package/Makefile.package.in b/package/Makefile.package.in
deleted file mode 100644
index f7b6566..0000000
--- a/package/Makefile.package.in
+++ /dev/null
@@ -1,750 +0,0 @@
-################################################################################
-# Generic package infrastructure
-#
-# This file implements an infrastructure that eases development of
-# package .mk files. It should be used for all non-autotools based
-# packages. Autotools-based packages should use the specialized
-# autotools infrastructure in package/Makefile.autotools.in.
-#
-# See the Buildroot documentation for details on the usage of this
-# infrastructure
-#
-# In terms of implementation, this generic infrastructure requires the
-# .mk file to specify:
-#
-#   1. Metadata informations about the package: name, version,
-#      download URL, etc.
-#
-#   2. Description of the commands to be executed to configure, build
-#      and install the package
-#
-# The autotools infrastructure specializes this generic infrastructure
-# by already implementing the configure, build and install steps.
-################################################################################
-
-# UPPERCASE Macro -- transform its argument to uppercase and replace dots and
-# hyphens to underscores
-
-# Heavily inspired by the up macro from gmsl (http://gmsl.sf.net)
-# This is approx 5 times faster than forking a shell and tr, and
-# as this macro is used a lot it matters
-# This works by creating translation character pairs (E.G. a:A b:B)
-# and then looping though all of them running $(subst from,to,text)
-[FROM] := a b c d e f g h i j k l m n o p q r s t u v w x y z . -
-[TO]   := A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ _
-
-UPPERCASE = $(strip $(eval __tmp := $1) \
-     $(foreach c, $(join $(addsuffix :,$([FROM])),$([TO])), \
-	$(eval __tmp :=	\
-		$(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),\
-			$(__tmp)))) \
-     $(__tmp))
-
-define KCONFIG_ENABLE_OPT
-       $(SED) "/\\<$(1)\\>/d" $(2)
-       echo "$(1)=y" >> $(2)
-endef
-
-define KCONFIG_SET_OPT
-       $(SED) "/\\<$(1)\\>/d" $(3)
-       echo "$(1)=$(2)" >> $(3)
-endef
-
-define KCONFIG_DISABLE_OPT
-       $(SED) "/\\<$(1)\\>/d" $(2)
-       echo "# $(1) is not set" >> $(2)
-endef
-
-# Helper functions to determine the name of a package and its
-# directory from its makefile directory, using the $(MAKEFILE_LIST)
-# variable provided by make. This is used by the *TARGETS macros to
-# automagically find where the package is located. Note that the
-# pkgdir macro is carefully written to handle the case of the Linux
-# package, for which the package directory is an empty string.
-define pkgdir
-$(dir $(lastword $(MAKEFILE_LIST)))
-endef
-
-define pkgname
-$(lastword $(subst /, ,$(call pkgdir)))
-endef
-
-define pkgparentdir
-$(patsubst %$(call pkgname)/,%,$(call pkgdir))
-endef
-
-# Define extractors for different archive suffixes
-INFLATE.bz2  = $(BZCAT)
-INFLATE.gz   = $(ZCAT)
-INFLATE.tbz  = $(BZCAT)
-INFLATE.tbz2 = $(BZCAT)
-INFLATE.tgz  = $(ZCAT)
-INFLATE.xz   = $(XZCAT)
-INFLATE.tar  = cat
-
-# MESSAGE Macro -- display a message in bold type
-MESSAGE = echo "$(TERM_BOLD)>>> $($(PKG)_NAME) $($(PKG)_VERSION) $(1)$(TERM_RESET)"
-TERM_BOLD := $(shell tput smso)
-TERM_RESET := $(shell tput rmso)
-
-# Download method commands
-WGET:=$(call qstrip,$(BR2_WGET)) $(QUIET)
-SVN:=$(call qstrip,$(BR2_SVN))
-BZR:=$(call qstrip,$(BR2_BZR))
-GIT:=$(call qstrip,$(BR2_GIT))
-HG:=$(call qstrip,$(BR2_HG)) $(QUIET)
-SCP:=$(call qstrip,$(BR2_SCP)) $(QUIET)
-SSH:=$(call qstrip,$(BR2_SSH)) $(QUIET)
-LOCALFILES:=$(call qstrip,$(BR2_LOCALFILES))
-
-# Default spider mode is 'DOWNLOAD'. Other possible values are 'SOURCE_CHECK'
-# used by the _source-check target and 'SHOW_EXTERNAL_DEPS', used by the
-# external-deps target.
-DL_MODE=DOWNLOAD
-
-DL_DIR=$(call qstrip,$(BR2_DL_DIR))
-ifeq ($(DL_DIR),)
-DL_DIR:=$(TOPDIR)/dl
-endif
-
-#
-# URI scheme helper functions
-# Example URIs:
-# * http://www.example.com/dir/file
-# * scp://www.example.com:dir/file (with domainseparator :)
-#
-# geturischeme: http
-geturischeme=$(firstword $(subst ://, ,$(call qstrip,$(1))))
-# stripurischeme: www.example.com/dir/file
-stripurischeme=$(lastword $(subst ://, ,$(call qstrip,$(1))))
-# domain: www.example.com
-domain=$(firstword $(subst $(call domainseparator,$(2)), ,$(call stripurischeme,$(1))))
-# notdomain: dir/file
-notdomain=$(patsubst $(call domain,$(1),$(2))$(call domainseparator,$(2))%,%,$(call stripurischeme,$(1)))
-#
-# default domainseparator is /, specify alternative value as first argument
-domainseparator=$(if $(1),$(1),/)
-
-################################################################################
-# The DOWNLOAD_{GIT,SVN,BZR,HG,LOCALFILES} helpers are in charge of getting a
-# working copy of the source repository for their corresponding SCM,
-# checking out the requested version / commit / tag, and create an
-# archive out of it. DOWNLOAD_SCP uses scp to obtain a remote file with
-# ssh authentication. DOWNLOAD_WGET is the normal wget-based download
-# mechanism.
-#
-# The SOURCE_CHECK_{GIT,SVN,BZR,HG,WGET,LOCALFILES,SCP} helpers are in charge of
-# simply checking that the source is available for download. This can be used
-# to make sure one will be able to get all the sources needed for
-# one's build configuration.
-#
-# The SHOW_EXTERNAL_DEPS_{GIT,SVN,BZR,HG,WGET,LOCALFILES,SCP} helpers simply
-# output to the console the names of the files that will be downloaded, or path
-# and revision of the source repositories, producing a list of all the
-# "external dependencies" of a given build configuration.
-################################################################################
-
-define DOWNLOAD_GIT
-	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
-	(pushd $(DL_DIR) > /dev/null && \
-	$(GIT) clone --bare $($(PKG)_SITE) $($(PKG)_BASE_NAME) && \
-	pushd $($(PKG)_BASE_NAME) > /dev/null && \
-	$(GIT) archive --format=tar --prefix=$($(PKG)_BASE_NAME)/ $($(PKG)_DL_VERSION) | \
-		gzip -c > $(DL_DIR)/$($(PKG)_SOURCE) && \
-	popd > /dev/null && \
-	rm -rf $($(PKG)_DL_DIR) && \
-	popd > /dev/null)
-endef
-
-# TODO: improve to check that the given PKG_DL_VERSION exists on the remote
-# repository
-define SOURCE_CHECK_GIT
-  $(GIT) ls-remote --heads $($(PKG)_SITE) > /dev/null
-endef
-
-define SHOW_EXTERNAL_DEPS_GIT
-	echo $($(PKG)_SOURCE)
-endef
-
-
-define DOWNLOAD_BZR
-	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
-	$(BZR) export $(DL_DIR)/$($(PKG)_SOURCE) $($(PKG)_SITE) -r $($(PKG)_DL_VERSION)
-endef
-
-define SOURCE_CHECK_BZR
-	$(BZR) ls --quiet $($(PKG)_SITE) > /dev/null
-endef
-
-define SHOW_EXTERNAL_DEPS_BZR
-	echo $($(PKG)_SOURCE)
-endef
-
-
-define DOWNLOAD_SVN
-	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
-	(pushd $(DL_DIR) > /dev/null && \
-	$(SVN) export -r $($(PKG)_DL_VERSION) $($(PKG)_SITE) $($(PKG)_DL_DIR) && \
-	$(TAR) czf $($(PKG)_SOURCE) $($(PKG)_BASE_NAME)/ && \
-	rm -rf $($(PKG)_DL_DIR) && \
-	popd > /dev/null)
-endef
-
-define SOURCE_CHECK_SVN
-  $(SVN) ls $($(PKG)_SITE) > /dev/null
-endef
-
-define SHOW_EXTERNAL_DEPS_SVN
-  echo $($(PKG)_SOURCE)
-endef
-
-# SCP URIs should be of the form scp://[user@]host:filepath
-# Note that filepath is relative to the user's home directory, so you may want
-# to prepend the path with a slash: scp://[user@]host:/absolutepath
-define DOWNLOAD_SCP
-	test -e $(DL_DIR)/$(2) || \
-	$(SCP) '$(call stripurischeme,$(call qstrip,$(1)))' $(DL_DIR)/$(2)
-endef
-
-define SOURCE_CHECK_SCP
-	$(SSH) $(call domain,$(1),:) ls '$(call notdomain,$(1),:)' > /dev/null
-endef
-
-define SHOW_EXTERNAL_DEPS_SCP
-	echo $(2)
-endef
-
-
-define DOWNLOAD_HG
-	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
-	(pushd $(DL_DIR) > /dev/null && \
-	$(HG) clone --noupdate --rev $($(PKG)_DL_VERSION) $($(PKG)_SITE) $($(PKG)_BASE_NAME) && \
-	$(HG) archive --repository $($(PKG)_BASE_NAME) --type tgz --prefix $($(PKG)_BASE_NAME)/ \
-	              --rev $($(PKG)_DL_VERSION) $(DL_DIR)/$($(PKG)_SOURCE) && \
-	rm -rf $($(PKG)_DL_DIR) && \
-	popd > /dev/null)
-endef
-
-# TODO: improve to check that the given PKG_DL_VERSION exists on the remote
-# repository
-define SOURCE_CHECK_HG
-  $(HG) incoming --force -l1 $($(PKG)_SITE) > /dev/null
-endef
-
-define SHOW_EXTERNAL_DEPS_HG
-  echo $($(PKG)_SOURCE)
-endef
-
-# Download a file using wget. Only download the file if it doesn't
-# already exist in the download directory. If the download fails,
-# remove the file (because wget -O creates a 0-byte file even if the
-# download fails).
-define DOWNLOAD_WGET
-	test -e $(DL_DIR)/$(2) || \
-	$(WGET) -O $(DL_DIR)/$(2) '$(call qstrip,$(1))' || \
-	(rm -f $(DL_DIR)/$(2) ; exit 1)
-endef
-
-define SOURCE_CHECK_WGET
-  $(WGET) --spider '$(call qstrip,$(1))'
-endef
-
-define SHOW_EXTERNAL_DEPS_WGET
-  echo $(2)
-endef
-
-define DOWNLOAD_LOCALFILES
-	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
-		$(LOCALFILES) $(call qstrip,$(subst file://,,$($(PKG)_SITE)))/$($(PKG)_SOURCE) $(DL_DIR)
-endef
-
-define SOURCE_CHECK_LOCALFILES
-  test -e $(call qstrip,$(subst file://,,$($(PKG)_SITE)))/$($(PKG)_SOURCE)
-endef
-
-define SHOW_EXTERNAL_DEPS_LOCALFILES
-  echo $($(PKG)_SITE)/$($(PKG)_SOURCE)
-endef
-
-################################################################################
-# DOWNLOAD -- Download helper. Will try to download source from:
-# 1) BR2_PRIMARY_SITE if enabled
-# 2) Download site
-# 3) BR2_BACKUP_SITE if enabled
-#
-# Argument 1 is the source location
-# Argument 2 is the source filename
-#
-# E.G. use like this:
-# $(call DOWNLOAD,$(FOO_SITE),$(FOO_SOURCE))
-################################################################################
-
-define DOWNLOAD
-	$(call DOWNLOAD_INNER,$(1),$(if $(2),$(2),$(notdir $(1))))
-endef
-
-define DOWNLOAD_INNER
-	$(Q)if test -n "$(call qstrip,$(BR2_PRIMARY_SITE))" ; then \
-		case "$(call geturischeme,$(BR2_PRIMARY_SITE))" in \
-			scp) $(call $(DL_MODE)_SCP,$(BR2_PRIMARY_SITE),$(2)) && exit ;; \
-			*) $(call $(DL_MODE)_WGET,$(BR2_PRIMARY_SITE),$(2)) && exit ;; \
-		esac ; \
-	fi ; \
-	if test -n "$(1)" ; then \
-		case "$($(PKG)_SITE_METHOD)" in \
-			git) $($(DL_MODE)_GIT) && exit ;; \
-			svn) $($(DL_MODE)_SVN) && exit ;; \
-			bzr) $($(DL_MODE)_BZR) && exit ;; \
-			file) $($(DL_MODE)_LOCALFILES) && exit ;; \
-			scp) $($(DL_MODE)_SCP) && exit ;; \
-			hg) $($(DL_MODE)_HG) && exit ;; \
-			*) $(call $(DL_MODE)_WGET,$(1),$(2)) && exit ;; \
-		esac ; \
-	fi ; \
-	if test -n "$(call qstrip,$(BR2_BACKUP_SITE))" ; then \
-		$(call $(DL_MODE)_WGET,$(BR2_BACKUP_SITE)/$(2),$(2)) && exit ; \
-	fi ; \
-	exit 1
-endef
-
-# Needed for the foreach loops to loop over the list of hooks, so that
-# each hook call is properly separated by a newline.
-define sep
-
-
-endef
-
-################################################################################
-# Implicit targets -- produce a stamp file for each step of a package build
-################################################################################
-
-# Retrieve the archive
-$(BUILD_DIR)/%/.stamp_downloaded:
-ifeq ($(DL_MODE),DOWNLOAD)
-# Only show the download message if it isn't already downloaded
-	$(Q)(test -e $(DL_DIR)/$($(PKG)_SOURCE) && \
-		(test -z $($(PKG)_PATCH) || test -e $(DL_DIR)$($(PKG)_PATCH))) || \
-		$(call MESSAGE,"Downloading")
-endif
-	$(if $($(PKG)_SOURCE),$(call DOWNLOAD,$($(PKG)_SITE)/$($(PKG)_SOURCE)))
-	$(if $($(PKG)_PATCH),$(call DOWNLOAD,$($(PKG)_SITE)/$($(PKG)_PATCH)))
-	$(foreach hook,$($(PKG)_POST_DOWNLOAD_HOOKS),$(call $(hook))$(sep))
-ifeq ($(DL_MODE),DOWNLOAD)
-	$(Q)mkdir -p $(@D)
-	$(Q)touch $@
-endif
-
-# Unpack the archive
-$(BUILD_DIR)/%/.stamp_extracted:
-	@$(call MESSAGE,"Extracting")
-	$(Q)mkdir -p $(@D)
-	$($(PKG)_EXTRACT_CMDS)
-# some packages have messed up permissions inside
-	$(Q)chmod -R +rw $(@D)
-	$(foreach hook,$($(PKG)_POST_EXTRACT_HOOKS),$(call $(hook))$(sep))
-	$(Q)touch $@
-
-# Rsync the source directory if the <pkg>_OVERRIDE_SRCDIR feature is
-# used.
-$(BUILD_DIR)/%/.stamp_rsynced:
-	@$(call MESSAGE,"Syncing from source dir $(SRCDIR)")
-	@test -d $(SRCDIR) || (echo "ERROR: $(SRCDIR) does not exist" ; exit 1)
-	rsync -au $(SRCDIR)/ $(@D)
-	$(Q)touch $@
-
-# Handle the SOURCE_CHECK and SHOW_EXTERNAL_DEPS cases for rsynced
-# packages
-$(BUILD_DIR)/%/.stamp_rsync_sourced:
-ifeq ($(DL_MODE),SOURCE_CHECK)
-	test -d $(SRCDIR)
-else ifeq ($(DL_MODE),SHOW_EXTERNAL_DEPS)
-	echo "file://$(SRCDIR)"
-else
-	@true # Nothing to do to source a local package
-endif
-
-# Patch
-#
-# The RAWNAME variable is the lowercased package name, which allows to
-# find the package directory (typically package/<pkgname>) and the
-# prefix of the patches
-$(BUILD_DIR)/%/.stamp_patched: NAMEVER = $(RAWNAME)-$($(PKG)_VERSION)
-$(BUILD_DIR)/%/.stamp_patched:
-	@$(call MESSAGE,"Patching $($(PKG)_DIR_PREFIX)/$(RAWNAME)")
-	$(foreach hook,$($(PKG)_PRE_PATCH_HOOKS),$(call $(hook))$(sep))
-	$(if $($(PKG)_PATCH),support/scripts/apply-patches.sh $(@D) $(DL_DIR) $($(PKG)_PATCH))
-	$(Q)( \
-	if test -d $($(PKG)_DIR_PREFIX)/$(RAWNAME); then \
-	  if test "$(wildcard $($(PKG)_DIR_PREFIX)/$(RAWNAME)/$(NAMEVER)*.patch*)"; then \
-	    support/scripts/apply-patches.sh $(@D) $($(PKG)_DIR_PREFIX)/$(RAWNAME) $(NAMEVER)\*.patch $(NAMEVER)\*.patch.$(ARCH) || exit 1; \
-	  else \
-	    support/scripts/apply-patches.sh $(@D) $($(PKG)_DIR_PREFIX)/$(RAWNAME) $(RAWNAME)\*.patch $(RAWNAME)\*.patch.$(ARCH) || exit 1; \
-	    if test -d $($(PKG)_DIR_PREFIX)/$(RAWNAME)/$(NAMEVER); then \
-	      support/scripts/apply-patches.sh $(@D) $($(PKG)_DIR_PREFIX)/$(RAWNAME)/$(NAMEVER) \*.patch \*.patch.$(ARCH) || exit 1; \
-	    fi; \
-	  fi; \
-	fi; \
-	)
-	$(foreach hook,$($(PKG)_POST_PATCH_HOOKS),$(call $(hook))$(sep))
-	$(Q)touch $@
-
-# Configure
-$(BUILD_DIR)/%/.stamp_configured:
-	$(foreach hook,$($(PKG)_PRE_CONFIGURE_HOOKS),$(call $(hook))$(sep))
-	@$(call MESSAGE,"Configuring")
-	$($(PKG)_CONFIGURE_CMDS)
-	$(foreach hook,$($(PKG)_POST_CONFIGURE_HOOKS),$(call $(hook))$(sep))
-	$(Q)touch $@
-
-# Build
-$(BUILD_DIR)/%/.stamp_built::
-	@$(call MESSAGE,"Building")
-	$($(PKG)_BUILD_CMDS)
-	$(foreach hook,$($(PKG)_POST_BUILD_HOOKS),$(call $(hook))$(sep))
-	$(Q)touch $@
-
-# Install to host dir
-$(BUILD_DIR)/%/.stamp_host_installed:
-	@$(call MESSAGE,"Installing to host directory")
-	$($(PKG)_INSTALL_CMDS)
-	$(foreach hook,$($(PKG)_POST_INSTALL_HOOKS),$(call $(hook))$(sep))
-	$(Q)touch $@
-
-# Install to staging dir
-$(BUILD_DIR)/%/.stamp_staging_installed:
-	@$(call MESSAGE,"Installing to staging directory")
-	$($(PKG)_INSTALL_STAGING_CMDS)
-	$(foreach hook,$($(PKG)_POST_INSTALL_STAGING_HOOKS),$(call $(hook))$(sep))
-	$(Q)touch $@
-
-# Install to images dir
-$(BUILD_DIR)/%/.stamp_images_installed:
-	@$(call MESSAGE,"Installing to images directory")
-	$($(PKG)_INSTALL_IMAGES_CMDS)
-	$(foreach hook,$($(PKG)_POST_INSTALL_IMAGES_HOOKS),$(call $(hook))$(sep))
-	$(Q)touch $@
-
-# Install to target dir
-$(BUILD_DIR)/%/.stamp_target_installed:
-	@$(call MESSAGE,"Installing to target")
-	$($(PKG)_INSTALL_TARGET_CMDS)
-	$(foreach hook,$($(PKG)_POST_INSTALL_TARGET_HOOKS),$(call $(hook))$(sep))
-	$(Q)touch $@
-
-# Clean package
-$(BUILD_DIR)/%/.stamp_cleaned:
-	@$(call MESSAGE,"Cleaning up")
-	$($(PKG)_CLEAN_CMDS)
-	rm -f $(@D)/.stamp_built
-
-# Uninstall package from target and staging
-# Uninstall commands tend to fail, so remove the stamp files first
-$(BUILD_DIR)/%/.stamp_uninstalled:
-	@$(call MESSAGE,"Uninstalling")
-	rm -f $($(PKG)_TARGET_INSTALL_STAGING)
-	rm -f $($(PKG)_TARGET_INSTALL_TARGET)
-	$($(PKG)_UNINSTALL_STAGING_CMDS)
-	$($(PKG)_UNINSTALL_TARGET_CMDS)
-
-# Remove package sources
-$(BUILD_DIR)/%/.stamp_dircleaned:
-	rm -Rf $(@D)
-
-################################################################################
-# GENTARGETS_INNER -- generates the make targets needed to build a
-# generic package
-#
-#  argument 1 is the lowercase package name
-#  argument 2 is the uppercase package name, including an HOST_ prefix
-#             for host packages
-#  argument 3 is the uppercase package name, without the HOST_ prefix
-#             for host packages
-#  argument 4 is the package directory prefix
-#  argument 5 is the type (target or host)
-################################################################################
-
-define GENTARGETS_INNER
-
-# Define default values for various package-related variables, if not
-# already defined. For some variables (version, source, site and
-# subdir), if they are undefined, we try to see if a variable without
-# the HOST_ prefix is defined. If so, we use such a variable, so that
-# these informations have only to be specified once, for both the
-# target and host packages of a given .mk file.
-
-$(2)_TYPE                       =  $(5)
-$(2)_NAME			=  $(1)
-
-# Keep the package version that may contain forward slashes in the _DL_VERSION
-# variable, then replace all forward slashes ('/') by underscores ('_') to
-# sanitize the package version that is used in paths, directory and file names.
-# Forward slashes may appear in the package's version when pointing to a
-# version control system branch or tag, for example remotes/origin/1_10_stable.
-ifndef $(2)_VERSION
- ifdef $(3)_VERSION
-  $(2)_DL_VERSION = $($(3)_VERSION)
-  $(2)_VERSION = $(subst /,_,$($(3)_VERSION))
- else
-  $(2)_VERSION = undefined
-  $(2)_DL_VERSION = undefined
- endif
-else
-  $(2)_DL_VERSION = $($(2)_VERSION)
-  $(2)_VERSION = $(subst /,_,$($(2)_VERSION))
-endif
-
-$(2)_BASE_NAME	=  $(1)-$$($(2)_VERSION)
-$(2)_DL_DIR	=  $$(DL_DIR)/$$($(2)_BASE_NAME)
-$(2)_DIR	=  $$(BUILD_DIR)/$$($(2)_BASE_NAME)
-
-ifneq ($$($(2)_OVERRIDE_SRCDIR),)
-$(2)_VERSION = custom
-endif
-
-ifndef $(2)_SOURCE
- ifdef $(3)_SOURCE
-  $(2)_SOURCE = $($(3)_SOURCE)
- else
-  $(2)_SOURCE			?= $$($(2)_BASE_NAME).tar.gz
- endif
-endif
-
-ifndef $(2)_PATCH
- ifdef $(3)_PATCH
-  $(2)_PATCH = $($(3)_PATCH)
- endif
-endif
-
-ifndef $(2)_SITE
- ifdef $(3)_SITE
-  $(2)_SITE = $($(3)_SITE)
- else
-  $(2)_SITE			?= \
-	http://$$(BR2_SOURCEFORGE_MIRROR).dl.sourceforge.net/sourceforge/$(1)
- endif
-endif
-
-ifndef $(2)_SITE_METHOD
- ifdef $(3)_SITE_METHOD
-  $(2)_SITE_METHOD = $($(3)_SITE_METHOD)
- else
-	# Try automatic detection using the scheme part of the URI
-	$(2)_SITE_METHOD = $(firstword $(subst ://, ,$(call qstrip,$($(2)_SITE))))
- endif
-endif
-
-ifeq ($$($(2)_SITE_METHOD),local)
-ifeq ($$($(2)_OVERRIDE_SRCDIR),)
-$(2)_OVERRIDE_SRCDIR = $($(2)_SITE)
-endif
-endif
-
-$(2)_DEPENDENCIES ?= $(patsubst host-host-%,host-%,$(addprefix host-,$($(3)_DEPENDENCIES)))
-
-$(2)_INSTALL_STAGING		?= NO
-$(2)_INSTALL_IMAGES		?= NO
-$(2)_INSTALL_TARGET		?= YES
-$(2)_DIR_PREFIX			= $(if $(4),$(4),$(TOP_SRCDIR)/package)
-
-# define sub-target stamps
-$(2)_TARGET_INSTALL_TARGET =	$$($(2)_DIR)/.stamp_target_installed
-$(2)_TARGET_INSTALL_STAGING =	$$($(2)_DIR)/.stamp_staging_installed
-$(2)_TARGET_INSTALL_IMAGES =	$$($(2)_DIR)/.stamp_images_installed
-$(2)_TARGET_INSTALL_HOST =      $$($(2)_DIR)/.stamp_host_installed
-$(2)_TARGET_BUILD =		$$($(2)_DIR)/.stamp_built
-$(2)_TARGET_CONFIGURE =		$$($(2)_DIR)/.stamp_configured
-$(2)_TARGET_RSYNC =	        $$($(2)_DIR)/.stamp_rsynced
-$(2)_TARGET_RSYNC_SOURCE =      $$($(2)_DIR)/.stamp_rsync_sourced
-$(2)_TARGET_PATCH =		$$($(2)_DIR)/.stamp_patched
-$(2)_TARGET_EXTRACT =		$$($(2)_DIR)/.stamp_extracted
-$(2)_TARGET_SOURCE =		$$($(2)_DIR)/.stamp_downloaded
-$(2)_TARGET_UNINSTALL =		$$($(2)_DIR)/.stamp_uninstalled
-$(2)_TARGET_CLEAN =		$$($(2)_DIR)/.stamp_cleaned
-$(2)_TARGET_DIRCLEAN =		$$($(2)_DIR)/.stamp_dircleaned
-
-# default extract command
-$(2)_EXTRACT_CMDS ?= \
-	$$(if $$($(2)_SOURCE),$$(INFLATE$$(suffix $$($(2)_SOURCE))) $(DL_DIR)/$$($(2)_SOURCE) | \
-	$(TAR) $(TAR_STRIP_COMPONENTS)=1 -C $$($(2)_DIR) $(TAR_OPTIONS) -)
-
-# post-steps hooks
-$(2)_POST_DOWNLOAD_HOOKS        ?=
-$(2)_POST_EXTRACT_HOOKS         ?=
-$(2)_PRE_PATCH_HOOKS            ?=
-$(2)_POST_PATCH_HOOKS           ?=
-$(2)_PRE_CONFIGURE_HOOKS        ?=
-$(2)_POST_CONFIGURE_HOOKS       ?=
-$(2)_POST_BUILD_HOOKS           ?=
-$(2)_POST_INSTALL_HOOKS         ?=
-$(2)_POST_INSTALL_STAGING_HOOKS ?=
-$(2)_POST_INSTALL_TARGET_HOOKS  ?=
-$(2)_POST_INSTALL_IMAGES_HOOKS  ?=
-
-# human-friendly targets and target sequencing
-$(1):			$(1)-install
-
-ifeq ($$($(2)_TYPE),host)
-$(1)-install:	        $(1)-install-host
-else
-$(1)-install:		$(1)-install-staging $(1)-install-target $(1)-install-images
-endif
-
-ifeq ($$($(2)_INSTALL_TARGET),YES)
-$(1)-install-target:	$(1)-build \
-			$$($(2)_TARGET_INSTALL_TARGET)
-else
-$(1)-install-target:
-endif
-
-ifeq ($$($(2)_INSTALL_STAGING),YES)
-$(1)-install-staging:	$(1)-build \
-			$$($(2)_TARGET_INSTALL_STAGING)
-else
-$(1)-install-staging:
-endif
-
-ifeq ($$($(2)_INSTALL_IMAGES),YES)
-$(1)-install-images:	$(1)-build \
-			$$($(2)_TARGET_INSTALL_IMAGES)
-else
-$(1)-install-images:
-endif
-
-$(1)-install-host:      $(1)-build $$($(2)_TARGET_INSTALL_HOST)
-
-$(1)-build:		$(1)-configure \
-			$$($(2)_TARGET_BUILD)
-
-ifeq ($$($(2)_OVERRIDE_SRCDIR),)
-# In the normal case (no package override), the sequence of steps is
-#  source, by downloading
-#  depends
-#  extract
-#  patch
-#  configure
-$(1)-configure:		$(1)-patch $(1)-depends \
-			$$($(2)_TARGET_CONFIGURE)
-
-$(1)-patch:		$(1)-extract $$($(2)_TARGET_PATCH)
-
-$(1)-extract:		$(1)-source \
-			$$($(2)_TARGET_EXTRACT)
-
-$(1)-depends:		$$($(2)_DEPENDENCIES)
-
-$(1)-source:		$$($(2)_TARGET_SOURCE)
-else
-# In the package override case, the sequence of steps
-#  source, by rsyncing
-#  depends
-#  configure
-$(1)-configure:		$(1)-depends \
-			$$($(2)_TARGET_CONFIGURE)
-
-$(1)-depends:		$(1)-rsync $$($(2)_DEPENDENCIES)
-
-$(1)-rsync:		$$($(2)_TARGET_RSYNC)
-
-$(1)-source:		$$($(2)_TARGET_RSYNC_SOURCE)
-endif
-
-$(1)-show-depends:
-			@echo $$($(2)_DEPENDENCIES)
-
-$(1)-uninstall:		$(1)-configure $$($(2)_TARGET_UNINSTALL)
-
-$(1)-clean:		$(1)-uninstall \
-			$$($(2)_TARGET_CLEAN)
-
-$(1)-dirclean:		$$($(2)_TARGET_DIRCLEAN)
-
-$(1)-clean-for-rebuild:
-ifneq ($$($(2)_OVERRIDE_SRCDIR),)
-			rm -f $$($(2)_TARGET_RSYNC)
-endif
-			rm -f $$($(2)_TARGET_BUILD)
-			rm -f $$($(2)_TARGET_INSTALL_STAGING)
-			rm -f $$($(2)_TARGET_INSTALL_TARGET)
-			rm -f $$($(2)_TARGET_INSTALL_IMAGES)
-			rm -f $$($(2)_TARGET_INSTALL_HOST)
-
-$(1)-rebuild:		$(1)-clean-for-rebuild all
-
-$(1)-clean-for-reconfigure: $(1)-clean-for-rebuild
-			rm -f $$($(2)_TARGET_CONFIGURE)
-
-$(1)-reconfigure:	$(1)-clean-for-reconfigure all
-
-# define the PKG variable for all targets, containing the
-# uppercase package variable prefix
-$$($(2)_TARGET_INSTALL_TARGET):		PKG=$(2)
-$$($(2)_TARGET_INSTALL_STAGING):	PKG=$(2)
-$$($(2)_TARGET_INSTALL_IMAGES):		PKG=$(2)
-$$($(2)_TARGET_INSTALL_HOST):           PKG=$(2)
-$$($(2)_TARGET_BUILD):			PKG=$(2)
-$$($(2)_TARGET_CONFIGURE):		PKG=$(2)
-$$($(2)_TARGET_RSYNC):                  SRCDIR=$$($(2)_OVERRIDE_SRCDIR)
-$$($(2)_TARGET_RSYNC):                  PKG=$(2)
-$$($(2)_TARGET_RSYNC_SOURCE):		SRCDIR=$$($(2)_OVERRIDE_SRCDIR)
-$$($(2)_TARGET_RSYNC_SOURCE):		PKG=$(2)
-$$($(2)_TARGET_PATCH):			PKG=$(2)
-$$($(2)_TARGET_PATCH):			RAWNAME=$(patsubst host-%,%,$(1))
-$$($(2)_TARGET_EXTRACT):		PKG=$(2)
-$$($(2)_TARGET_SOURCE):			PKG=$(2)
-$$($(2)_TARGET_UNINSTALL):		PKG=$(2)
-$$($(2)_TARGET_CLEAN):			PKG=$(2)
-$$($(2)_TARGET_DIRCLEAN):		PKG=$(2)
-
-# Compute the name of the Kconfig option that correspond to the
-# package being enabled. We handle three cases: the special Linux
-# kernel case, the bootloaders case, and the normal packages case.
-ifeq ($(1),linux)
-$(2)_KCONFIG_VAR = BR2_LINUX_KERNEL
-else ifeq ($(4),boot/)
-$(2)_KCONFIG_VAR = BR2_TARGET_$(2)
-else
-$(2)_KCONFIG_VAR = BR2_PACKAGE_$(2)
-endif
-
-# add package to the general list of targets if requested by the buildroot
-# configuration
-ifeq ($$($$($(2)_KCONFIG_VAR)),y)
-
-TARGETS += $(1)
-PACKAGES_PERMISSIONS_TABLE += $$($(2)_PERMISSIONS)$$(sep)
-PACKAGES_DEVICES_TABLE += $$($(2)_DEVICES)$$(sep)
-
-ifeq ($$($(2)_SITE_METHOD),svn)
-DL_TOOLS_DEPENDENCIES += svn
-else ifeq ($$($(2)_SITE_METHOD),git)
-DL_TOOLS_DEPENDENCIES += git
-else ifeq ($$($(2)_SITE_METHOD),bzr)
-DL_TOOLS_DEPENDENCIES += bzr
-else ifeq ($$($(2)_SITE_METHOD),scp)
-DL_TOOLS_DEPENDENCIES += scp ssh
-else ifeq ($$($(2)_SITE_METHOD),hg)
-DL_TOOLS_DEPENDENCIES += hg
-endif # SITE_METHOD
-
-DL_TOOLS_DEPENDENCIES += $(firstword $(INFLATE$(suffix $($(2)_SOURCE))))
-
-endif # $(2)_KCONFIG_VAR
-endef # GENTARGETS_INNER
-
-################################################################################
-# GENTARGETS -- the target generator macro for generic packages
-#
-# Argument 1 is "target" or "host"           [optional, default: "target"]
-################################################################################
-
-define GENTARGETS
-ifeq ($(1),host)
-# In the case of host packages, turn the package name "pkg" into "host-pkg"
-$(call GENTARGETS_INNER,$(1)-$(call pkgname),$(call UPPERCASE,$(1)-$(call pkgname)),$(call UPPERCASE,$(call pkgname)),$(call pkgparentdir),host)
-else
-# In the case of target packages, keep the package name "pkg"
-$(call GENTARGETS_INNER,$(call pkgname),$(call UPPERCASE,$(call pkgname)),$(call UPPERCASE,$(call pkgname)),$(call pkgparentdir),target)
-endif
-endef
-
-# :mode=makefile:
diff --git a/package/pkg-download.mk b/package/pkg-download.mk
new file mode 100644
index 0000000..a565ae6
--- /dev/null
+++ b/package/pkg-download.mk
@@ -0,0 +1,219 @@
+# Download method commands
+WGET:=$(call qstrip,$(BR2_WGET)) $(QUIET)
+SVN:=$(call qstrip,$(BR2_SVN))
+BZR:=$(call qstrip,$(BR2_BZR))
+GIT:=$(call qstrip,$(BR2_GIT))
+HG:=$(call qstrip,$(BR2_HG)) $(QUIET)
+SCP:=$(call qstrip,$(BR2_SCP)) $(QUIET)
+SSH:=$(call qstrip,$(BR2_SSH)) $(QUIET)
+LOCALFILES:=$(call qstrip,$(BR2_LOCALFILES))
+
+# Default spider mode is 'DOWNLOAD'. Other possible values are 'SOURCE_CHECK'
+# used by the _source-check target and 'SHOW_EXTERNAL_DEPS', used by the
+# external-deps target.
+DL_MODE=DOWNLOAD
+
+DL_DIR=$(call qstrip,$(BR2_DL_DIR))
+ifeq ($(DL_DIR),)
+DL_DIR:=$(TOPDIR)/dl
+endif
+
+#
+# URI scheme helper functions
+# Example URIs:
+# * http://www.example.com/dir/file
+# * scp://www.example.com:dir/file (with domainseparator :)
+#
+# geturischeme: http
+geturischeme=$(firstword $(subst ://, ,$(call qstrip,$(1))))
+# stripurischeme: www.example.com/dir/file
+stripurischeme=$(lastword $(subst ://, ,$(call qstrip,$(1))))
+# domain: www.example.com
+domain=$(firstword $(subst $(call domainseparator,$(2)), ,$(call stripurischeme,$(1))))
+# notdomain: dir/file
+notdomain=$(patsubst $(call domain,$(1),$(2))$(call domainseparator,$(2))%,%,$(call stripurischeme,$(1)))
+#
+# default domainseparator is /, specify alternative value as first argument
+domainseparator=$(if $(1),$(1),/)
+
+################################################################################
+# The DOWNLOAD_{GIT,SVN,BZR,HG,LOCALFILES} helpers are in charge of getting a
+# working copy of the source repository for their corresponding SCM,
+# checking out the requested version / commit / tag, and create an
+# archive out of it. DOWNLOAD_SCP uses scp to obtain a remote file with
+# ssh authentication. DOWNLOAD_WGET is the normal wget-based download
+# mechanism.
+#
+# The SOURCE_CHECK_{GIT,SVN,BZR,HG,WGET,LOCALFILES,SCP} helpers are in charge of
+# simply checking that the source is available for download. This can be used
+# to make sure one will be able to get all the sources needed for
+# one's build configuration.
+#
+# The SHOW_EXTERNAL_DEPS_{GIT,SVN,BZR,HG,WGET,LOCALFILES,SCP} helpers simply
+# output to the console the names of the files that will be downloaded, or path
+# and revision of the source repositories, producing a list of all the
+# "external dependencies" of a given build configuration.
+################################################################################
+
+define DOWNLOAD_GIT
+	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
+	(pushd $(DL_DIR) > /dev/null && \
+	$(GIT) clone --bare $($(PKG)_SITE) $($(PKG)_BASE_NAME) && \
+	pushd $($(PKG)_BASE_NAME) > /dev/null && \
+	$(GIT) archive --format=tar --prefix=$($(PKG)_BASE_NAME)/ $($(PKG)_DL_VERSION) | \
+		gzip -c > $(DL_DIR)/$($(PKG)_SOURCE) && \
+	popd > /dev/null && \
+	rm -rf $($(PKG)_DL_DIR) && \
+	popd > /dev/null)
+endef
+
+# TODO: improve to check that the given PKG_DL_VERSION exists on the remote
+# repository
+define SOURCE_CHECK_GIT
+  $(GIT) ls-remote --heads $($(PKG)_SITE) > /dev/null
+endef
+
+define SHOW_EXTERNAL_DEPS_GIT
+	echo $($(PKG)_SOURCE)
+endef
+
+
+define DOWNLOAD_BZR
+	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
+	$(BZR) export $(DL_DIR)/$($(PKG)_SOURCE) $($(PKG)_SITE) -r $($(PKG)_DL_VERSION)
+endef
+
+define SOURCE_CHECK_BZR
+	$(BZR) ls --quiet $($(PKG)_SITE) > /dev/null
+endef
+
+define SHOW_EXTERNAL_DEPS_BZR
+	echo $($(PKG)_SOURCE)
+endef
+
+
+define DOWNLOAD_SVN
+	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
+	(pushd $(DL_DIR) > /dev/null && \
+	$(SVN) export -r $($(PKG)_DL_VERSION) $($(PKG)_SITE) $($(PKG)_DL_DIR) && \
+	$(TAR) czf $($(PKG)_SOURCE) $($(PKG)_BASE_NAME)/ && \
+	rm -rf $($(PKG)_DL_DIR) && \
+	popd > /dev/null)
+endef
+
+define SOURCE_CHECK_SVN
+  $(SVN) ls $($(PKG)_SITE) > /dev/null
+endef
+
+define SHOW_EXTERNAL_DEPS_SVN
+  echo $($(PKG)_SOURCE)
+endef
+
+# SCP URIs should be of the form scp://[user@]host:filepath
+# Note that filepath is relative to the user's home directory, so you may want
+# to prepend the path with a slash: scp://[user@]host:/absolutepath
+define DOWNLOAD_SCP
+	test -e $(DL_DIR)/$(2) || \
+	$(SCP) '$(call stripurischeme,$(call qstrip,$(1)))' $(DL_DIR)/$(2)
+endef
+
+define SOURCE_CHECK_SCP
+	$(SSH) $(call domain,$(1),:) ls '$(call notdomain,$(1),:)' > /dev/null
+endef
+
+define SHOW_EXTERNAL_DEPS_SCP
+	echo $(2)
+endef
+
+
+define DOWNLOAD_HG
+	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
+	(pushd $(DL_DIR) > /dev/null && \
+	$(HG) clone --noupdate --rev $($(PKG)_DL_VERSION) $($(PKG)_SITE) $($(PKG)_BASE_NAME) && \
+	$(HG) archive --repository $($(PKG)_BASE_NAME) --type tgz --prefix $($(PKG)_BASE_NAME)/ \
+	              --rev $($(PKG)_DL_VERSION) $(DL_DIR)/$($(PKG)_SOURCE) && \
+	rm -rf $($(PKG)_DL_DIR) && \
+	popd > /dev/null)
+endef
+
+# TODO: improve to check that the given PKG_DL_VERSION exists on the remote
+# repository
+define SOURCE_CHECK_HG
+  $(HG) incoming --force -l1 $($(PKG)_SITE) > /dev/null
+endef
+
+define SHOW_EXTERNAL_DEPS_HG
+  echo $($(PKG)_SOURCE)
+endef
+
+# Download a file using wget. Only download the file if it doesn't
+# already exist in the download directory. If the download fails,
+# remove the file (because wget -O creates a 0-byte file even if the
+# download fails).
+define DOWNLOAD_WGET
+	test -e $(DL_DIR)/$(2) || \
+	$(WGET) -O $(DL_DIR)/$(2) '$(call qstrip,$(1))' || \
+	(rm -f $(DL_DIR)/$(2) ; exit 1)
+endef
+
+define SOURCE_CHECK_WGET
+  $(WGET) --spider '$(call qstrip,$(1))'
+endef
+
+define SHOW_EXTERNAL_DEPS_WGET
+  echo $(2)
+endef
+
+define DOWNLOAD_LOCALFILES
+	test -e $(DL_DIR)/$($(PKG)_SOURCE) || \
+		$(LOCALFILES) $(call qstrip,$(subst file://,,$($(PKG)_SITE)))/$($(PKG)_SOURCE) $(DL_DIR)
+endef
+
+define SOURCE_CHECK_LOCALFILES
+  test -e $(call qstrip,$(subst file://,,$($(PKG)_SITE)))/$($(PKG)_SOURCE)
+endef
+
+define SHOW_EXTERNAL_DEPS_LOCALFILES
+  echo $($(PKG)_SITE)/$($(PKG)_SOURCE)
+endef
+
+################################################################################
+# DOWNLOAD -- Download helper. Will try to download source from:
+# 1) BR2_PRIMARY_SITE if enabled
+# 2) Download site
+# 3) BR2_BACKUP_SITE if enabled
+#
+# Argument 1 is the source location
+# Argument 2 is the source filename
+#
+# E.G. use like this:
+# $(call DOWNLOAD,$(FOO_SITE),$(FOO_SOURCE))
+################################################################################
+
+define DOWNLOAD
+	$(call DOWNLOAD_INNER,$(1),$(if $(2),$(2),$(notdir $(1))))
+endef
+
+define DOWNLOAD_INNER
+	$(Q)if test -n "$(call qstrip,$(BR2_PRIMARY_SITE))" ; then \
+		case "$(call geturischeme,$(BR2_PRIMARY_SITE))" in \
+			scp) $(call $(DL_MODE)_SCP,$(BR2_PRIMARY_SITE),$(2)) && exit ;; \
+			*) $(call $(DL_MODE)_WGET,$(BR2_PRIMARY_SITE),$(2)) && exit ;; \
+		esac ; \
+	fi ; \
+	if test -n "$(1)" ; then \
+		case "$($(PKG)_SITE_METHOD)" in \
+			git) $($(DL_MODE)_GIT) && exit ;; \
+			svn) $($(DL_MODE)_SVN) && exit ;; \
+			bzr) $($(DL_MODE)_BZR) && exit ;; \
+			file) $($(DL_MODE)_LOCALFILES) && exit ;; \
+			scp) $($(DL_MODE)_SCP) && exit ;; \
+			hg) $($(DL_MODE)_HG) && exit ;; \
+			*) $(call $(DL_MODE)_WGET,$(1),$(2)) && exit ;; \
+		esac ; \
+	fi ; \
+	if test -n "$(call qstrip,$(BR2_BACKUP_SITE))" ; then \
+		$(call $(DL_MODE)_WGET,$(BR2_BACKUP_SITE)/$(2),$(2)) && exit ; \
+	fi ; \
+	exit 1
+endef
diff --git a/package/pkg-gentargets.mk b/package/pkg-gentargets.mk
new file mode 100644
index 0000000..a535681
--- /dev/null
+++ b/package/pkg-gentargets.mk
@@ -0,0 +1,458 @@
+################################################################################
+# Generic package infrastructure
+#
+# This file implements an infrastructure that eases development of
+# package .mk files. It should be used for all non-autotools based
+# packages. Autotools-based packages should use the specialized
+# autotools infrastructure in package/Makefile.autotools.in.
+#
+# See the Buildroot documentation for details on the usage of this
+# infrastructure
+#
+# In terms of implementation, this generic infrastructure requires the
+# .mk file to specify:
+#
+#   1. Metadata informations about the package: name, version,
+#      download URL, etc.
+#
+#   2. Description of the commands to be executed to configure, build
+#      and install the package
+#
+# The autotools infrastructure specializes this generic infrastructure
+# by already implementing the configure, build and install steps.
+################################################################################
+
+################################################################################
+# Implicit targets -- produce a stamp file for each step of a package build
+################################################################################
+
+# Retrieve the archive
+$(BUILD_DIR)/%/.stamp_downloaded:
+ifeq ($(DL_MODE),DOWNLOAD)
+# Only show the download message if it isn't already downloaded
+	$(Q)(test -e $(DL_DIR)/$($(PKG)_SOURCE) && \
+		(test -z $($(PKG)_PATCH) || test -e $(DL_DIR)$($(PKG)_PATCH))) || \
+		$(call MESSAGE,"Downloading")
+endif
+	$(if $($(PKG)_SOURCE),$(call DOWNLOAD,$($(PKG)_SITE)/$($(PKG)_SOURCE)))
+	$(if $($(PKG)_PATCH),$(call DOWNLOAD,$($(PKG)_SITE)/$($(PKG)_PATCH)))
+	$(foreach hook,$($(PKG)_POST_DOWNLOAD_HOOKS),$(call $(hook))$(sep))
+ifeq ($(DL_MODE),DOWNLOAD)
+	$(Q)mkdir -p $(@D)
+	$(Q)touch $@
+endif
+
+# Unpack the archive
+$(BUILD_DIR)/%/.stamp_extracted:
+	@$(call MESSAGE,"Extracting")
+	$(Q)mkdir -p $(@D)
+	$($(PKG)_EXTRACT_CMDS)
+# some packages have messed up permissions inside
+	$(Q)chmod -R +rw $(@D)
+	$(foreach hook,$($(PKG)_POST_EXTRACT_HOOKS),$(call $(hook))$(sep))
+	$(Q)touch $@
+
+# Rsync the source directory if the <pkg>_OVERRIDE_SRCDIR feature is
+# used.
+$(BUILD_DIR)/%/.stamp_rsynced:
+	@$(call MESSAGE,"Syncing from source dir $(SRCDIR)")
+	@test -d $(SRCDIR) || (echo "ERROR: $(SRCDIR) does not exist" ; exit 1)
+	rsync -au $(SRCDIR)/ $(@D)
+	$(Q)touch $@
+
+# Handle the SOURCE_CHECK and SHOW_EXTERNAL_DEPS cases for rsynced
+# packages
+$(BUILD_DIR)/%/.stamp_rsync_sourced:
+ifeq ($(DL_MODE),SOURCE_CHECK)
+	test -d $(SRCDIR)
+else ifeq ($(DL_MODE),SHOW_EXTERNAL_DEPS)
+	echo "file://$(SRCDIR)"
+else
+	@true # Nothing to do to source a local package
+endif
+
+# Patch
+#
+# The RAWNAME variable is the lowercased package name, which allows to
+# find the package directory (typically package/<pkgname>) and the
+# prefix of the patches
+$(BUILD_DIR)/%/.stamp_patched: NAMEVER = $(RAWNAME)-$($(PKG)_VERSION)
+$(BUILD_DIR)/%/.stamp_patched:
+	@$(call MESSAGE,"Patching $($(PKG)_DIR_PREFIX)/$(RAWNAME)")
+	$(foreach hook,$($(PKG)_PRE_PATCH_HOOKS),$(call $(hook))$(sep))
+	$(if $($(PKG)_PATCH),support/scripts/apply-patches.sh $(@D) $(DL_DIR) $($(PKG)_PATCH))
+	$(Q)( \
+	if test -d $($(PKG)_DIR_PREFIX)/$(RAWNAME); then \
+	  if test "$(wildcard $($(PKG)_DIR_PREFIX)/$(RAWNAME)/$(NAMEVER)*.patch*)"; then \
+	    support/scripts/apply-patches.sh $(@D) $($(PKG)_DIR_PREFIX)/$(RAWNAME) $(NAMEVER)\*.patch $(NAMEVER)\*.patch.$(ARCH) || exit 1; \
+	  else \
+	    support/scripts/apply-patches.sh $(@D) $($(PKG)_DIR_PREFIX)/$(RAWNAME) $(RAWNAME)\*.patch $(RAWNAME)\*.patch.$(ARCH) || exit 1; \
+	    if test -d $($(PKG)_DIR_PREFIX)/$(RAWNAME)/$(NAMEVER); then \
+	      support/scripts/apply-patches.sh $(@D) $($(PKG)_DIR_PREFIX)/$(RAWNAME)/$(NAMEVER) \*.patch \*.patch.$(ARCH) || exit 1; \
+	    fi; \
+	  fi; \
+	fi; \
+	)
+	$(foreach hook,$($(PKG)_POST_PATCH_HOOKS),$(call $(hook))$(sep))
+	$(Q)touch $@
+
+# Configure
+$(BUILD_DIR)/%/.stamp_configured:
+	$(foreach hook,$($(PKG)_PRE_CONFIGURE_HOOKS),$(call $(hook))$(sep))
+	@$(call MESSAGE,"Configuring")
+	$($(PKG)_CONFIGURE_CMDS)
+	$(foreach hook,$($(PKG)_POST_CONFIGURE_HOOKS),$(call $(hook))$(sep))
+	$(Q)touch $@
+
+# Build
+$(BUILD_DIR)/%/.stamp_built::
+	@$(call MESSAGE,"Building")
+	$($(PKG)_BUILD_CMDS)
+	$(foreach hook,$($(PKG)_POST_BUILD_HOOKS),$(call $(hook))$(sep))
+	$(Q)touch $@
+
+# Install to host dir
+$(BUILD_DIR)/%/.stamp_host_installed:
+	@$(call MESSAGE,"Installing to host directory")
+	$($(PKG)_INSTALL_CMDS)
+	$(foreach hook,$($(PKG)_POST_INSTALL_HOOKS),$(call $(hook))$(sep))
+	$(Q)touch $@
+
+# Install to staging dir
+$(BUILD_DIR)/%/.stamp_staging_installed:
+	@$(call MESSAGE,"Installing to staging directory")
+	$($(PKG)_INSTALL_STAGING_CMDS)
+	$(foreach hook,$($(PKG)_POST_INSTALL_STAGING_HOOKS),$(call $(hook))$(sep))
+	$(Q)touch $@
+
+# Install to images dir
+$(BUILD_DIR)/%/.stamp_images_installed:
+	@$(call MESSAGE,"Installing to images directory")
+	$($(PKG)_INSTALL_IMAGES_CMDS)
+	$(foreach hook,$($(PKG)_POST_INSTALL_IMAGES_HOOKS),$(call $(hook))$(sep))
+	$(Q)touch $@
+
+# Install to target dir
+$(BUILD_DIR)/%/.stamp_target_installed:
+	@$(call MESSAGE,"Installing to target")
+	$($(PKG)_INSTALL_TARGET_CMDS)
+	$(foreach hook,$($(PKG)_POST_INSTALL_TARGET_HOOKS),$(call $(hook))$(sep))
+	$(Q)touch $@
+
+# Clean package
+$(BUILD_DIR)/%/.stamp_cleaned:
+	@$(call MESSAGE,"Cleaning up")
+	$($(PKG)_CLEAN_CMDS)
+	rm -f $(@D)/.stamp_built
+
+# Uninstall package from target and staging
+# Uninstall commands tend to fail, so remove the stamp files first
+$(BUILD_DIR)/%/.stamp_uninstalled:
+	@$(call MESSAGE,"Uninstalling")
+	rm -f $($(PKG)_TARGET_INSTALL_STAGING)
+	rm -f $($(PKG)_TARGET_INSTALL_TARGET)
+	$($(PKG)_UNINSTALL_STAGING_CMDS)
+	$($(PKG)_UNINSTALL_TARGET_CMDS)
+
+# Remove package sources
+$(BUILD_DIR)/%/.stamp_dircleaned:
+	rm -Rf $(@D)
+
+################################################################################
+# GENTARGETS_INNER -- generates the make targets needed to build a
+# generic package
+#
+#  argument 1 is the lowercase package name
+#  argument 2 is the uppercase package name, including an HOST_ prefix
+#             for host packages
+#  argument 3 is the uppercase package name, without the HOST_ prefix
+#             for host packages
+#  argument 4 is the package directory prefix
+#  argument 5 is the type (target or host)
+################################################################################
+
+define GENTARGETS_INNER
+
+# Define default values for various package-related variables, if not
+# already defined. For some variables (version, source, site and
+# subdir), if they are undefined, we try to see if a variable without
+# the HOST_ prefix is defined. If so, we use such a variable, so that
+# these informations have only to be specified once, for both the
+# target and host packages of a given .mk file.
+
+$(2)_TYPE                       =  $(5)
+$(2)_NAME			=  $(1)
+
+# Keep the package version that may contain forward slashes in the _DL_VERSION
+# variable, then replace all forward slashes ('/') by underscores ('_') to
+# sanitize the package version that is used in paths, directory and file names.
+# Forward slashes may appear in the package's version when pointing to a
+# version control system branch or tag, for example remotes/origin/1_10_stable.
+ifndef $(2)_VERSION
+ ifdef $(3)_VERSION
+  $(2)_DL_VERSION = $($(3)_VERSION)
+  $(2)_VERSION = $(subst /,_,$($(3)_VERSION))
+ else
+  $(2)_VERSION = undefined
+  $(2)_DL_VERSION = undefined
+ endif
+else
+  $(2)_DL_VERSION = $($(2)_VERSION)
+  $(2)_VERSION = $(subst /,_,$($(2)_VERSION))
+endif
+
+$(2)_BASE_NAME	=  $(1)-$$($(2)_VERSION)
+$(2)_DL_DIR	=  $$(DL_DIR)/$$($(2)_BASE_NAME)
+$(2)_DIR	=  $$(BUILD_DIR)/$$($(2)_BASE_NAME)
+
+ifneq ($$($(2)_OVERRIDE_SRCDIR),)
+$(2)_VERSION = custom
+endif
+
+ifndef $(2)_SOURCE
+ ifdef $(3)_SOURCE
+  $(2)_SOURCE = $($(3)_SOURCE)
+ else
+  $(2)_SOURCE			?= $$($(2)_BASE_NAME).tar.gz
+ endif
+endif
+
+ifndef $(2)_PATCH
+ ifdef $(3)_PATCH
+  $(2)_PATCH = $($(3)_PATCH)
+ endif
+endif
+
+ifndef $(2)_SITE
+ ifdef $(3)_SITE
+  $(2)_SITE = $($(3)_SITE)
+ else
+  $(2)_SITE			?= \
+	http://$$(BR2_SOURCEFORGE_MIRROR).dl.sourceforge.net/sourceforge/$(1)
+ endif
+endif
+
+ifndef $(2)_SITE_METHOD
+ ifdef $(3)_SITE_METHOD
+  $(2)_SITE_METHOD = $($(3)_SITE_METHOD)
+ else
+	# Try automatic detection using the scheme part of the URI
+	$(2)_SITE_METHOD = $(firstword $(subst ://, ,$(call qstrip,$($(2)_SITE))))
+ endif
+endif
+
+ifeq ($$($(2)_SITE_METHOD),local)
+ifeq ($$($(2)_OVERRIDE_SRCDIR),)
+$(2)_OVERRIDE_SRCDIR = $($(2)_SITE)
+endif
+endif
+
+$(2)_DEPENDENCIES ?= $(patsubst host-host-%,host-%,$(addprefix host-,$($(3)_DEPENDENCIES)))
+
+$(2)_INSTALL_STAGING		?= NO
+$(2)_INSTALL_IMAGES		?= NO
+$(2)_INSTALL_TARGET		?= YES
+$(2)_DIR_PREFIX			= $(if $(4),$(4),$(TOP_SRCDIR)/package)
+
+# define sub-target stamps
+$(2)_TARGET_INSTALL_TARGET =	$$($(2)_DIR)/.stamp_target_installed
+$(2)_TARGET_INSTALL_STAGING =	$$($(2)_DIR)/.stamp_staging_installed
+$(2)_TARGET_INSTALL_IMAGES =	$$($(2)_DIR)/.stamp_images_installed
+$(2)_TARGET_INSTALL_HOST =      $$($(2)_DIR)/.stamp_host_installed
+$(2)_TARGET_BUILD =		$$($(2)_DIR)/.stamp_built
+$(2)_TARGET_CONFIGURE =		$$($(2)_DIR)/.stamp_configured
+$(2)_TARGET_RSYNC =	        $$($(2)_DIR)/.stamp_rsynced
+$(2)_TARGET_RSYNC_SOURCE =      $$($(2)_DIR)/.stamp_rsync_sourced
+$(2)_TARGET_PATCH =		$$($(2)_DIR)/.stamp_patched
+$(2)_TARGET_EXTRACT =		$$($(2)_DIR)/.stamp_extracted
+$(2)_TARGET_SOURCE =		$$($(2)_DIR)/.stamp_downloaded
+$(2)_TARGET_UNINSTALL =		$$($(2)_DIR)/.stamp_uninstalled
+$(2)_TARGET_CLEAN =		$$($(2)_DIR)/.stamp_cleaned
+$(2)_TARGET_DIRCLEAN =		$$($(2)_DIR)/.stamp_dircleaned
+
+# default extract command
+$(2)_EXTRACT_CMDS ?= \
+	$$(if $$($(2)_SOURCE),$$(INFLATE$$(suffix $$($(2)_SOURCE))) $(DL_DIR)/$$($(2)_SOURCE) | \
+	$(TAR) $(TAR_STRIP_COMPONENTS)=1 -C $$($(2)_DIR) $(TAR_OPTIONS) -)
+
+# post-steps hooks
+$(2)_POST_DOWNLOAD_HOOKS        ?=
+$(2)_POST_EXTRACT_HOOKS         ?=
+$(2)_PRE_PATCH_HOOKS            ?=
+$(2)_POST_PATCH_HOOKS           ?=
+$(2)_PRE_CONFIGURE_HOOKS        ?=
+$(2)_POST_CONFIGURE_HOOKS       ?=
+$(2)_POST_BUILD_HOOKS           ?=
+$(2)_POST_INSTALL_HOOKS         ?=
+$(2)_POST_INSTALL_STAGING_HOOKS ?=
+$(2)_POST_INSTALL_TARGET_HOOKS  ?=
+$(2)_POST_INSTALL_IMAGES_HOOKS  ?=
+
+# human-friendly targets and target sequencing
+$(1):			$(1)-install
+
+ifeq ($$($(2)_TYPE),host)
+$(1)-install:	        $(1)-install-host
+else
+$(1)-install:		$(1)-install-staging $(1)-install-target $(1)-install-images
+endif
+
+ifeq ($$($(2)_INSTALL_TARGET),YES)
+$(1)-install-target:	$(1)-build \
+			$$($(2)_TARGET_INSTALL_TARGET)
+else
+$(1)-install-target:
+endif
+
+ifeq ($$($(2)_INSTALL_STAGING),YES)
+$(1)-install-staging:	$(1)-build \
+			$$($(2)_TARGET_INSTALL_STAGING)
+else
+$(1)-install-staging:
+endif
+
+ifeq ($$($(2)_INSTALL_IMAGES),YES)
+$(1)-install-images:	$(1)-build \
+			$$($(2)_TARGET_INSTALL_IMAGES)
+else
+$(1)-install-images:
+endif
+
+$(1)-install-host:      $(1)-build $$($(2)_TARGET_INSTALL_HOST)
+
+$(1)-build:		$(1)-configure \
+			$$($(2)_TARGET_BUILD)
+
+ifeq ($$($(2)_OVERRIDE_SRCDIR),)
+# In the normal case (no package override), the sequence of steps is
+#  source, by downloading
+#  depends
+#  extract
+#  patch
+#  configure
+$(1)-configure:		$(1)-patch $(1)-depends \
+			$$($(2)_TARGET_CONFIGURE)
+
+$(1)-patch:		$(1)-extract $$($(2)_TARGET_PATCH)
+
+$(1)-extract:		$(1)-source \
+			$$($(2)_TARGET_EXTRACT)
+
+$(1)-depends:		$$($(2)_DEPENDENCIES)
+
+$(1)-source:		$$($(2)_TARGET_SOURCE)
+else
+# In the package override case, the sequence of steps
+#  source, by rsyncing
+#  depends
+#  configure
+$(1)-configure:		$(1)-depends \
+			$$($(2)_TARGET_CONFIGURE)
+
+$(1)-depends:		$(1)-rsync $$($(2)_DEPENDENCIES)
+
+$(1)-rsync:		$$($(2)_TARGET_RSYNC)
+
+$(1)-source:		$$($(2)_TARGET_RSYNC_SOURCE)
+endif
+
+$(1)-show-depends:
+			@echo $$($(2)_DEPENDENCIES)
+
+$(1)-uninstall:		$(1)-configure $$($(2)_TARGET_UNINSTALL)
+
+$(1)-clean:		$(1)-uninstall \
+			$$($(2)_TARGET_CLEAN)
+
+$(1)-dirclean:		$$($(2)_TARGET_DIRCLEAN)
+
+$(1)-clean-for-rebuild:
+ifneq ($$($(2)_OVERRIDE_SRCDIR),)
+			rm -f $$($(2)_TARGET_RSYNC)
+endif
+			rm -f $$($(2)_TARGET_BUILD)
+			rm -f $$($(2)_TARGET_INSTALL_STAGING)
+			rm -f $$($(2)_TARGET_INSTALL_TARGET)
+			rm -f $$($(2)_TARGET_INSTALL_IMAGES)
+			rm -f $$($(2)_TARGET_INSTALL_HOST)
+
+$(1)-rebuild:		$(1)-clean-for-rebuild all
+
+$(1)-clean-for-reconfigure: $(1)-clean-for-rebuild
+			rm -f $$($(2)_TARGET_CONFIGURE)
+
+$(1)-reconfigure:	$(1)-clean-for-reconfigure all
+
+# define the PKG variable for all targets, containing the
+# uppercase package variable prefix
+$$($(2)_TARGET_INSTALL_TARGET):		PKG=$(2)
+$$($(2)_TARGET_INSTALL_STAGING):	PKG=$(2)
+$$($(2)_TARGET_INSTALL_IMAGES):		PKG=$(2)
+$$($(2)_TARGET_INSTALL_HOST):           PKG=$(2)
+$$($(2)_TARGET_BUILD):			PKG=$(2)
+$$($(2)_TARGET_CONFIGURE):		PKG=$(2)
+$$($(2)_TARGET_RSYNC):                  SRCDIR=$$($(2)_OVERRIDE_SRCDIR)
+$$($(2)_TARGET_RSYNC):                  PKG=$(2)
+$$($(2)_TARGET_RSYNC_SOURCE):		SRCDIR=$$($(2)_OVERRIDE_SRCDIR)
+$$($(2)_TARGET_RSYNC_SOURCE):		PKG=$(2)
+$$($(2)_TARGET_PATCH):			PKG=$(2)
+$$($(2)_TARGET_PATCH):			RAWNAME=$(patsubst host-%,%,$(1))
+$$($(2)_TARGET_EXTRACT):		PKG=$(2)
+$$($(2)_TARGET_SOURCE):			PKG=$(2)
+$$($(2)_TARGET_UNINSTALL):		PKG=$(2)
+$$($(2)_TARGET_CLEAN):			PKG=$(2)
+$$($(2)_TARGET_DIRCLEAN):		PKG=$(2)
+
+# Compute the name of the Kconfig option that correspond to the
+# package being enabled. We handle three cases: the special Linux
+# kernel case, the bootloaders case, and the normal packages case.
+ifeq ($(1),linux)
+$(2)_KCONFIG_VAR = BR2_LINUX_KERNEL
+else ifeq ($(4),boot/)
+$(2)_KCONFIG_VAR = BR2_TARGET_$(2)
+else
+$(2)_KCONFIG_VAR = BR2_PACKAGE_$(2)
+endif
+
+# add package to the general list of targets if requested by the buildroot
+# configuration
+ifeq ($$($$($(2)_KCONFIG_VAR)),y)
+
+TARGETS += $(1)
+PACKAGES_PERMISSIONS_TABLE += $$($(2)_PERMISSIONS)$$(sep)
+PACKAGES_DEVICES_TABLE += $$($(2)_DEVICES)$$(sep)
+
+ifeq ($$($(2)_SITE_METHOD),svn)
+DL_TOOLS_DEPENDENCIES += svn
+else ifeq ($$($(2)_SITE_METHOD),git)
+DL_TOOLS_DEPENDENCIES += git
+else ifeq ($$($(2)_SITE_METHOD),bzr)
+DL_TOOLS_DEPENDENCIES += bzr
+else ifeq ($$($(2)_SITE_METHOD),scp)
+DL_TOOLS_DEPENDENCIES += scp ssh
+else ifeq ($$($(2)_SITE_METHOD),hg)
+DL_TOOLS_DEPENDENCIES += hg
+endif # SITE_METHOD
+
+DL_TOOLS_DEPENDENCIES += $(firstword $(INFLATE$(suffix $($(2)_SOURCE))))
+
+endif # $(2)_KCONFIG_VAR
+endef # GENTARGETS_INNER
+
+################################################################################
+# GENTARGETS -- the target generator macro for generic packages
+#
+# Argument 1 is "target" or "host"           [optional, default: "target"]
+################################################################################
+
+define GENTARGETS
+ifeq ($(1),host)
+# In the case of host packages, turn the package name "pkg" into "host-pkg"
+$(call GENTARGETS_INNER,$(1)-$(call pkgname),$(call UPPERCASE,$(1)-$(call pkgname)),$(call UPPERCASE,$(call pkgname)),$(call pkgparentdir),host)
+else
+# In the case of target packages, keep the package name "pkg"
+$(call GENTARGETS_INNER,$(call pkgname),$(call UPPERCASE,$(call pkgname)),$(call UPPERCASE,$(call pkgname)),$(call pkgparentdir),target)
+endif
+endef
+
+# :mode=makefile:
diff --git a/package/pkg-utils.mk b/package/pkg-utils.mk
new file mode 100644
index 0000000..729f8bb
--- /dev/null
+++ b/package/pkg-utils.mk
@@ -0,0 +1,72 @@
+# UPPERCASE Macro -- transform its argument to uppercase and replace dots and
+# hyphens to underscores
+
+# Heavily inspired by the up macro from gmsl (http://gmsl.sf.net)
+# This is approx 5 times faster than forking a shell and tr, and
+# as this macro is used a lot it matters
+# This works by creating translation character pairs (E.G. a:A b:B)
+# and then looping though all of them running $(subst from,to,text)
+[FROM] := a b c d e f g h i j k l m n o p q r s t u v w x y z . -
+[TO]   := A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ _
+
+UPPERCASE = $(strip $(eval __tmp := $1) \
+     $(foreach c, $(join $(addsuffix :,$([FROM])),$([TO])), \
+	$(eval __tmp :=	\
+		$(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),\
+			$(__tmp)))) \
+     $(__tmp))
+
+define KCONFIG_ENABLE_OPT
+       $(SED) "/\\<$(1)\\>/d" $(2)
+       echo "$(1)=y" >> $(2)
+endef
+
+define KCONFIG_SET_OPT
+       $(SED) "/\\<$(1)\\>/d" $(3)
+       echo "$(1)=$(2)" >> $(3)
+endef
+
+define KCONFIG_DISABLE_OPT
+       $(SED) "/\\<$(1)\\>/d" $(2)
+       echo "# $(1) is not set" >> $(2)
+endef
+
+# Helper functions to determine the name of a package and its
+# directory from its makefile directory, using the $(MAKEFILE_LIST)
+# variable provided by make. This is used by the *TARGETS macros to
+# automagically find where the package is located. Note that the
+# pkgdir macro is carefully written to handle the case of the Linux
+# package, for which the package directory is an empty string.
+define pkgdir
+$(dir $(lastword $(MAKEFILE_LIST)))
+endef
+
+define pkgname
+$(lastword $(subst /, ,$(call pkgdir)))
+endef
+
+define pkgparentdir
+$(patsubst %$(call pkgname)/,%,$(call pkgdir))
+endef
+
+# Define extractors for different archive suffixes
+INFLATE.bz2  = $(BZCAT)
+INFLATE.gz   = $(ZCAT)
+INFLATE.tbz  = $(BZCAT)
+INFLATE.tbz2 = $(BZCAT)
+INFLATE.tgz  = $(ZCAT)
+INFLATE.xz   = $(XZCAT)
+INFLATE.tar  = cat
+
+# MESSAGE Macro -- display a message in bold type
+MESSAGE = echo "$(TERM_BOLD)>>> $($(PKG)_NAME) $($(PKG)_VERSION) $(1)$(TERM_RESET)"
+TERM_BOLD := $(shell tput smso)
+TERM_RESET := $(shell tput rmso)
+
+
+# Needed for the foreach loops to loop over the list of hooks, so that
+# each hook call is properly separated by a newline.
+define sep
+
+
+endef
