Search code examples
gnu-makeguile

Generating a complete GNU Make recipe with Guile


I am playing with the $(guile ...) support in GNU Make, but I'm having trouble generating a complete recipe from within Guile.

This traditional approach works as expected:

brazil:
<--tab-->@echo Ere I am J.H.

(where <--tab--> is an ASCII tab character, as required)

But when I try this supposed-equivalent:

$(guile (format #f "brazil:~%~/@echo Ere I am J.H."))

I am treated to the following error message when I run make brazil:

make: *** No rule to make target '@echo', needed by 'brazil'.  Stop.

I was under the impression that with format, ~% encodes a newline, and ~/ encodes a tab character. But based on the error message above, it seems like at least the newline is missing from the generated recipe.


Solution

  • You can't do it this way, just like it won't work to have a $(shell ...) invocation define rules with multiple lines, and just like you can't use define / endef to create an entire multi-line rule then have it simply expanded with $(MY_VAR).

    The expansion of a single line (like a $(guile ...) operation) cannot expand to multiple lines of output: make uses a line-oriented parser and it's already parsed this line: any subsequent newlines will be treated as ordinary spaces (not newlines).

    You need to use $(eval ...) to tell make to treat the output as an actual multi-line makefile snippet. So you want:

    $(eval $(guile (format #f "brazil:~%~/@echo Ere I am J.H.")))
    

    You can also use this instead if you can put the recipe onto a single line:

    $(guile (format #f "brazil: ; @echo Ere I am J.H."))
    

    You can also put the recipe, if it must be multiline, into a variable and use:

    $(guile (format #f "brazil: ; $(MY_RECIPE)"))