1################################################################################ 2# rebar package infrastructure for Erlang packages 3# 4# This file implements an infrastructure that eases development of 5# package .mk files for rebar packages. It should be used for all 6# packages that use rebar as their build system. 7# 8# In terms of implementation, this rebar infrastructure requires the 9# .mk file to only specify metadata information about the package: 10# name, version, download URL, etc. 11# 12# We still allow the package .mk file to override what the different 13# steps are doing, if needed. For example, if <PKG>_BUILD_CMDS is 14# already defined, it is used as the list of commands to perform to 15# build the package, instead of the default rebar behaviour. The 16# package can also define some post operation hooks. 17# 18################################################################################ 19 20# Directories to store rebar dependencies in. 21# 22# These directories actually only contain symbolic links to Erlang 23# applications in either $(HOST_DIR) or $(STAGING_DIR). One needs 24# them to avoid rebar complaining about missing dependencies, as this 25# infrastructure tells rebar to NOT download dependencies during 26# the build stage. 27# 28REBAR_HOST_DEPS_DIR = $(HOST_DIR)/share/rebar/deps 29REBAR_TARGET_DEPS_DIR = $(STAGING_DIR)/usr/share/rebar/deps 30 31# Tell rebar where to find the dependencies 32# 33REBAR_HOST_DEPS_ENV = \ 34 ERL_COMPILER_OPTIONS='{i, "$(REBAR_HOST_DEPS_DIR)"}' \ 35 ERL_EI_LIBDIR=$(HOST_DIR)/lib/erlang/lib/erl_interface-$(ERLANG_EI_VSN)/lib 36REBAR_TARGET_DEPS_ENV = \ 37 ERL_COMPILER_OPTIONS='{i, "$(REBAR_TARGET_DEPS_DIR)"}' \ 38 ERL_EI_LIBDIR=$(STAGING_DIR)/usr/lib/erlang/lib/erl_interface-$(ERLANG_EI_VSN)/lib 39 40################################################################################ 41# Helper functions 42################################################################################ 43 44# Install an Erlang application from $(@D). 45# 46# i.e., define a recipe that installs the "bin ebin priv $(2)" directories 47# from $(@D) to $(1)/$($(PKG)_ERLANG_LIBDIR). 48# 49# argument 1 should typically be $(HOST_DIR), $(TARGET_DIR), 50# or $(STAGING_DIR). 51# argument 2 is typically empty when installing in $(TARGET_DIR) and 52# "include" when installing in $(HOST_DIR) or 53# $(STAGING_DIR). 54# 55# Note: calling this function must be done with $$(call ...) because it 56# expands package-related variables. 57# 58define install-erlang-directories 59 $(INSTALL) -d $(1)/$($(PKG)_ERLANG_LIBDIR) 60 for dir in bin ebin priv $(2); do \ 61 if test -d $(@D)/$$dir; then \ 62 cp -r $(@D)/$$dir $(1)/$($(PKG)_ERLANG_LIBDIR); \ 63 fi; \ 64 done 65endef 66 67# Setup a symbolic link in rebar's deps_dir to the actual location 68# where an Erlang application is installed. 69# 70# i.e., define a recipe that creates a symbolic link 71# from $($(PKG)_REBAR_DEPS_DIR)/$($(PKG)_ERLANG_APP) 72# to $(1)$($(PKG)_ERLANG_LIBDIR). 73# 74# For target packages for example, one uses this to setup symbolic 75# links from $(STAGING_DIR)/usr/share/rebar/deps/<erlang-app> to 76# $(STAGING_DIR)/usr/lib/erlang/lib/<erlang-app>-<version>. This 77# infrastructure points rebar at the former in order to tell rebar to 78# NOT download dependencies during the build stage, and instead use 79# the already available dependencies. 80# 81# Therefore, 82# argument 1 is $(HOST_DIR) (for host packages) or 83# $(STAGING_DIR) (for target packages). 84# 85# argument 2 is HOST (for host packages) or 86# TARGET (for target packages). 87# 88# Note: calling this function must be done with $$(call ...) because it 89# expands package-related variables. 90# 91define install-rebar-deps 92 $(INSTALL) -d $(REBAR_$(2)_DEPS_DIR) 93 ln -f -s $(1)/$($(PKG)_ERLANG_LIBDIR) \ 94 $(REBAR_$(2)_DEPS_DIR)/$($(PKG)_ERLANG_APP) 95endef 96 97# Remove the "deps" statement from a rebar.config file 98define remove-rebar-config-dependencies 99 $(SED) '/^{deps.*}\.$$/d' -e '/^{deps/,/}\.$$/d' \ 100 $($(PKG)_DIR)/rebar.config 101endef 102 103 104################################################################################ 105# inner-rebar-package -- defines how the configuration, compilation 106# and installation of a rebar package should be done, implements a few 107# hooks to tune the build process according to rebar specifities, and 108# calls the generic package infrastructure to generate the necessary 109# make targets. 110# 111# argument 1 is the lowercase package name 112# argument 2 is the uppercase package name, including a HOST_ prefix 113# for host packages 114# argument 3 is the uppercase package name, without the HOST_ prefix 115# for host packages 116# argument 4 is the type (target or host) 117# 118################################################################################ 119 120define inner-rebar-package 121 122# Extract just the raw package name, lowercase without the leading 123# erlang- or host- prefix, as this is used by rebar to find the 124# dependencies a package specifies. 125# 126$(2)_ERLANG_APP = $(subst -,_,$(patsubst erlang-%,%,$(patsubst host-%,%,$(1)))) 127 128# Path where to store the package's libs, relative to either $(HOST_DIR) 129# for host packages, or $(STAGING_DIR)/usr for target packages. 130# 131$(2)_ERLANG_LIBDIR = \ 132 lib/erlang/lib/$$($$(PKG)_ERLANG_APP)-$$($$(PKG)_VERSION) 133 134# If a host package, inherit <pkg>_USE_BUNDLED_REBAR from the target 135# package, if not explicitly defined. Otherwise, default to NO. 136ifndef $(2)_USE_BUNDLED_REBAR 137 ifdef $(3)_USE_BUNDLED_REBAR 138 $(2)_USE_BUNDLED_REBAR = $$($(3)_USE_BUNDLED_REBAR) 139 else 140 $(2)_USE_BUNDLED_REBAR ?= NO 141 endif 142endif 143 144# If a host package, inherit <pkg>_USE_AUTOCONF from the target 145# package, if not explicitly defined. Otherwise, default to NO. 146ifndef $(2)_USE_AUTOCONF 147 ifdef $(3)_USE_AUTOCONF 148 $(2)_USE_AUTOCONF = $$($(3)_USE_AUTOCONF) 149 else 150 $(2)_USE_AUTOCONF ?= NO 151 endif 152endif 153 154# Define the build and install commands 155# 156ifeq ($(4),target) 157 158# Target packages need the erlang interpreter on the target 159$(2)_DEPENDENCIES += erlang 160 161# Used only if the package uses autotools underneath; otherwise, ignored 162$(2)_CONF_ENV += $$(REBAR_TARGET_DEPS_ENV) 163 164ifndef $(2)_BUILD_CMDS 165define $(2)_BUILD_CMDS 166 (cd $$(@D); \ 167 CC="$$(TARGET_CC)" \ 168 CXX="$$(TARGET_CXX)" \ 169 CFLAGS="$$(TARGET_CFLAGS)" \ 170 CXXFLAGS="$$(TARGET_CXXFLAGS)" \ 171 LDFLAGS="$$(TARGET_LDFLAGS)" \ 172 $$(REBAR_TARGET_DEPS_ENV) \ 173 $$(TARGET_MAKE_ENV) \ 174 $$($$(PKG)_REBAR_ENV) $$($$(PKG)_REBAR) deps_dir=$$(REBAR_TARGET_DEPS_DIR) compile \ 175 ) 176endef 177endif 178 179# We need to double-$ the 'call' because it wants to expand 180# package-related variables 181ifndef $(2)_INSTALL_STAGING_CMDS 182define $(2)_INSTALL_STAGING_CMDS 183 $$(call install-erlang-directories,$$(STAGING_DIR)/usr,include) 184 $$(call install-rebar-deps,$$(STAGING_DIR)/usr,TARGET) 185endef 186endif 187 188# We need to double-$ the 'call' because it wants to expand 189# package-related variables 190ifndef $(2)_INSTALL_TARGET_CMDS 191define $(2)_INSTALL_TARGET_CMDS 192 $$(call install-erlang-directories,$$(TARGET_DIR)/usr) 193endef 194endif 195 196else # !target 197 198# Host packages need the erlang interpreter on the host 199$(2)_DEPENDENCIES += host-erlang 200 201# Used only if the package uses autotools underneath; otherwise, ignored 202$(2)_CONF_ENV += $$(REBAR_HOST_DEPS_ENV) 203 204ifndef $(2)_BUILD_CMDS 205define $(2)_BUILD_CMDS 206 (cd $$(@D); \ 207 CC="$$(HOSTCC)" \ 208 CFLAGS="$$(HOST_CFLAGS)" \ 209 LDFLAGS="$$(HOST_LDFLAGS)" \ 210 $$(REBAR_HOST_DEPS_ENV) \ 211 $$(HOST_MAKE_ENV) \ 212 $$($$(PKG)_REBAR_ENV) $$($$(PKG)_REBAR) deps_dir=$$(REBAR_HOST_DEPS_DIR) compile \ 213 ) 214endef 215endif 216 217# We need to double-$ the 'call' because it wants to expand 218# package-related variables 219ifndef $(2)_INSTALL_CMDS 220define $(2)_INSTALL_CMDS 221 $$(call install-erlang-directories,$$(HOST_DIR),include) 222 $$(call install-rebar-deps,$$(HOST_DIR),HOST) 223endef 224endif 225 226endif # !target 227 228# Whether to use the generic rebar or the package's bundled rebar 229# 230ifeq ($$($(2)_USE_BUNDLED_REBAR),YES) 231$(2)_REBAR = ./rebar 232else 233$(2)_REBAR = rebar 234$(2)_DEPENDENCIES += host-erlang-rebar 235endif 236 237$(2)_KEEP_DEPENDENCIES ?= NO 238 239# Remove dependencies listed in rebar.config unless the package says 240# otherwise 241ifeq ($$($(2)_KEEP_DEPENDENCIES),NO) 242$(2)_POST_PATCH_HOOKS += remove-rebar-config-dependencies 243endif 244 245# The package sub-infra to use 246# 247ifeq ($$($(2)_USE_AUTOCONF),YES) 248$(call inner-autotools-package,$(1),$(2),$(3),$(4)) 249else 250$(call inner-generic-package,$(1),$(2),$(3),$(4)) 251endif 252 253endef # inner-rebar-package 254 255rebar-package = $(call inner-rebar-package,$(pkgname),$(call UPPERCASE,$(pkgname)),$(call UPPERCASE,$(pkgname)),target) 256host-rebar-package = $(call inner-rebar-package,host-$(pkgname),$(call UPPERCASE,host-$(pkgname)),$(call UPPERCASE,$(pkgname)),host) 257