Check if a program exists from a Makefile

后端 未结 12 1081
时光取名叫无心
时光取名叫无心 2020-12-12 20:20

How can I check if a program is callable from a Makefile?

(That is, the program should exist in the path or otherwise be callable.)

It could be used to chec

相关标签:
12条回答
  • 2020-12-12 20:22

    is this what you did?

    check: PYTHON-exists
    PYTHON-exists: ; @which python > /dev/null
    mytarget: check
    .PHONY: check PYTHON-exists
    

    credit to my coworker.

    0 讨论(0)
  • 2020-12-12 20:24

    I am personally defining a require target which runs before all the others. This target simply runs the version commands of all requirements one at a time and prints appropriate error messages if the command is invalid.

    all: require validate test etc
    
    require:
        @echo "Checking the programs required for the build are installed..."
        @shellcheck --version >/dev/null 2>&1 || (echo "ERROR: shellcheck is required."; exit 1)
        @derplerp --version >/dev/null 2>&1 || (echo "ERROR: derplerp is required."; exit 1) 
    
    # And the rest of your makefile below.
    

    The output of the below script is

    Checking the programs required for the build are installed...
    ERROR: derplerp is required.
    makefile:X: recipe for target 'prerequisites' failed
    make: *** [prerequisites] Error 1
    
    0 讨论(0)
  • 2020-12-12 20:26

    Use the shell function to call your program in a way that it prints something to standard output. For example, pass --version.

    GNU Make ignores the exit status of the command passed to shell. To avoid the potential "command not found" message, redirect standard error to /dev/null.

    Then you may check the result using ifdef, ifndef, $(if) etc.

    YOUR_PROGRAM_VERSION := $(shell your_program --version 2>/dev/null)
    
    all:
    ifdef YOUR_PROGRAM_VERSION
        @echo "Found version $(YOUR_PROGRAM_VERSION)"
    else
        @echo Not found
    endif
    

    As a bonus, the output (such as program version) might be useful in other parts of your Makefile.

    0 讨论(0)
  • 2020-12-12 20:27

    Cleaned up some of the existing solutions here...

    REQUIRED_BINS := composer npm node php npm-shrinkwrap
    $(foreach bin,$(REQUIRED_BINS),\
        $(if $(shell command -v $(bin) 2> /dev/null),$(info Found `$(bin)`),$(error Please install `$(bin)`)))
    

    The $(info ...) you can exclude if you want this to be quieter.

    This will fail fast. No target required.

    0 讨论(0)
  • 2020-12-12 20:29

    For me all above answers are based on linux and are not working with windows. I'm new to make so my approach may not be ideal. But complete example that works for me on both linux and windows is this:

    # detect what shell is used
    ifeq ($(findstring cmd.exe,$(SHELL)),cmd.exe)
    $(info "shell Windows cmd.exe")
    DEVNUL := NUL
    WHICH := where
    else
    $(info "shell Bash")
    DEVNUL := /dev/null
    WHICH := which
    endif
    
    # detect platform independently if gcc is installed
    ifeq ($(shell ${WHICH} gcc 2>${DEVNUL}),)
    $(error "gcc is not in your system PATH")
    else
    $(info "gcc found")
    endif
    

    optionally when I need to detect more tools I can use:

    EXECUTABLES = ls dd 
    K := $(foreach myTestCommand,$(EXECUTABLES),\
            $(if $(shell ${WHICH} $(myTestCommand) 2>${DEVNUL} ),\
                $(myTestCommand) found,\
                $(error "No $(myTestCommand) in PATH)))
    $(info ${K})        
    
    0 讨论(0)
  • I mixed the solutions from @kenorb and @0xF and got this:

    DOT := $(shell command -v dot 2> /dev/null)
    
    all:
    ifndef DOT
        $(error "dot is not available please install graphviz")
    endif
        dot -Tpdf -o pres.pdf pres.dot 
    

    It works beautifully because "command -v" doesn't print anything if the executable is not available, so the variable DOT never gets defined and you can just check it whenever you want in your code. In this example I'm throwing an error, but you could do something more useful if you wanted.

    If the variable is available, "command -v" performs the inexpensive operation of printing the command path, defining the DOT variable.

    0 讨论(0)
提交回复
热议问题