Search code examples
dependenciesuser-defined-functionsgnu-make

GNU Make: how can I set up two or more dependency targets within a single define..endef block?


I'm trying to set up multiple dependencies within a single GNU Make define..endef block, but I'm having no luck at all. If I strip the problem down to a basic form, I'm aiming for a final makefile that looks like this:

all:    CPU1    CPU2

CPU1: Build_CPU1

CPU2: Build_CPU2

Build_CPU1:
    @echo Building CPU #1

Build_CPU2:
    @echo Building CPU #2

The problem comes if I try to put the two intermediate dependencies inside a define..endef block:

all:    CPU1    CPU2

define DoBuild =
CPU1:   Build_CPU1



CPU2:   Build_CPU2



endef

$(call DoBuild)

Build_CPU1:
    @echo Building CPU #1

Build_CPU2:
    @echo Building CPU #2

If I put a bare newline after each of the two :-dependency lines (i.e. "CPU1: Build_CPU1" and "CPU2: Build_CPU2") in the define..endef block, GNU Make complains about "*** target pattern contains no '%'". But if I add in a space-then-newline after the two dependencies, that error message goes away.

However, having followed the two dependency lines with space-then-newline, GNU Make complains about "*** multiple target patterns."

What I'm pretty sure is happening here is that GNU Make is collapsing all the lines of the define..endef block into a single line: and, of course, you can't have multiple colons on a single line.

According to the GNU Make manual 6.8 ("Defining Multi-Line Variables"), you should be able to force a newline inside a define..endef block by using two newlines. However, the problem with this seems to be that this is ultimately defining a single variable, and so is being parsed as if it were a single line, even though it contains newlines. Which is (I think) why it is collapsing the two dependencies into a single line (placing both the colons on a single line), so I'm basically out of ideas. :-(

Is there any way of convincing GNU Make to define two or more dependency targets within a single define..endef block?

PS: I'm using GNU Make 4.2.1


Solution

  • The following is a working example:

    all: CPU1 CPU2
    
    define DoBuild # No equal sign is needed.
    CPU1: Build_CPU1
        @echo $$@
    CPU2: Build_CPU2
        @echo $$@
    endef
    
    $(eval $(call DoBuild)) # Use eval.
    
    Build_CPU1:
        @echo $@
    
    Build_CPU2:
        @echo $@
    

    Note that call returns a string. To make that string a part of the makefile eval is required.