help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Function not returning result


From: Philip Guenther
Subject: Re: Function not returning result
Date: Thu, 28 Jul 2016 08:55:17 -0700

On Thu, Jul 28, 2016 at 3:44 AM, Lee Shallis <address@hidden> wrote:
> This is my function as it is
>
>> define STAT_MODIFIED
>> $(eval $(info $($(0)_SYS)-$(0),$(1)))

The expansion of $(info ...) is the empty string, so the $(eval) is
doing nothing there expect make this harder to read and understand.
Ditto for the other $(eval $(info ...)) uses, of course.


>> $(eval $(0)_SH=$(call $($(0)_SYS)_$(0),$(1)))
>> $(eval $(info $(0)_SH=$($(0)_SH)))
>> $(eval $(0)_FAIL=0)
>> $(eval $(info $(0)_FAIL=$($(0)_FAIL)))
>> $(eval $(0)_VAL=$(if $(wildcard $(1)),SH,FAIL))
>> $(eval $(info $(0)_VAL=$($(0)_VAL)))
>> $(eval $(0)_RESULT=$(call $($(0)_SYS)_$(0)_STRIP,$(shell
>> $($(0)_$($(0)_VAL)))))
>> $(eval $(info $(0)_RESULT=$($(0)_RESULT)))
>> $($(0)_RESULT)
>> endef
>>
> I thought it would return the correct result via the $($(0)_RESULT)
> statement at the bottom but for some reason when I try this:
>
>> $(eval $(0)_LASTMOD=$(call STAT_MODIFIED,$($(0)_SRC)))

The expansion of $(call STAT_MODIFIED, ...) includes the newlines at
the end of each line.  For example, consider this simpler version:

----
define foo
$(eval bar=1)
$(info bar = ${bar})
bar=${bar}
endef

$(info >>$(call foo, 1)<<)
baz = $(call foo, 1)
$(info >>baz = ${baz}<<)

$(eval quux = $(call foo, 1))
$(info >>quux = ${quux}<<)

all:
        @:
----

$ gmake
bar = 1
>>

bar=1<<
bar = 1
>>baz =

bar=1<<
bar = 1
>>quux = <<
$

See how the ${baz} value contains newlines?  For the "$(eval quux =
$(call foo, 1))" assignment, those newlines would be treated as
makefile line separators and make parses this:
---
quux=

bar=1
---
That sure looks like an assignment of the empty string to quux,
followed by assigning 1 to bar.  Make sense?


When building these complicated $(eval) setups you almost always see
evaluation happening *too often*, or *too soon*.  Remember: when using
$(eval) the argument has variable expansion happen *twice*, once when
make it figuring out what was passed to $(eval) and once when $(eval)
reparses the value as makefile content.

In my experience, you often don't need or want the first expansion, so
you should suppress it by doubling the dollar-signs in the argument to
$(eval).  That would solve the problem here by delaying the $(call)
processing where the newlines come from until the second expansion in
$(eval).  For example, if we change the quux assignment to "$(eval
quux=$$(call foo,1))" then the problem goes away and quux contains the
newlines:
...
$(eval quux = $$(call foo, 1))
$(info >>quux = ${quux}<<)
...
>>quux =

bar=1<<


Oh, you don't want the newlines in the expansion of that $(call)?
Then you need to strip them out, such as by wrapping all the leading
lines in a $(strip) whose closing paren is at the start of the last
line.

So that fixes the "too soon" and "newlines" points; that leaves the
"too often" concern.  I won't go into the details, but I strongly
suspect you should write that macro with the expansions inside the
$(eval)s suppressed except for $0 and $1, ala:

define STAT_MODIFIED
$(strip
$(info $($(0)_SYS)-$(0),$(1))
$(eval $(0)_SH=$$(call $$($(0)_SYS)_$(0),$(1)))
$(info $(0)_SH=$($(0)_SH))
$(eval $(0)_FAIL=0)
$(info $(0)_FAIL=$($(0)_FAIL))
$(eval $(0)_VAL=$$(if $$(wildcard $(1)),SH,FAIL))
$(info $(0)_VAL=$$($(0)_VAL))
$(eval $(0)_RESULT=$$(call $$($(0)_SYS)_$(0)_STRIP,$$(shell
$$($(0)_$$($(0)_VAL)))))
$(info $(0)_RESULT=$$($(0)_RESULT))
)$($(0)_RESULT)
endef


Just Say No To Multiple Expansions!


Philip Guenther



reply via email to

[Prev in Thread] Current Thread [Next in Thread]