How to Write Bash Scripts in Makefiles

bashmake

I love to type bash scripts, but if I prepare multiple tools, project's root directory is filled with so many shell scripts. That's why I prefer using Makefile.

Makefile is good. However I want to build my makefiles just as regular bash scripts.

Eg:

Think that I wrote a bash script very quickly with the following content:

#!/bin/bash
echo "hello"
cd ~
do-some-work.sh my-parameter

I can run this script with $ ./my-important-task.sh.

If I wanted to move that script into makefile, I should do the following:

SHELL := /bin/bash 

my-important-task: 
    echo "hello" ;\
    cd ~ ;\
    do-some-work.sh my-parameter

but I want the following:

my-important-task: 
    [[copy and paste the my-important-task.sh file]]

Is there anyway to accomplish this goal?

Best Answer

If you really want to “write exactly bash scripts into Makefiles” then you'll need to do it a bit indirectly. If you just paste the script after the target line, then you'll run into two problems that just cannot be bypassed: the command lines need to be indented with a tab, and dollar signs need to be escaped.

If you use GNU make (as opposed to BSD make, Solaris make, etc.), then you can define your script as a variable using the multi-line definition syntax, and then use the value function to use the raw value of the variable, bypassing expansion.

In addition, as explained by skwllsp, you need to tell make to execute the command list for each target as a single shell script rather than line by line, which you can do in GNU make by defining a .ONESHELL target.

define my_important_task =
# script goes here
endef

my-important-task: ; $(value my_important_task)

.ONESHELL:
Related Question