It appears to me that empty(), defined() etc. do not work on .for loop variables, at least not on NetBSD 7's make and bmake-20150505. Assigning the loop variable to anothe rintermediate var seems tu cure it.
.for i in aXa bYb .if defined(i) .info DEFINED .else .info UNDEFINED .endif .if empty(i:M*X*) .info ${i}: NO .else .info ${i}: YES .endif j:= ${i} .if empty(j:M*X*) .info ${j}: NO .else .info ${j}: YES .endif .endfor My guess would be that the logic that magically substitutes i with :U<loop value> misses the defined(i) case.