LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   how to print variable value in Makefile? (https://www.linuxquestions.org/questions/programming-9/how-to-print-variable-value-in-makefile-438225/)

George2 04-24-2006 01:41 AM

how to print variable value in Makefile?
 
Hello everyone,


I want to print variable value of Makefile, but it seems that simple echo command is not working.

This is my Makefile,

--------------------
Foo=newdir
echo $Foo
--------------------

when I execute make, it prints out the following error message,

--------------------
Makefile:2: *** missing separator. Stop.
--------------------

I am using Red Hat Linux 9.0. Does anyone know what is the correct approach to print out the value of a variable?


thanks in advance,
George

Dark_Helmet 04-24-2006 02:25 AM

It would be extremely beneficial to read the documentation on make. It's very thorough and not too terribly technical in the language it uses. I say that because the Makefile you present demonstrates a basic mistake.

Makefiles aren't like shell scripts. You need to create targets (objects that make tries to create). The make command only looks for commands to execute related to a specific target, and also requires the command to be indented with a tab character as the first character on the line. The documentation describes it a little better. To give you a Makefile that will accomplish what you want, use this:
Code:

Foo=newdir

.PHONY: print_vars

print_vars:
echo $(Foo)


George2 04-24-2006 03:54 AM

Dark_Helmet.


Quote:

Originally Posted by Dark_Helmet
It would be extremely beneficial to read the documentation on make. It's very thorough and not too terribly technical in the language it uses. I say that because the Makefile you present demonstrates a basic mistake.

Makefiles aren't like shell scripts. You need to create targets (objects that make tries to create). The make command only looks for commands to execute related to a specific target, and also requires the command to be indented with a tab character as the first character on the line. The documentation describes it a little better. To give you a Makefile that will accomplish what you want, use this:
Code:

Foo=newdir

.PHONY: print_vars

print_vars:
echo $(Foo)


Thank you for your great reply! I would like to read through the Makefile document. But I do not know which document do you mean. Could you provide an URL please?

Another question is that, what is the use of .PHONY target? I think the following Makefile will work the same,

Code:

Foo=newdir
print_vars:
echo $(Foo)


regards,
George

Dark_Helmet 04-24-2006 10:27 AM

The ".PHONY" tag is a special "target" that tells the Makefile there are no dependencies to check against. In short, any target listed as a phony will always execute the commands for the target no matter what. Contrast that behavior with a normal target (one with .c or .h file dependencies) where the commands to create the target are only executed if one or more of the dependencies has changed.

The documentation I was referring to is located here:
Make manual

George2 04-25-2006 02:01 AM

Thanks Dark_Helmet,


Quote:

Originally Posted by Dark_Helmet
The ".PHONY" tag is a special "target" that tells the Makefile there are no dependencies to check against. In short, any target listed as a phony will always execute the commands for the target no matter what. Contrast that behavior with a normal target (one with .c or .h file dependencies) where the commands to create the target are only executed if one or more of the dependencies has changed.

The documentation I was referring to is located here:
Make manual

I still do not quite understand what do you mean "no dependencies to check against". Do you mean no need to check whether the dependencies have changed? Or also including other situations to check?


regards,
George

Dark_Helmet 04-25-2006 02:28 AM

No dependencies to check for modification.

When make is invoked, it compares the timestamp for the target's last modification against the timestamps of the target's dependencies. If the target's modification timestamp is the most recent, then the target is "up to date" and make will not perform any commands for the target. If, however, one (or more) of the target's dependencies has a more recent modification timestamp than the target itself, the target needs o be updated to reflect the changes made since the last time make was run for that target.

So, what's the timestamp for a non-existent target? When "make print_vars" is issued, we have no file representing our up-to-date target. The commands do not create a file named print_vars. So there's nothing for make to get a timestamp from. Not only that, but the print_vars target has no dependencies either. So make couldn't even look at those timestamps. So what should make do? I think the documentation says that in this case, make will do nothing for the target. The makefile needs to specify ".PHONY" to tell make to ignore its normal timestamp-check and execute the commands regardless. It's the same concept behind the "make clean" target found in many source code tarballs. The "clean" target does not create a "clean" file -- the commands are meant to accomplish the side-effect of deleting all the object files and executables for the project (to allow a from-scratch recompile).

George2 04-25-2006 04:47 AM

Thanks Dark_Helmet,


Quote:

Originally Posted by Dark_Helmet
No dependencies to check for modification.

When make is invoked, it compares the timestamp for the target's last modification against the timestamps of the target's dependencies. If the target's modification timestamp is the most recent, then the target is "up to date" and make will not perform any commands for the target. If, however, one (or more) of the target's dependencies has a more recent modification timestamp than the target itself, the target needs o be updated to reflect the changes made since the last time make was run for that target.

So, what's the timestamp for a non-existent target? When "make print_vars" is issued, we have no file representing our up-to-date target. The commands do not create a file named print_vars. So there's nothing for make to get a timestamp from. Not only that, but the print_vars target has no dependencies either. So make couldn't even look at those timestamps. So what should make do? I think the documentation says that in this case, make will do nothing for the target. The makefile needs to specify ".PHONY" to tell make to ignore its normal timestamp-check and execute the commands regardless. It's the same concept behind the "make clean" target found in many source code tarballs. The "clean" target does not create a "clean" file -- the commands are meant to accomplish the side-effect of deleting all the object files and executables for the project (to allow a from-scratch recompile).

Thank you very much for your great reply! I have also taken reference to some Makefile samples. I think your option is that, the .PHONY target should be used in the situation when there is no existing files to check timestamp (for some special case), is that correct? But I found that in some samples on the internet, .PHONY target is defined the same as the default "all" target, like

.PHONY: all

I think it is not the case you mentioned that there is no existing file to check timestamp.

Another question is that, what do you mean "accomplish the side-effect of deleting all the object files and executables for the project"?


regards,
George

bigearsbilly 04-25-2006 08:00 AM

Try:
Code:

FOO = newdir

help:
<TAB>echo FOO = ${FOO}

make help


make -pns | grep FOO

George2 04-25-2006 08:40 AM

Thanks bigearsbilly,


Quote:

Originally Posted by bigearsbilly
Try:
Code:

FOO = newdir

help:
<TAB>echo FOO = ${FOO}

make help


make -pns | grep FOO

Why use make -pns? I have tried that make help also works.


regards,
George

bigearsbilly 04-25-2006 09:20 AM

make -pns (chortle) prints out variables and macros.

for example I have a messy tcl script for evaluating all variables
using make -pns

so for a makefile:
Code:

AA = ${PWD}
AAA = ${AA}

all:

I get:
Code:

billym.primadtpdev>makelook| grep AAA
AAA =  ${AA}
AAA =  ${PWD}
AAA =    /export/home/billym/bin

Code:

#!/bin/sh
# \
exec tclsh "$0" "$*"

# attempt to display all macro expansions
# invoked in a makefile

set macro_list ""

puts $argc
foreach nm [ array names $argv ] {
puts "$nm"
}


set infile [ open "|make -pns" r ];


while { [gets $infile line] != -1 } {
    if { [ regexp -- {^ *([a-zA-Z0-9_]*) *\=(.*)} $line dummy var value ]  } {
 set macro_list [concat $macro_list $var ]
 set $var $value
 }
}



foreach nm $macro_list {

    set val [ set $nm ]
    puts "$nm = $val"


    set newval " "
    while { [regexp {[^ ]*} $val dummy]  } {

 regsub -all {[)(]} $val {} val

 if { [catch  {set newval [ subst $val]}  ] } {
  set newval $val
    }

 if { $val == $newval } break
 puts "$nm = $newval"
 set val $newval
 ### break

    }; ### while loop

}; ### foreach macro


George2 04-26-2006 02:11 AM

Thanks bigearsbilly,


Quote:

Originally Posted by bigearsbilly
make -pns (chortle) prints out variables and macros.

for example I have a messy tcl script for evaluating all variables
using make -pns

so for a makefile:
Code:

AA = ${PWD}
AAA = ${AA}

all:

I get:
Code:

billym.primadtpdev>makelook| grep AAA
AAA =  ${AA}
AAA =  ${PWD}
AAA =    /export/home/billym/bin

Code:

#!/bin/sh
# \
exec tclsh "$0" "$*"

# attempt to display all macro expansions
# invoked in a makefile

set macro_list ""

puts $argc
foreach nm [ array names $argv ] {
puts "$nm"
}


set infile [ open "|make -pns" r ];


while { [gets $infile line] != -1 } {
    if { [ regexp -- {^ *([a-zA-Z0-9_]*) *\=(.*)} $line dummy var value ]  } {
 set macro_list [concat $macro_list $var ]
 set $var $value
 }
}



foreach nm $macro_list {

    set val [ set $nm ]
    puts "$nm = $val"


    set newval " "
    while { [regexp {[^ ]*} $val dummy]  } {

 regsub -all {[)(]} $val {} val

 if { [catch  {set newval [ subst $val]}  ] } {
  set newval $val
    }

 if { $val == $newval } break
 puts "$nm = $newval"
 set val $newval
 ### break

    }; ### while loop

}; ### foreach macro


Your reply is great! But I think I am talking about using Makefile to build C/C++ applications, what is the relationship of your tcl script with my topic?


regards,
George

bigearsbilly 04-26-2006 07:17 AM

printing variables, maybe ;)

George2 04-27-2006 05:12 AM

Thanks bigearsbilly,


Quote:

Originally Posted by bigearsbilly
printing variables, maybe ;)

I am wondering why using so complex a sample to print out variables. What points this sample want to prove and illustrate? Could you provide a simple and clear sample please? :-)


regards,
George


All times are GMT -5. The time now is 01:14 PM.