5

I want to add a couple of lines so that the make process can error out if certain directory (set by a Makefile variable DIR1) doesn't exist. Here is the added part but this errors out even if I the directory set by DIR1 exists. For example, I made the directory called 'dir1' but make errors out. What is wrong?

DIR1 = dir1

.PHONY : check_dir

$(info DIR1 = $(DIR1))

check_dir:  
    if [ ! -d $(DIR1) ]; then \
        $(error "DIR1 does not exist! check Makefile!"); \
    fi

This is the run result.(I have directory called dir1 in current directory).

> ckim@chan-ubuntu:~/testmake/test1$ make  
> DIR1 = dir1 Makefile:8:
> *** "DIR1 does not exist! check Makefile!".  Stop.
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
Chan Kim
  • 5,177
  • 12
  • 57
  • 112

1 Answers1

4

The $(error ...) is systematically expanded by make before passing the recipe to the shell. So the error is raised each time this recipe is run, independently from the result of you shell if statement.

Use only shell constructs:

check_dir:  
    if [ ! -d "$(DIR1)" ]; then \
        echo "$(DIR1) does not exist! check Makefile!"; \
        exit 1; \
    fi

Or (a bit more compact, if not easier to understand):

MESSAGE := $(DIR1) does not exist! check Makefile!
check_dir:  
    @[ -d "$(DIR1)" ] || { echo "$(MESSAGE)"; exit 1; }

There are other possibilities like:

check_dir: $(DIR1)

$(DIR1):
    $(error $(DIR1) does not exist! check Makefile!)

But this does not make a difference between a file named $(DIR1) and a directory.

Note: if you want to raise an error when make parses the Makefile and discovers the directory does not exist, you can use the shell function and a make conditional:

OK := $(shell if [ -d $(DIR1) ]; then echo "ok"; fi)

ifeq ($(OK),)
$(error $(DIR1) does not exist! check Makefile!)
endif
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • oh sorry, that if part was not the prerequisite. it was raised to the upper line by the stackoverflow editor. i'll fix it. – Chan Kim Dec 14 '20 at 05:57
  • your first suggention gives me : ckim@chan-ubuntu:~/testmake/test1$ make DIR1 = dir1 if [ ! -d dir1 ]; then \ echo "dir1 does not exist! check Makefile!"); \ exit 1; \ fi /bin/sh: 2: Syntax error: ")" unexpected (expecting "fi") Makefile:7: recipe for target 'check_dir' failed make: *** [check_dir] Error 2. maybe putting exit inside if ~ fi doesn't work? I'm sorry but can you it yourself?(if you have spare time) – Chan Kim Dec 14 '20 at 06:18
  • Inside a recipe, obviously this could be simplified to just `[ -d "$(DIR1") ]` (notice also [When to wrap quotes around a shell variable](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable)) – tripleee Dec 14 '20 at 06:20
  • Renaud, and your second suggestion gives me : make: 'dir1' is up to date. – Chan Kim Dec 14 '20 at 06:23
  • Renaud, the third method surely works. I guess the `if [ -d .. ]` is only for bash and not Makefile. (I saw somewhere on SO it's like also for Makefile.. Hm..) Thanks! – Chan Kim Dec 14 '20 at 06:28
  • @ChanKim Sorry about the trailing `)` at the end of `echo...` in my first suggestion. This was a typo that I just fixed. – Renaud Pacalet Dec 14 '20 at 08:31
  • @ChanKim With the second solution I suggest, if `$(DIR1)` exists, you will get `make: 'dir1' is up to date` because make tells you that there is nothing to be done for `dir1`. This is normal. It is only if it does not exist that you will get the error. – Renaud Pacalet Dec 14 '20 at 08:34
  • @ChanKim The third solution uses the standard `test` shell builtin (`[ -d ... ]`) and works with the default shell used by make (the bourne shell). It should work with any variant of the bourne shell (ksh, bash, zsh...) – Renaud Pacalet Dec 14 '20 at 08:35
  • @tripleee Yes, you're right about the quotes, of course. I fixed this, thanks. But the simplification you suggest (`[ -d "$(DIR1") ]`) would not print the error message. So it would have to be `[ -d "$(DIR1") ] || echo ...` anyway. But then the recipe would no fail and we would need to add something else. Not sure it's easier to understand for beginners. I'll suggest it as an alternative. – Renaud Pacalet Dec 14 '20 at 08:42
  • What I often do is put a comment above the check so that it's clearly visible in the transcript what failed. Making `make` print additional diagnostics is rarely worth the effort. – tripleee Dec 14 '20 at 08:45