Mike
Mike

Reputation: 1319

Makefile variable assignment based on an existence of a directory

Looking for ways to assign a variable in a Makefile based on the existence of a directory.

Eg: (pseudo code)

if dir "src/$(project)" exists
SOURCE_DIR := src/$(project)
else
SOURCE_DIR := src/default

test.o: $SOURCE_DIR/test.c
    gcc -c -o $@ $<

What's the best way to achieve the above

Upvotes: 1

Views: 2121

Answers (2)

Stefan Becker
Stefan Becker

Reputation: 5972

As your source directory will contain files and a non-existing directory will not, you can utilize the GNU make internal function $(wildcard):

project := test

# returns all entries under src/$(project) directory or empty string
ifneq ($(wildcard src/$(project)/*),)
SOURCE_DIR := src/$(project)
else
SOURCE_DIR := src/default
endif

.PHONY: all
all:
    @echo $(SOURCE_DIR)

Test run

$ ls src/test/
a.c
$ make
src/test

$ rm -rf src/test
$ make
src/default

BONUS: it might be more readable to rewrite the conditional like this:

SOURCE_DIR := src/$(project)
ifeq ($(wildcard $(SOURCE_DIR)/*),)
  # fall back to default directory
  SOURCE_DIR := src/default
endif

UPDATE 2: if you don't want to rely on the existence of any files in the directory, you can also test the directory name directly. A directory always has an entry ., because it points to itself:

SOURCE_DIR := src/$(project)
ifeq ($(wildcard $(SOURCE_DIR)/.),)
  # fall back to default directory
  SOURCE_DIR := src/default
endif

UPDATE 3: adding a check that $(project) is set:

SOURCE_DIR := src/$(project)
ifeq ($(strip $(project)),)
  # fall back to default directory
  SOURCE_DIR := src/default
else ifeq ($(wildcard $(SOURCE_DIR)/.),)
  # fall back to default directory
  SOURCE_DIR := src/default
endif

or if you prefer makefile Golfing (thanks @MadScientist for the suggestion)

SOURCE_DIR := $(or $(and $(project),$(wildcard src/$(project)/.)),src/default)
  • $(and) result
    • if $(project) is an empty string: empty string
    • if src/$(project) is not a directory: empty string
    • otherwise: src/$(project)/., which is equivalent to src/$(project)
  • $(or) result
    • if $(and) returns empty string: src/default
    • otherwise: the string returned by $(and)

CAVEAT: the above listed tests will fail if $(project) contains white space.

Upvotes: 4

tripleee
tripleee

Reputation: 189799

Try this.

SOURCE_DIR := src/$(shell test -d src/"$(project)" && echo "$(project)" || echo default)

Upvotes: 1

Related Questions