0

Is is possible to use shell arguments inside a makefile function? e.g.

mywords:=hello there neighbour

myrecipe:
    for ((i = 0 ; i < 3 ; i++)); do \
        this_word=$(word $${i}, $(mywords)); \
    done

Except myrecipe gives the error non-numeric first argument to 'word' function: '${i}'. Stop

2
  • You're trying to use a Make function inside a shell function, and no, it won't work. Is this just exploration, or are you actually trying to do something? Commented Mar 23, 2022 at 7:11
  • 3
    No, any shell arguments are expanded after the makefile function is done. However, what you present is the shell function for. You can the line with for this_word in $mywords; do \ and you'll have shell variable this_word set each iteration. Commented Mar 23, 2022 at 7:13

1 Answer 1

1

Remember that make first expands the entire recipe (yes, that's all of the recipe lines) before ever doing anything with the shell. Only after this full expansion does make then look for individual recipe lines, running each one in turn.

Thus make behaves sensibly when you have a macro that expands to more than one line.

It also hints that you should use make functionality wherever possible.

mywords := hello there neighbour

define mkcommand
    echo $1
    something $1
endef

myrecipe:
    $(foreach _,${mywords},$(call mkcommand,$_))

Now, when you ask make to build myrecipe, make sees something like:

myrecipe:
    echo hello
    something hello
    echo there
    something there
    ⋮

IMHO it's nearly always a mistake if you find yourself writing shell loops in a makefile.

Sign up to request clarification or add additional context in comments.

2 Comments

I agree with your description of make's operation, but not necessarily with your recommendation. If one is interested in writing portable (that is, not GNU-specific) makefiles, then make itself sometimes doesn't provide what you need. Moreover, even when GNU make is targeted, I find it much clearer to reserve make functions for top-scope code, and to use only shell code in recipes. One may be able to avoid looping at all, but if a loop must appear in a recipe then I would prefer it to be expressed in shell language.
I respectfully disagree. Doing it in make invariably produces cleaner build files in my experience, covers more corner cases, and is easier to refactor. Admittedly I know make quite well. For example, most loops do not check for non-zero exit codes properly. Parallel builds also start working, and we all have more than one CPU nowadays (your makefile is broken if it doesn't work when building in parallel). Shell loops are usually a sign that the author isn't familiar with make. Similar problems accrue when $(shell … ) is overused. YMMV applies of course.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.