my_question
my_question

Reputation: 3235

Cannot call bash function inside makefile

I have an impression that I can call bash function inside GNU makefile, but seems wrong. Here is a simple test, I have this function defined:

>type lsc
lsc is a function
lsc () 
{ 
    ls --color=auto --color=tty
}

Here is my Makefile:

>cat Makefile
all:
    lsc

Here is what I get in running make:

>make
lsc
make: lsc: Command not found
make: *** [all] Error 127

Is my impression wrong? Or is there any env setup issue? I can run "lsc" at the command line.

Upvotes: 10

Views: 9462

Answers (6)

Brent Bradburn
Brent Bradburn

Reputation: 54859

This issue is not unique to make. Make executes commands in the context of a shell, and that shell can execute functions if they've been made available.

The problem is that when you launch a new shell (or shell script, or make command), Bash doesn't automatically forward all functions from the calling environment.

Explicitly specifying that the shell should be /bin/bash ensures that make won't invoke a different shell interpreter, which could affect function handling. There are a couple ways of doing this. In the examples below, I use the targeted-specific approach.

As an example, the below makefile snippets invoke nvm which is implemented as a collection of bash functions.

WARNING: Using previously-defined functions means the makefile depends on the (potentially uncontrolled) state of your shell environment, so this type of solution should be used judiciously.


Method 1: Run an "interactive" shell

In this example, the functions are assumed to be defined as part of a users's .bashrc file. Running Bash in interactive mode (with -i) causes .bashrc to be processed into the command environment.

mytarget1: SHELL:=/bin/bash -i
mytarget1:
    nvm install 14 && npm version

Method 2: Import the functions on demand

This approach explicitly sources the script that defines the functions of interest.

mytarget2:
    . ~/.nvm/nvm.sh && nvm install 14 && npm version

For this, you might prefer: Multi-line bash commands in makefile


Method 3: Export the function before running makefile

Invoke make with: export -f nvm ; make mytarget3 to export the function to any sub-commands.

mytarget3: SHELL:=/bin/bash
mytarget3:
    nvm install 14 && npm version

Note: This example won't work fully because nvm, internally, relies on a large collection of sub-functions which would also need to be exported.

Upvotes: 0

ZK_
ZK_

Reputation: 564

suppose compile is a function in you .bash_profile

.bash_profile

compile(){
  ...
}

Makefile

ACTIVE_ENV=source ~/.bash_profile 
default:
    $(ACTIVE_ENV) && compile boot_sect_simple.asm c

Upvotes: 0

Evandro Coan
Evandro Coan

Reputation: 9418

You can import all shell scripts functions from a shell file if you use this from the question How do I write the 'cd' command in a makefile?

.ONESHELL: my_target

my_target: dependency
    . ./shell_script.sh
    my_imported_shell_function "String Parameter"

If you like, you can also even do not use the .ONESHELL thing and do it all in one line just by using a colon ; right after the importing the shell script:

my_target: dependency
    . ./shell_script.sh; my_imported_shell_function "String Parameter"

Upvotes: 1

luismartingil
luismartingil

Reputation: 1109

Use $* in your BASH script:

functions.sh

_my_function() {
  echo $1
}

# Allows to call a function based on arguments passed to the script
$*

Makefile

test:
    ./functions.sh _my_function "hello!"

Running example:

$ make test
./functions.sh _my_function "hello!"
hello!

Upvotes: 12

Olaf Dietsche
Olaf Dietsche

Reputation: 74018

You cannot call bash functions or aliases in a Makefile, only binaries and scripts. What you can do however, is calling an interactive bash and instruct it to call your function or alias:

all:
    bash -i -c lsc

if lsc is defined in your .bashrc, for example.

Upvotes: 11

Sebastian
Sebastian

Reputation: 1889

Did you export your function with "export -f"?

Is bash the shell of your Makefile, or is is sh?

Upvotes: 2

Related Questions