From gnulists@ai.mit.edu Sat Aug 24 23:57:54 1991 From: lrs@indetech.com (Lynn Slater x2048) To: bug-gnu-utils@prep.ai.mit.edu, jlee@sobeco.com, lrs@indetech.com Subject: Explaination of common makefile errors -- Save this posting Date: Tue, 20 Aug 91 13:04 PDT > The problem is that the dependencies are being evaluated when the rule is > encountered rather than after the variable definitions have been sorted > out. This means that when variables are used for expressing the > dependencies but (re)defined later in the makefile you don't get the same > evaluation for the dependency list as in the body of the rule. This is a basic make problem (not just gnumake). As this problem seems to be one of the "top 10" reasons for makefile errors, let me clarify this for others. Basic make operation: Anything on the rule definition line (i.e. rule: dependents) is evaluated in full when encountered; thus the most reciently set value wins. For this purpose, there is no difference between = and := assignments. Anything in the body of the rule is evaluated if and when the rule is executed; thus the last value set wins. = assignments are plain string substutions that are not expanded, even before being passed to shells. Here is a makefile that will demonstrate a few of these features. Many of these will surprize even the old-timers. Save this and pass it on to new folks -- a few minutes with this file can save hours later. =============================================================== Lynn Slater -- lrs@indetech.com or {sun, ames, pacbell}!indetech!lrs 42075 Lawrence Place, Fremont Ca 94538 Office (415) 438-2048; Home (415) 793-1864; Fax (415) 438-2034 =============================================================== -*- File: /net/src/tools/process/ibuild/src/integration/Makefile_Funnies.mk ############################## -*- Mode: Make -*- ############################# ## Makefile_Funnies.mk -- demonstrate makefile oddities ## ## AFSID : $__Header$ ## RCSID : $Header: /net/src/tools/process/ibuild/src/integration/RCS/Makefile_Funnies.mk,v 1.17 1991/08/19 18:49:49 lrs Exp lrs $ ## Author : Lynn Slater ## Created On : Mon Oct 1 11:53:01 1990 ## Last Modified By: Lynn Slater x2048 ## Last Modified On: Tue Aug 20 13:00:41 1991 ## Update Count : 48 ## State : $State: Exp $ ## ## HISTORY ## 22-May-1991 Lynn Slater x2048 ## Last Modified: Mon Oct 1 12:31:15 1990 #8 (Lynn Slater) ## cleaned up documentation ## ## PURPOSE ## This file demonstrates various oddities in makefiles that might ## affect developers. Consider this to be sort of the equivilent to the "C ## Puzzle Book". Read the first part of this makefile and try to guess what ## a "make all" will do. Then try the make all and see if you are correct. ## If you were correct, you are hereby certified as a make guru class 2. ## ## After trying this, do a make all_explained and read the rest of the makefile. ## ## Note: the author has emacs routines that maintain these makefile rule ## doc boxes and the related table of contents. There is even automatic ## conversion to framemaker documentation available. ## ## This file is not copyrighted ## This file has no doc because it is a standalone example. ## ## TABLE OF CONTENTS ## Rules ## ${variable}: -- Demo use of value in a command target name ## all_explained: -- Master rule to make all the commented targets ## ${variable}: -- Demonstrate rule with safe body ## demo_env: -- Demonstrates getenv error with = assignments ## Command Variables ## variable -- Describe oddity about assignment ## temp_variable -- This shows how to force instantious eveluation ## ############################################################################### ## ###################################################################### ## First, demo without comments, as you would most likely see it in a real ## makefile. ## ###################################################################### var=val1 ${var}: @echo making $@ but var is ${var} all: ${var} var=val2 ${var}: @echo making $@ but var is ${var} all: ${var} var = val3 temp_var := ${var} ${var}: @echo making $@ but variable is ${temp_var} all_explained: ${variable} all: ${var} var = val4 vars: @echo making $@ but var is ${var} odd: # This is a comment # Comment line 2 # This is comment line 3, but why are you seeing this? # Will you ever know? What happened to comment line 2? # What it this happened in YOUR makefile? # invisible comment line odd_env: @echo env 1 is ${OENV1} or $$OENV1 @echo env 2 is ${OENV2} or $$OENV2 @echo env 3 is ${OENV3} or $$OENV3 OENV1=1 OENV2=${OENV1} OENV3:=${OENV1} # Your challenge is to guess what the next rule does. all: vars odd odd_env ### *** !!!!!!!!!!!!!!!!!!!! STOP READING !!!!!!!!!!!!!!!!!! *** ### ## ###################################################################### ## Here are essentially the same rules, with some comments. ## Reading past this point before doing the puzzle would be cheating! ## ###################################################################### ####################################################################### ## variable -- Describe oddity about assignment ## DESCRIPTION ## Variables in makefiles are expanded at time of use. In practice, ## this means that variables used in the body of a rule can be defined ## anywhere in the makefile and the last definition wins (because the ## entire makefile is scanned). ## NOTES ## CAVEATS AND BUGS variable=value1 ####################################################################### ## ${variable}: -- Demo use of value in a command target name ## DESCRIPTION ## This variable is evaluated upon makefile scan and is value1 ## Later assignments to variable have no effect on this rule name, but will ## have an affect on references to variable in the rule body ## NOTES ## In the body, the ${variable} is evaluated upon rule execution and is value3 ## CAVEATS AND BUGS ## This example shows something that will be responsible fpor many ## makefile funnies ${variable}: @echo making $@ but variable is ${variable} ####################################################################### ## all_explained: -- Master rule to make all the commented targets ## DESCRIPTION ## Note that this rule depends upon a value held in a variable. That ## variable is scanned WHEN THIS RULE IS FRST SCANNED and will not change ## with later assignments. ## NOTES ## In a mkaefile, this can cause poor dependency eveluation with some ## types of mix and match, because you will depend upon the wrong versions ## of the files. ## CAVEATS AND BUGS all_explained: ${variable} variable=value2 ${variable}: @echo making $@ but variable is ${variable} all_explained: ${variable} variable = value3 ####################################################################### ## temp_variable -- This shows how to force instantious eveluation ## DESCRIPTION ## This assignment occurs immediately and later changes to variable will have ## no effect. ## NOTES ## CAVEATS AND BUGS temp_variable := ${variable} ####################################################################### ## ${variable}: -- Demonstrate rule with safe body ## DESCRIPTION ## This rule (actually value3:) uses a body whose action will not change ## even if variable gets reassigned. ## NOTES ## This was done by := assigning variable to a temp value ## CAVEATS AND BUGS ${variable}: @echo making $@ but variable is ${temp_variable} all_explained: ${variable} variable = value4 variables: @echo making $@ but variable is ${variable} comments: # this line is not seen # neither is this one # but this line is seen, demonstrating the Makefile Funny Behavior, # because it started with a tab, and the # went to the shell # before being seen as a comment, instead of the makefile # not seeing it as it does not see this line. ####################################################################### ## demo_env: -- Demonstrates getenv error with = assignments ## DESCRIPTION ## Makefiles varuiables become environment variables. Makefiles variables ## assigned with = are pure string replacement (unevaluated). Thus, if ## you assign one varible to another, the second variable gets the ## unexpanded string form of the first variable, $ sign and all. A ## "getenv" will get a values such as ${var} instead of the real value. ## Unless the getenv call is looped, you lose! ## ## Most folks will not see this in casual use because they will reference ## the varibles from a shell line and make expands the variable once ## before passign it to the shell and the shell expands the expansion. ## However, if you are more than two deep, you lose! ## NOTES ## For safety, use := assignments for variables you intend to be used ## from a shell or via getenv. ## CAVEATS AND BUGS demo_env: @echo env 1 is ${ENV1} or $$ENV1 @echo env 2 is ${ENV2} or $$ENV2 @echo env 3 is ${ENV3} or $$ENV3 ENV1=1 ENV2=${ENV1} ENV3:=${ENV1} all_explained: variables comments demo_env -*- End File: /net/src/tools/process/ibuild/src/integration/Makefile_Funnies.mk