2

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?

Will
  • 24,082
  • 14
  • 97
  • 108
mcandre
  • 22,868
  • 20
  • 88
  • 147

1 Answers1

1

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).

MadScientist
  • 92,819
  • 9
  • 109
  • 136