Makeifle: if condition block in define block

Viewed 70

I create a define block

I'd like to check the program whether in the $PATH env.var,

i.e. whether program exists.

define CheckProgExist
    @$(eval exist=$(shell ${1} ${2} 2> /dev/null))
    @$(info ${1} ${2})
    @$(info ${exist})
    ifneq (${exist},"")
        @$(error "${1} does not exist in the $${PATH} of env.var")
    endif
endef

First Line: @$(eval exist=$(shell ${1} ${2} 2> /dev/null))

Check command exists,

  • ${1} is command I specify
  • ${2} flags of program which I can check if program exists, generally:
    • return version message (to stdout) if program exists
    • return null(maybe) if program doesn't exist, because I've redirected stderr to null, output should be null

Second line: @$(info ${1} ${2})

Display argument I input.

Third line: @$(info ${exist})

Display content of variable, if

  • ${1} exists, ${exist} should be message of version and program
  • ${2} does not exists, ${exist} should be empty (or null)

Fourth Line: ifneq (${exist},"")

If variable does not exist, then abort makefile


For example, I'd like to check whether ls exist:

chk_env_hw:
    @$(call CheckProgExist,ls,--version)

If program ls does not exist, then error message will display.

But the result seems strange:

>$ make
ls --version
ls (GNU coreutils) 8.32 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.  Written by Richard M. Stallman and David MacKenzie.
Makefile:11: *** "ls does not exist in the ${PATH} of env.var".  Stop.

ls is exist but the result shows not.


fully code

define CheckProgExist
    @$(eval exist=$(shell ${1} ${2} 2> /dev/null))
    @$(info ${1} ${2})
    @$(info ${exist})
    ifneq (${exist},"")
        @$(error "${1} does not exist in the $${PATH} of env.var")
    endif
endef

chk_env_hw:
    $(call CheckProgExist,ls,--version)

1 Answers

You have several problems here:

  1. ifneq (${exist},"") will fire the error if ${exist} is not equal to "", which is the case. Try ifneq (${exist},).
  2. ls --version sends its output to the standard output, not the standard error, so in your case, with ls --version, exist will not be the empty string. It will be something like ls (GNU coreutils) 8.32...
  3. What you're doing is a strange mixture of make and shell constructs. Make recipes are shell scripts. There is no need to call the shell make function in a recipe. You should maybe try to write a make macro with 100% shell content (including shell variables if you need some). Do not forget to escape the make expansion if needed.

You could try something like (not tested):

define CheckProgExist
@command -v '$(1)' > /dev/null || { echo "$(1) does not exist"; exit 1; }
endef

.PHONY: chk_env_hw

chk_env_hw:
    $(call CheckProgExist,ls)

(edited to use command -v as suggested by MadScientist instead of the non-POSIX which).

Related