Skip to content

Commit

Permalink
#96: Add lots of useful utils for embuild
Browse files Browse the repository at this point in the history
  • Loading branch information
abusalimov committed Sep 3, 2010
1 parent 324fc62 commit d24b01e
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 27 deletions.
24 changes: 20 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
#
# EMBOX root Makefile
# EMBOX root Makefile.
#
# This file just have to define ROOT_DIR variable and to include maik.mk
# This file have just to setup proper make flags and to invoke mk/main.mk
# which will perform the real work.
#
# Author: Eldar Abusalimov
#

ROOT_DIR:=.#$(CURDIR)
MK_DIR := $(abspath mk)

ifdef mk_ready
include main.mk
else

MAKEFLAGS += --include-dir=$(MK_DIR)
MAKEFLAGS += --no-builtin-rules
MAKEFLAGS += --no-builtin-variables
MAKEFLAGS += --no-print-directory
#MAKEFLAGS += --warn-undefined-variables

.DEFAULT_GOAL := all

% :
@$(MAKE) mk_ready=1 $@

endif

include $(ROOT_DIR)/mk/main.mk
1 change: 1 addition & 0 deletions mk/image.mk
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ checksum:
# Not yet implemented

CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
Expand Down
29 changes: 18 additions & 11 deletions mk/main.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,31 @@
# EMBOX main Makefile
#

# The first target is "all"
all:

# Check Make version (we need at least GNU Make 3.81)
# .FEATURES built-in variable has been introduced exactly in GNU Make 3.81.
ifneq ($(origin .FEATURES),default)
define ERROR
define error_msg
Unsupported Make version.
Unfortunatelly EMBuild does not work properly with GNU Make $(MAKE_VERSION).
This is a known issue. Please use GNU Make 3.81 or above
endef
$(error $(ERROR))
endif

ifndef ROOT_DIR
$(error ROOT_DIR undefined)
# Root makefile runs this using single goal per invocation. Check it.
ifneq ($(words $(MAKECMDGOALS)),1)
define error_msg
Illegal invocation (non-single make goal).
Please use root makefile to run the build
endef
endif

# Fail here if things are bad...
ifdef error_msg
$(error $(error_msg))
endif

ROOT_DIR := .#

MK_DIR := $(ROOT_DIR)/mk
SCRIPTS_DIR := $(ROOT_DIR)/scripts
PROJECTS_DIR := $(ROOT_DIR)/templates
Expand Down Expand Up @@ -53,10 +60,10 @@ SHELL := bash

TEMPLATES = $(notdir $(wildcard $(PROJECTS_DIR)/*))

include $(MK_DIR)/rules.mk
include $(MK_DIR)/util.mk
include rules.mk
include util.mk

include $(MK_DIR)/gmsl.mk
include gmsl.mk

makegoals := $(MAKECMDGOALS)
ifeq ($(makegoals),)
Expand Down Expand Up @@ -94,7 +101,7 @@ all: $(build_patch_targets) build_base_target
$(build_patch_targets): export PATCH_NAME=$(basename $@)
$(build_patch_targets) build_base_target: export BUILD_TARGET=1
$(build_patch_targets) build_base_target:
$(MAKE) --no-print-directory build
$(MAKE) build

build: check_config prepare image
@echo '$(or $(PATCH_NAME),Base) build complete'
Expand Down
2 changes: 1 addition & 1 deletion mk/traverse.mk
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ include $(MK_DIR)/util.mk
# If not specified traverse will search for files named Makefile and makefile
#
TRAVERSE = \
$(call assert_called,$0,TRAVERSE) \
$(call assert_called,TRAVERSE,$0) \
$(foreach __traverse_root,$(patsubst %/,%,$(wildcard $(1:%=%/))), \
$(eval __traverse_return := ) \
$(eval $(call __traverse_invoke,$(__traverse_root),$2)) \
Expand Down
158 changes: 147 additions & 11 deletions mk/util.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,160 @@
ifndef _util_mk_
_util_mk_ := 1

include gmsl.mk

##
# The last word of the MAKEFILE_LIST variable.
# Actual only until another makefile is included.
self_makefile = $(abspath $(lastword $(MAKEFILE_LIST)))

##
# Expands to empty string for the first time, and to 'true' for subsequent
# invocations. Should be used before any include directives.
#
# Thus, the typical usage of this function is:
#
# ifndef $(already_included)
# ...
# endif #$(already_included)
#
already_included = \
$(or $(call get,included,$(self_makefile)), \
$(call set,included,$(self_makefile),true))

##
# Can be used to check whether the variable is expanded using call or not.
#
# For example:
# func = $(call assert_called,$0,func) Use input args, e.g. $1, $2 or $3
# func = $(call assert_called,func,$0) Use input args, e.g. $1, $2 or $3
# $(call func,foo,bar,baz) expands to "Use input args, e.g. foo, bar or baz"
# but plain $(func) expansion produces an error.
# but plain $(func) expansion produces an assertion failure.
#
# Usage: $(call assert_called,$0,var_name)
# Usage: $(call assert_called,var_name,$0)
#
assert_called = $(strip \
$(call __assert_called,$0,assert_called) \
assert_called = $(info $1)$(strip \
$(call __assert_called,assert_called,$0) \
$(call __assert_called,$1,$2) \
)

__assert_called = $(if $(filter $1,$2),,$(error $2 must be call'ed))
__assert_called = $(call assert \
,$(call seq,$1,$2),$1 must be call'ed$(if $1, (last call'ed variable is $2)))

args_nr = $(foreach __args_nr_i,1,$(__args_nr))
__args_nr = \
$(if $(filter-out undefined,$(origin $(__args_nr_i))), \
$(foreach __args_nr_i,$(call inc,$(__args_nr_i)),$(__args_nr)), \
$(__args_nr_i) \
)

interval = $(if $(call lt,$1,$2) \
,$(call __interval_inc,$1,$2),$(call __interval_dec,$2,$1))
__interval_inc = $1$(if $(call lt,$1,$2),$(call $0, $(call inc,$1),$2))
__interval_dec = $(if $(call lt,$1,$2),$(call $0,$(call inc,$1) ,$2))$1

expand_once = $(call expand_once_0,$1)
__expand_once_def_all = \
$(foreach x,$(call interval,0,9),$(eval $(value __expand_once_def_x)))
define __expand_once_def_x
expand_once_$x = $(foreach total_args,$x,$(__expand_once))
endef

#
$(__expand_once_def_all)

# Do not call. Pass number of args through total_args variable.
__expand_once = $(strip \
$(call assert_called,expand_once_$(total_args),$0) \
$(call assert,$(call eq,$(words $1),1),Invalid name of variable being expanded) \
$(if $(filter undefined,$(origin $(__expansion_name))),$(eval \
$(value __expansion_name) := $$(call $(__expansion_args)) \
)) \
)$($(__expansion_name))
# XXX may be encode $(value __expansion_name) inside eval ? -- Eldar

__expansion_arg_nrs = $(call interval,1,$(call inc,$(total_args)))
__expansion_escape_arg = $(call dollar_encode,$($(arg_nr)))

__expansion_args = $(call split,_$$$$$$_,$(call merge,$(true:%=,), \
$(foreach arg_nr,$(__expansion_arg_nrs), \
$(call merge,_$$$$$$_,$(__expansion_escape_arg)) \
) \
))

__expansion_name = __expansion_of_$1_$$__$(strip $(call merge \
,_$$$$$$_, \
$(foreach arg_nr,$(__expansion_arg_nrs) \
,$(call merge,_$$_,$(__expansion_escape_arg))) \
))

define var_info
$(call assert_called,var_info,$0) \
$(call assert,$1,Variable name is empty) Variable [$1] info:
flavor: [$(flavor $1)]
origin: [$(origin $1)]
value: [$(value $1)]
expansion: [$($1)]

endef

var_assign_recursive = \
$(call assert_called,var_assign_recursive,$0)$(call __var_assign,$1 =,$2)

var_assign_simple = \
$(call assert_called,var_assign_simple,$0)$(call __var_assign,$1:=,$2)

var_assign_append = \
$(call assert_called,var_assign_append,$0)$(call __var_assign,$1+=,$2)

var_assign_conditional = \
$(call assert_called,var_assign_conditional,$0)$(call __var_assign,$1?=,$2)

ifeq ($(MAKE_VERSION),3.81)
var_assign_undefined = $(strip \
$(call assert_called,var_assign_undefined,$0) \
$(if $(filter-out undefined,$(origin $1)),$(call __var_assign,$1:=,)) \
)
else # Since version 3.82 GNU Make provides true 'undefine' directive.
var_assign_undefined = \
$(call assert_called,var_assign_undefined,$0)$(call __var_assign,undefine $1,)
endif

__var_assign = $(strip \
$(call assert,$(strip $1)) \
$(eval $(call escape,$1) $(empty)$2$(empty)) \
)

var_define = \
$(call assert_called,var_define,$0)$(call var_assign_recursive,$1,$2)
var_undefine = \
$(call assert_called,var_undefine,$0)$(call var_assign_undefined,$1,$2)

var_swap = $(strip \
$(call assert_called,var_swap,$0) \
$(call __var_swap,$1,$2,__var_swap_tmp) \
)
__var_swap = \
$(call var_assign_$(flavor $1),$3,$(value $1)) \
$(call var_assign_$(flavor $2),$1,$(value $2)) \
$(call var_assign_$(flavor $3),$2,$(value $3))

var_save = $(strip \
$(call assert_called,var_save,$0) \
$(call set,__var_value,$1,$(value $1)) \
$(call set,__var_flavor,$1,$(flavor $1)) \
)
var_restore = $(strip \
$(call assert_called,var_restore,$0) \
$(call var_assign_$(call get,__var_flavor,$1),$1,$(call get,__var_value,$1))\
)

escape = $(call assert_called,escape,$0)$(call dollar_encode,$1)

dollar_encode = $(call assert_called,dollar_encode,$0)$(subst $$,$$$$,$1)
dollar_decode = $(call assert_called,dollar_decode,$0)$(subst $$$$,$$,$1)

empty:=#

##
# r-patsubst stands for recursive patsubst.
# This function has the same syntax as patsubst, excepting that you should use
# $(call ...) to invoke it.
Expand All @@ -39,7 +175,7 @@ __assert_called = $(if $(filter $1,$2),,$(error $2 must be call'ed))
#
r-patsubst = $(if $(filter $1,$3),$(call $0,$1,$2,$(3:$1=$2)),$3)

#
##
# Extended version of wildcard that understands double asterisk pattern (**).
#
# Usage: $(call r-wildcard,pattern)
Expand All @@ -55,18 +191,18 @@ __r-wildcard = \

# Directory/file versions of wildcard.
# Both of them are based on the fact that wildcard expansion of the expression
# containing the trailing slash drops the slash in files but leaves it in
# containing the trailing slash drops the slash for files but leaves it for
# directories.

#
##
# Directory-only wildcard. This version of wildcard filters out any files
# leaving only directories.
#
# Usage: $(call d-wildcard,pattern)
#
d-wildcard = $(patsubst %/,%,$(filter %/,$(wildcard $(1:%=%/))))

#
##
# File-only wildcard. This version of wildcard leaves only files in the
# expansion result.
#
Expand Down

0 comments on commit d24b01e

Please sign in to comment.