9

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.

Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
my_question
  • 3,075
  • 2
  • 27
  • 44
  • Another piece of information: When I try to reproduce this, I add the command `type lsc` to the rule, and it gives the correct answer-- but the command `lsc` still fails. – Beta Oct 29 '12 at 01:24

6 Answers6

10

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!
luismartingil
  • 1,029
  • 11
  • 16
7

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.

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198
2

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

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

Sebastian
  • 1,839
  • 12
  • 16
  • 1
    Yes, I tried "export -f", not help. Not sure your 2nd question mean, my shell is bash and I run make in it. – my_question Oct 29 '12 at 04:14
  • Did you set the SHELL variable? See here: http://www.gnu.org/software/make/manual/html_node/Choosing-the-Shell.html#Choosing-the-Shell "If this variable is not set in your makefile, the program /bin/sh is used as the shell." – Sebastian Oct 29 '12 at 23:57
1

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"
Evandro Coan
  • 8,560
  • 11
  • 83
  • 144
0

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
ZK_
  • 494
  • 5
  • 14
0

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.

Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
  • Method 4: declare the function inline as part of a [multi-line bash command](https://stackoverflow.com/questions/10121182/multi-line-bash-commands-in-makefile/29085684#29085684). Don't forget `SHELL=bash`. – Brent Bradburn Mar 17 '23 at 23:20
  • Scripting `nvm` is a pain. [nvm command not available in bash script](https://unix.stackexchange.com/q/184508/6764) – Brent Bradburn Aug 09 '23 at 15:29