Search code examples
shellmakefileprotocol-buffersprotoc

why does find work inside makefile but not glob **/*.proto for protoc compiler


I recently wrote a Makefile instruction for compiling .proto files and ran into odd behavior.

This command works when running in my own shell, but when inside a Makefile target...

    protoc \
        --proto_path ./protos \
        --go_out ./protos/gen \
        --go_opt paths=source_relative \
        --go-grpc_out ./protos/gen \
        --go-grpc_opt paths=source_relative \
        ./protos/**/*.proto

...it fails with:

Could not make proto path relative: ./protos/**/*.proto: No such file or directory

However, this does work inside the Makefile:

    protoc \
        --proto_path ./protos \
        --go_out ./protos/gen \
        --go_opt paths=source_relative \
        --go-grpc_out ./protos/gen \
        --go-grpc_opt paths=source_relative \
        $(shell find ./protos -name '*.proto')

The only difference is the last argument.

Specifically, inside the Makefile:

  • This correctly expands all the files: $(shell find ./protos -name '*.proto')
  • But, this does not: ./protos/**/*.proto

My question is How come the expansion of files via ./protos/**/*.proto does not work with Make?


Solution

  • Because make invokes /bin/sh as its shell, and /bin/sh is a POSIX shell which does not support ** as a globbing operation.

    Using ** to mean "search all subdirectories" is non-standard, extra feature of some shells like bash, etc.