something - makefile variables




How to print out a variable in makefile (10)

In my makefile, I have a variable 'NDK_PROJECT_PATH', my question is how can I print it out when it compiles?

I read Make file echo displaying "$PATH" string and I tried:

@echo $(NDK_PROJECT_PATH)
@echo $(value NDK_PROJECT_PATH)

Both gives me

"build-local.mk:102: *** missing separator.  Stop."

Any one knows why it is not working for me?


@echo $(NDK_PROJECT_PATH) is the good way to do it. I don't think the error comes from there. Generally this error appears when you mistyped the intendation : I think you have spaces where you should have a tab.


All versions of make require that command lines be indented with a TAB (not space) as the first character in the line. If you showed us the entire rule instead of just the two lines in question we could give a clearer answer, but it should be something like:

myTarget: myDependencies
        @echo hi

where the first character in the second line must be TAB.


If you don't want to modify the Makefile itself, you can use --eval to add a new target, and then execute the new target, e.g.

make --eval='print-tests: @echo TESTS $(TESTS) ' print-tests

You can insert the required TAB character in the command line using CTRL-V, TAB

example Makefile from above:

all: do-something

TESTS=
TESTS+='a'
TESTS+='b'
TESTS+='c'

do-something:
        @echo "doing something"
        @echo "running tests $(TESTS)"
        @exit 1

If you simply want some output, you want to use $(info) by itself. You can do that anywhere in a Makefile, and it will show when that line is evaluated:

$(info VAR="$(VAR)")

Will output VAR="<value of VAR>" whenever make processes that line. This behavior is very position dependent, so you must make sure that the $(info) expansion happens AFTER everything that could modify $(VAR) has already happened!

A more generic option is to create a special rule for printing the value of a variable. Generally speaking, rules are executed after variables are assigned, so this will show you the value that is actually being used. (Though, it is possible for a rule to change a variable.) Good formatting will help clarify what a variable is set to, and the $(flavor) function will tell you what kind of a variable something is. So in this rule:

print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
  • $* expands to the stem that the % pattern matched in the rule.
  • $($*) expands to the value of the variable whose name is given by by $*.
  • The [ and ] clearly delineate the variable expansion. You could also use " and " or similar.
  • $(flavor $*) tells you what kind of variable it is. NOTE: $(flavor) takes a variable name, and not its expansion. So if you say make print-LDFLAGS, you get $(flavor LDFLAGS), which is what you want.
  • $(info text) provides output. Make prints text on its stdout as a side-effect of the expansion. The expansion of $(info) though is empty. You can think of it like @echo, but importantly it doesn't use the shell, so you don't have to worry about shell quoting rules.
  • @true is there just to provide a command for the rule. Without that, make will also output print-blah is up to date. I feel @true makes it more clear that it's meant to be a no-op.

Running it, you get

$ make print-LDFLAGS
LDFLAGS is a recursive variable set to [-L/Users/...]

Run make -n; it shows you the value of the variable..

Makefile...

all:
        @echo $(NDK_PROJECT_PATH)

Command:

export NDK_PROJECT_PATH=/opt/ndk/project
make -n 

Output:

echo /opt/ndk/project

The problem is that echo works only under an execution block. i.e. anything after "xx:"

So anything above the first execution block is just initialization so no execution command can used.

So create a execution blocl


This can be done in a generic way and can be very useful when debugging a complex makefile. Following the same technique as described in another answer, you can insert the following into any makefile:

# if the first command line argument is "print"
ifeq ($(firstword $(MAKECMDGOALS)),print)

  # take the rest of the arguments as variable names
  VAR_NAMES := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))

  # turn them into do-nothing targets
  $(eval $(VAR_NAMES):;@:))

  # then print them
  .PHONY: print
  print:
          @$(foreach var,$(VAR_NAMES),\
            echo '$(var) = $($(var))';)
endif

Then you can just do "make print" to dump the value of any variable:

$ make print CXXFLAGS
CXXFLAGS = -g -Wall

To print the value of a variable you can use:

rule:
<tab>@echo $(VAR_NAME)

When the rule runs the variable will get printed.



if you use android make (mka) @echo $(NDK_PROJECT_PATH) will not work and gives you error *** missing separator. Stop." use this answer if you are trying to print variables in android make

NDK_PROJECT_PATH := some_value
$(warning $(NDK_PROJECT_PATH))

that worked for me





gnu-make