Tim F.
Tim F.

Reputation: 300

Usage of bash commands within Go makefiles

It is possible to exclude _test.go files when using go run via the command line (MacOS).

go run $(ls -1 dir/*.go | grep -v _test.go)

However, it seems the command isn't used in a similar manner via a Go makefile. For example,

start:
    go run $(ls -1 dir/*.go | grep -v _test.go)

and

start:
    go run `$(ls -1 dir/\*.go | grep -v _test.go)`

both result in,

go run: no go files listed

What is the correct way to use grep and similar commands inside of a Go makefile?

Upvotes: 1

Views: 239

Answers (2)

tripleee
tripleee

Reputation: 189387

As already mentioned in another answer, the trivial solution is to double all dollar signs to prevent Make from attempting to interpret them as Make variables or functions. Equivalently, you could use the obsolescent command substitution syntax `ls ... stuff` with backticks instead of $(ls ... stuff)

However, that approach is more fundamentally flawed in that it descends into the deep morass of corner cases that affect parsing ls output. A more robust approach is to use Make functions to express the pattern.

go run $(filter-out %_test.go,$(wildcard dir/*.go))

I'll also mention that Bash has a feature called extended globbing (google extglob) where you can say something like !(dir/*_test.go)dir/*.go to exclude a set of files from a wildcard match. But you probably don't want to wreck the portability of your Makefile when Make has built-in functionality which provides the same functionality (albeit with a more verbose syntax. That's a feature, actually, because it makes it easy for a new maintainer to google the function names and figure out what the code does!)

Upvotes: 1

MadScientist
MadScientist

Reputation: 100836

Dollar signs are special to make: they introduce make variables and functions. If you want to use a literal dollar sign in your recipe you need to escape it by doubling it:

start:
        go run $$(ls -1 dir/*.go | grep -v _test.go)

Upvotes: 2

Related Questions