From owner-freebsd-hackers@FreeBSD.ORG Sun Feb 13 11:10:33 2005 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D624016A4CE for ; Sun, 13 Feb 2005 11:10:33 +0000 (GMT) Received: from tigra.ip.net.ua (tigra.ip.net.ua [82.193.96.10]) by mx1.FreeBSD.org (Postfix) with ESMTP id 002BC43D1F for ; Sun, 13 Feb 2005 11:10:32 +0000 (GMT) (envelope-from ru@ip.net.ua) Received: from localhost (rocky.ip.net.ua [82.193.96.2]) by tigra.ip.net.ua (8.12.11/8.12.11) with ESMTP id j1DBAVTp094476; Sun, 13 Feb 2005 13:10:31 +0200 (EET) (envelope-from ru@ip.net.ua) Received: from tigra.ip.net.ua ([82.193.96.10]) by localhost (rocky.ipnet [82.193.96.2]) (amavisd-new, port 10024) with LMTP id 70710-07; Sun, 13 Feb 2005 13:10:30 +0200 (EET) Received: from heffalump.ip.net.ua (heffalump.ip.net.ua [82.193.96.213]) by tigra.ip.net.ua (8.12.11/8.12.11) with ESMTP id j1DBATnM094473 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sun, 13 Feb 2005 13:10:29 +0200 (EET) (envelope-from ru@ip.net.ua) Received: (from ru@localhost) by heffalump.ip.net.ua (8.13.1/8.13.1) id j1DBAX1r089049; Sun, 13 Feb 2005 13:10:33 +0200 (EET) (envelope-from ru) Date: Sun, 13 Feb 2005 13:10:33 +0200 From: Ruslan Ermilov To: Kris Kennaway Message-ID: <20050213111033.GB88954@ip.net.ua> References: <20050213023201.GB24426@xor.obsecurity.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="3uo+9/B/ebqu+fSQ" Content-Disposition: inline In-Reply-To: <20050213023201.GB24426@xor.obsecurity.org> User-Agent: Mutt/1.5.6i X-Virus-Scanned: by amavisd-new at ip.net.ua cc: hackers@freebsd.org Subject: Re: Makefile .for and .if expansion X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 13 Feb 2005 11:10:34 -0000 --3uo+9/B/ebqu+fSQ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi Kris, On Sat, Feb 12, 2005 at 06:32:01PM -0800, Kris Kennaway wrote: > The following small makefile doesn't behave as one would naively > expect: >=20 > MANLANG?=3Dfoo "" > all: > .for i in ${MANLANG} > .if empty(${i}) > @echo foo ${i} > .endif > .endfor >=20 > ports-i386%make > foo foo > foo >=20 > I think this is because the .if evaluation is happening too early, and > it's not being done after the .for loop is expanded and the i variable > is set. >=20 This makefile is broken, you're abusing empty(). empty() expects a variable name (without `$') as an argument, and ``.if empty(foo)'' means "true if ${foo} has an empty value". Note that in 4.x, "foo" also needs to be a defined variable, for this to work at all. In 5.x and 6.x, undefined variables are treated like empty variable by empty(). > In order to get this to work I seem to have to do the following: >=20 > MANLANG?=3Dfoo "" > .for i in ${MANLANG} > j=3D ${i} > .if (${j} !=3D "\"\"") > .for l in ${j} > k+=3D ${l} > .endfor > .endif > .endfor > all: > @echo ${k} >=20 > ports-i386%make > foo >=20 > If I remove the inner .for it breaks, and if I remove the j assignment > it breaks. Also if I try and remove the use of k and put an echo > inside the inner .for (with the all: preceding the whole loop) it > breaks. >=20 > This is extremely nasty. >=20 Yes. This behavior is documented in the BUGS section of the make(1) manpage: .for loops are unrolled before tests, and .for variables aren't real variables, so a fragment like this: =2Efor i in foo bar =2Eif ${i} =3D=3D "foo" echo ${i} =2Eendif =2Eendfor doesn't work. This fragment is rewritten by make(1) before further parsing as follows: =2Eif foo =3D=3D "foo" echo foo =2Eendif =2Eif bar =3D=3D "foo" echo bar =2Eendif And since .if expects a ${variable} as its first argument, it fails. About why you need an inner loop. Remember again that .for loops are unrolled before parsing, it means that a fragment like this: =2Efor i in foo bar j=3D${i} k+=3D${j} =2Eendfor is equivalent to j=3Dfoo k+=3D${j} j=3Dbar k+=3D${j} which means that `k' will get a value of "bar bar". When you use an inner loop, =2Efor i in foo bar j=3D${i} =2Efor l in ${j} k+=3D${l} =2Eendfor =2Eendfor it first gets rewritten to: j=3Dfoo =2Efor l in ${j} k+=3D${l} =2Eendfor j=3Dbar =2Efor l in ${j} k+=3D${l} =2Eendfor then to: j=3Dfoo k+=3Dfoo j=3Dbar k+=3Dbar which DTRT, but also has a side effect of setting "j" to "bar". > Am I missing an easier way to do this? >=20 May I suggest the following instead: %%% MANLANG?=3D foo "" bar all: =2Efor i in ${MANLANG:N""} @echo foo ${i} =2Eendfor %%% Note that `""' is not an empty value in make(1), it's just a regular value consisting of two double quotes. Cheers, --=20 Ruslan Ermilov ru@FreeBSD.org FreeBSD committer --3uo+9/B/ebqu+fSQ Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.6 (FreeBSD) iD8DBQFCDzWpqRfpzJluFF4RAoPjAKCNqVWvNF9dMDhdtHzN6RsIr/xBawCfR/h9 D2aBJUMMRYwLTtWxTN1QPLk= =wLUw -----END PGP SIGNATURE----- --3uo+9/B/ebqu+fSQ--