Tuesday, 7 June 2016

Defining bash functions in a Makefile

As I answered here; a makefile recipe may depend on bash functions rather than bash scripts.

Because of bash's export -f function-name feature to export a bash function definition into the environment where it will be picked up by sub-child invocations of bash, we can define a bash variable in the environment in the same form in the Makefile.

If we define bash functions in the Makefile using the same format bash does, and export them into the environment, and set SHELL=bash then we can use these bash functions in the make recipe.

Let's see how bash formats functions exported in the environment:

$ # define the function
$ something() { echo do something here ; }
$ export -f something

$ # the Makefile
$ cat > Makefile <<END
SHELL=bash
all: ; something
END
$

Try it out

$ make
something
do something here
$

How does this look in the environment?

$ env | grep something
BASH_FUNC_something%%=() { echo do something here

The pattern is (currently):
  BASH_FUNC_function-name%%=() { function-body }

So we do this in the Makefile:

SHELL=bash
define BASH_FUNC_something-else%%
() {
  echo something else
}
endef
export BASH_FUNC_something-else%%

all: ; something-else

and try it:

$ make
something-else
something else

It's a bit ugly in the Makefile but presents no ugliness for make -n