| ################################################################################ |
| # 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 |
| UPPERCASE = $(shell echo $(1) | tr "a-z.-" "A-Z__") |
| |
| # Define extrators for different archive suffixes |
| INFLATE.bz2 = $(BZCAT) |
| INFLATE.gz = $(ZCAT) |
| INFLATE.tbz = $(BZCAT) |
| INFLATE.tgz = $(ZCAT) |
| 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 -- 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)) |
| ################################################################################ |
| |
| # support make source-check/external-deps |
| ifneq ($(SPIDER),) |
| DOWNLOAD=$(WGET) -P $(DL_DIR) $(1)/$(2) |
| else |
| define DOWNLOAD |
| $(Q)test -e $(DL_DIR)/$(2) || \ |
| for site in $(call qstrip,$(BR2_PRIMARY_SITE)) $(1) $(call qstrip,$(BR2_BACKUP_SITE)); \ |
| do $(WGET) -P $(DL_DIR) $$site/$(2) && exit; done |
| endef |
| endif |
| |
| # Utility programs used to build packages |
| TAR ?= tar |
| |
| # Automatically detect tar --strip-path/components option |
| TAR_STRIP_COMPONENTS := \ |
| $(shell $(TAR) --help | grep strip-path > /dev/null ; \ |
| if test $$? = 0 ; then \ |
| echo '--strip-path' ; \ |
| else \ |
| echo '--strip-components' ; \ |
| fi) |
| |
| # 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: |
| # support make source-check/external-deps |
| ifeq ($(SPIDER),) |
| # 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 |
| $(call DOWNLOAD,$($(PKG)_SITE),$($(PKG)_SOURCE)) |
| $(if $($(PKG)_PATCH),$(call DOWNLOAD,$($(PKG)_SITE),$($(PKG)_PATCH))) |
| ifeq ($(SPIDER),) |
| $(Q)mkdir -p $(@D) |
| $(Q)touch $@ |
| endif |
| |
| # Unpack the archive |
| $(BUILD_DIR)/%/.stamp_extracted: |
| @$(call MESSAGE,"Extracting") |
| $(Q)mkdir -p $(@D) |
| $(Q)$(INFLATE$(suffix $($(PKG)_SOURCE))) $(DL_DIR)/$($(PKG)_SOURCE) | \ |
| $(TAR) $(TAR_STRIP_COMPONENTS)=1 -C $(@D) $(TAR_OPTIONS) - |
| # some packages have messed up permissions inside |
| $(Q)chmod -R ug+rw $(@D) |
| $(foreach hook,$($(PKG)_POST_EXTRACT_HOOKS),$(call $(hook))$(sep)) |
| $(Q)touch $@ |
| |
| # Patch |
| # |
| # The NOHOSTPKG variable is the uppercased package name, without the |
| # HOST_ prefix, even for host packages. This allows to find the |
| # patches in the package directory, because $($(NOHOSTPKG)_NAME) |
| # expands to the package directory name. |
| # |
| $(BUILD_DIR)/%/.stamp_patched: NAMEVER = $($(NOHOSTPKG)_NAME)-$($(PKG)_VERSION) |
| $(BUILD_DIR)/%/.stamp_patched: |
| @$(call MESSAGE,"Patching $($(PKG)_DIR_PREFIX)/$($(PKG)_NAME)") |
| $(if $($(PKG)_PATCH),toolchain/patch-kernel.sh $(@D) $(DL_DIR) $($(PKG)_PATCH)) |
| $(Q)( \ |
| if test -d $($(PKG)_DIR_PREFIX)/$($(NOHOSTPKG)_NAME); then \ |
| if test "$(wildcard $($(PKG)_DIR_PREFIX)/$($(NOHOSTPKG)_NAME)/$(NAMEVER)*.patch*)"; then \ |
| toolchain/patch-kernel.sh $(@D) $($(PKG)_DIR_PREFIX)/$($(NOHOSTPKG)_NAME) $(NAMEVER)\*.patch $(NAMEVER)\*.patch.$(ARCH) || exit 1; \ |
| else \ |
| toolchain/patch-kernel.sh $(@D) $($(PKG)_DIR_PREFIX)/$($(NOHOSTPKG)_NAME) $($(NOHOSTPKG)_NAME)\*.patch $($(NOHOSTPKG)_NAME)\*.patch.$(ARCH) || exit 1; \ |
| if test -d $($(PKG)_DIR_PREFIX)/$($(PKG)_NAME)/$(NAMEVER); then \ |
| toolchain/patch-kernel.sh $(@D) $($(PKG)_DIR_PREFIX)/$($(NOHOSTPKG)_NAME)/$(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: |
| @$(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 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 |
| $(BUILD_DIR)/%/.stamp_uninstalled: |
| @$(call MESSAGE,"Uninstalling") |
| $($(PKG)_UNINSTALL_STAGING_CMDS) |
| rm -f $($(PKG)_TARGET_INSTALL_STAGING) |
| $($(PKG)_UNINSTALL_TARGET_CMDS) |
| rm -f $($(PKG)_TARGET_INSTALL_TARGET) $($(PKG)_HOOK_POST_INSTALL) |
| |
| # 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) |
| |
| ifndef $(2)_VERSION |
| ifdef $(3)_VERSION |
| $(2)_VERSION = $($(3)_VERSION) |
| else |
| $(2)_VERSION = undefined |
| endif |
| endif |
| |
| $(2)_DIR = $$(BUILD_DIR)/$(1)-$$($(2)_VERSION) |
| |
| ifndef $(2)_SOURCE |
| ifdef $(3)_SOURCE |
| $(2)_SOURCE = $($(3)_SOURCE) |
| else |
| $(2)_SOURCE ?= $(1)-$$($(2)_VERSION).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 |
| |
| $(2)_DEPENDENCIES ?= |
| $(2)_INSTALL_STAGING ?= 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_HOST = $$($(2)_DIR)/.stamp_host_installed |
| $(2)_TARGET_BUILD = $$($(2)_DIR)/.stamp_built |
| $(2)_TARGET_CONFIGURE = $$($(2)_DIR)/.stamp_configured |
| $(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 |
| |
| # new-style hooks |
| $(2)_POST_EXTRACT_HOOKS ?= |
| $(2)_POST_PATCH_HOOKS ?= |
| $(2)_POST_CONFIGURE_HOOKS ?= |
| $(2)_POST_BUILD_HOOKS ?= |
| $(2)_POST_INSTALL_HOOKS ?= |
| $(2)_POST_INSTALL_STAGING_HOOKS ?= |
| $(2)_POST_INSTALL_TARGET_HOOKS ?= |
| |
| # old-style hooks |
| $(2)_HOOK_POST_EXTRACT = $$($(2)_DIR)/.stamp_hook_post_extract |
| $(2)_HOOK_POST_CONFIGURE = $$($(2)_DIR)/.stamp_hook_post_configure |
| $(2)_HOOK_POST_BUILD = $$($(2)_DIR)/.stamp_hook_post_build |
| $(2)_HOOK_POST_INSTALL = $$($(2)_DIR)/.stamp_hook_post_install |
| |
| # human-friendly targets and target sequencing |
| $(1): $(1)-install |
| |
| ifeq ($$($(2)_TYPE),host) |
| $(1)-install: $(1)-install-host $$($(2)_HOOK_POST_INSTALL) |
| else |
| $(1)-install: $(1)-install-staging $(1)-install-target \ |
| $$($(2)_HOOK_POST_INSTALL) |
| 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 |
| |
| $(1)-install-host: $(1)-build $$($(2)_TARGET_INSTALL_HOST) |
| |
| $(1)-build: $(1)-configure \ |
| $$($(2)_TARGET_BUILD) \ |
| $$($(2)_HOOK_POST_BUILD) |
| |
| $(1)-configure: $(1)-patch \ |
| $$($(2)_TARGET_CONFIGURE) \ |
| $$($(2)_HOOK_POST_CONFIGURE) |
| |
| $(1)-patch: $(1)-extract $$($(2)_TARGET_PATCH) |
| |
| $(1)-extract: $(1)-depends \ |
| $$($(2)_TARGET_EXTRACT) \ |
| $$($(2)_HOOK_POST_EXTRACT) |
| |
| $(1)-depends: $(1)-source $$($(2)_DEPENDENCIES) |
| |
| $(1)-source: $$($(2)_TARGET_SOURCE) |
| |
| $(1)-uninstall: $(1)-configure $$($(2)_TARGET_UNINSTALL) |
| |
| $(1)-clean: $(1)-uninstall \ |
| $$($(2)_TARGET_CLEAN) |
| |
| $(1)-dirclean: $$($(2)_TARGET_DIRCLEAN) |
| |
| # 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_HOST): PKG=$(2) |
| $$($(2)_TARGET_BUILD): PKG=$(2) |
| $$($(2)_TARGET_CONFIGURE): PKG=$(2) |
| $$($(2)_TARGET_PATCH): PKG=$(2) |
| $$($(2)_TARGET_PATCH): NOHOSTPKG=$(3) |
| $$($(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) |
| $$($(2)_HOOK_POST_EXTRACT): PKG=$(2) |
| $$($(2)_HOOK_POST_CONFIGURE): PKG=$(2) |
| $$($(2)_HOOK_POST_BUILD): PKG=$(2) |
| $$($(2)_HOOK_POST_INSTALL): PKG=$(2) |
| |
| # define hook targets |
| # default hook behaviour: do nothing |
| $$($(2)_HOOK_POST_EXTRACT): |
| $$($(2)_HOOK_POST_CONFIGURE): |
| $$($(2)_HOOK_POST_BUILD): |
| $$($(2)_HOOK_POST_INSTALL): |
| |
| # add package to the general list of targets if requested by the buildroot |
| # configuration |
| |
| ifeq ($$(BR2_PACKAGE_$(2)),y) |
| TARGETS += $(1) |
| endif |
| endef |
| |
| ################################################################################ |
| # GENTARGETS -- the target generator macro for generic packages |
| # |
| # Argument 1 is the package directory prefix [mandatory] |
| # Argument 2 is the lowercase package name [mandatory] |
| # Argument 3 is "target" or "host" [optional, default: "target"] |
| ################################################################################ |
| |
| define GENTARGETS |
| ifeq ($(3),host) |
| # In the case of host packages, turn the package name "pkg" into "host-pkg" |
| $(call GENTARGETS_INNER,$(3)-$(2),$(call UPPERCASE,$(3)-$(2)),$(call UPPERCASE,$(2)),$(1),host) |
| else |
| # In the case of target packages, keep the package name "pkg" |
| $(call GENTARGETS_INNER,$(2),$(call UPPERCASE,$(2)),$(call UPPERCASE,$(2)),$(1),target) |
| endif |
| endef |
| |
| # :mode=makefile: |