Question

I'm trying to check whether a variable is defined using ifndef/ifdef, but I keep getting a not found error from the execution. I'm using GNU Make 3.81, and here is a snippet of what I have:

all: _images                 
    $(call clean, .)         
    $(call compile, .)       
    @$(OPENER) *.pdf &       

_images:                     
    $(call clean, "images")  
    $(call compile, "images")

define clean                                             
    @rm -f ${1}/*.log ${1}/*.aux ${1}/*.pdf              
endef                                                    

define compile                                           

    ifdef ${1}                                           
        dir = ${1}                                       
    else                                                 
        dir = .                                          
    endif                                                

    ifdef ${2}                                           
        outdir = ${2}                                    
    else                                                 
        outdir = ${1}                                    
    endif                                                

    @$(COMPILER) -output-directory ${outdir} ${dir}/*.tex

endef                                                    

And the exact error:

$ make                       
ifdef  "images"              
/bin/sh: 1: ifdef: not found 
make: *** [_images] Error 127

Edit:

Considering Barmar comments, here goes the conclusions:

The contents of a define are shell command lines, not make directives; to break lines inside commands within a define block, the linebreak must be escaped -- with \; also, each block corresponding to one-liner commands is executed separately, each in a different shell execution, which means that, defining local variables won't work if the intention is to access the variable value in the next one-liner block.

Thanks tripleee for the nice work around.

Was it helpful?

Solution

You can combine the shell's facilities with Make's to get a fairly succinct definition.

define compile
        @dir="${1}"; outdir="${2}"; outdir=$${outdir:-"$dir"}; \
        $(COMPILER) -output-directory "$${outdir}" "$${dir:-.}/*.tex

The double-dollar is an escape which passes a single dollar sign to the shell. The construct ${variable:-value} returns the value of $variable unless it is unset or empty, in which case it returns value. Because ${1} and ${2} are replaced by static strings before the shell evaluates this expression, we have to take the roundabout route of assigning them to variables before examining them.

This also demonstrates how to combine two "one-liners" into a single shell invocation. The semicolon is a statement terminator (basically equivalent to a newline) and the sequence of a backslash and a newline causes the next line to be merged with the current line into a single "logical line".

This is complex enough that I would recommend you omit the leading @ but I left it in just to show where it belongs. If you want silent operation, once you have it properly debugged, run with make -s.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top