I want to call ShellCheck, a Haskell program for linting shell scripts, from a Makefile
.
When I install ShellCheck via cabal install
, it is installed as ~/.cabal/bin/shellcheck
. So, I have configured Bash accordingly:
$ cat ~/.bashrc
export PATH="$PATH:~/.cabal/bin"
$ source ~/.bashrc
$ shellcheck -V
ShellCheck - shell script analysis tool
version: 0.3.4
license: GNU Affero General Public License, version 3
website: http://www.shellcheck.net
This enables me to run shellcheck
from any directory in Bash. However, when I try to call it from a Makefile, make
cannot find shellcheck
.
$ cat Makefile
shlint:
-shlint lib/
shellcheck:
-shellcheck lib/**
lint: shlint shellcheck
$ make shellcheck
shellcheck lib/**
/bin/sh: 1: shellcheck: not found
make: [shellcheck] Error 127 (ignored)
I think that make is not receiving the same PATH
as my normal Bash shell. How can I fix this?
Try using $HOME
, not ~
:
export PATH="$PATH:$HOME/.cabal/bin"
The ~
-means-home-directory feature is not supported in pathnames everywhere in all shells. When make
runs a recipe it doesn't use the user's shell (that would be a disaster!) it uses /bin/sh
always.
On some systems (particularly Debian/Ubuntu-based GNU/Linux distributions) the default /bin/sh
is not bash, but rather dash. Dash doesn't support ~
being expanded in the PATH
variable.
In general, you should reserve ~
for use on the command line as a shorthand. But in scripting, etc. you should always prefer to write out $HOME
.
ETA:
Also, the double-star syntax lib/**
is a non-standard feature of shells like bash
and zsh
and will not do anything special in make
recipes. It is identical to writing lib/*
.
You can force make to use a different shell than /bin/sh
by adding:
SHELL := /bin/bash
to your makefile, for example, but this makes it less portable (if that's an issue).