From: Larry Lindstrom on
Hi Folks:

As I was fading away in the early hours of the morning, I
accidentally posted this to the UI newsgroup, instead of here.

Developing with VS 2008.

I've used make, on my Unix projects, but I've never gotten more
than Ankle deep in it's exotic features. I just identify the target,
the dependencies, and the commands to execute.

I've never used nmake in one of my projects, but I have built
libtommath using the version that came with VC6.

Now I'd like to re-build libtommath, with VS 2008, but I'm getting
this error.

NMAKE : fatal error U1100: macro '$@' is illegal in the context of batch
rule '.c.obj'

The make file that comes with libtommath looks like this:

---

CFLAGS = /I. /Ox /DWIN32 /W3 /Fo$@

default: library

OBJECTS=bncore.obj bn_mp_init.obj bn_mp_clear.obj bn_mp_exch.obj \
bn_mp_grow.obj bn_mp_shrink.obj bn_mp_clamp.obj bn_mp_zero.obj \
.
. < Many object files >
.
bn_mp_to_signed_bin_n.obj bn_mp_to_unsigned_bin_n.obj

HEADERS=tommath.h tommath_class.h tommath_superclass.h

library: $(OBJECTS)
lib /out:tommath.lib $(OBJECTS)

---

MSDN says this of the $@ macro:

$@ Current target's full name (path, base name, extension),
as currently specified

I've looked at MSDN's nmake documentation, and I don't
understand what it's saying, but I see that the section starting
with "OBJECTS=" is an example of a batch rule.

I'm reasonably certain that I built this with VC6's nmake.

Can someone suggest what needs to be done to make this legal?
Or should I take this back to the crypto group and ask Tom?

Thanks
Larry
From: Michael Wojcik on
[This is rather old, in Usenet terms, but no one's answered it yet, so
hopefully the OP is still reading.]

Larry Lindstrom wrote:
>
> I've used make, on my Unix projects, but I've never gotten more
> than Ankle deep in it's exotic features. I just identify the target,
> the dependencies, and the commands to execute.

In this case you're running up against an exotic feature of nmake, so
knowing Unix make inside and out wouldn't help anyway.

> I've never used nmake in one of my projects, but I have built
> libtommath using the version that came with VC6.
>
> Now I'd like to re-build libtommath, with VS 2008, but I'm getting
> this error.
>
> NMAKE : fatal error U1100: macro '$@' is illegal in the context of batch
> rule '.c.obj'

VS2008 - and earlier versions at least as far back as VS6 - have a
C-to-object inference rule that uses nmake's "batch compile" syntax.
It looks like this:

..c.obj::
$(CC) $(CFLAGS) /c $<

"nmake /p" will show you the body of this rule, but it doesn't show
the double-colon after the ".c.obj", which is what makes the
difference. Well, that's not very smart, is it, Microsoft?

In nmake, the use of a double-colon for an inference rule has a
different function than for regular rules (like eg "all::" or
"clean::", where it simply allows multiple bodies for the same target
- usually a pseudo-target). With an inference rule, it means "create a
temporary batch file that invokes the body once for multiple targets".

*Why* anyone would want to do that, especially by default, on a modern
system is an open question. The negligible performance gain for the
typical build is not worth the loss of information in the make output
and the additional confusion.

Also, as you've just seen, it means you can't use the predefined macro
"$@" in the rule body, because it refers to the result of processing a
single target, and nmake is invoking the rule once for multiple targets.

So one fix is to redefine nmake's default .c.obj inference rule. Just add:

..c.obj:
$(CC) $(CFLAGS) /c $<

to the makefile, and you should be fine.

However, it's worth taking a look at where that pesky $@ is set:

> CFLAGS = /I. /Ox /DWIN32 /W3 /Fo$@

Well. Far be it from me to criticize Tom's makefile (for one thing, if
he hears about it I'll probably get an earful), but half of that is a
big bunch of unnecessary.

"/I." is implicitly set by default, unless there are #include
directives of the <filename> form that refer to headers in the current
directory. If that's the case, they should be fixed, because that
vacates the (dubious) value of the <filename> form of #include. If
it's not the case, "/I." is redundant (and possibly dangerous) and
should go away.

"/DWIN32" shouldn't have been used. C code that needs to detect the
platform should check for the "_WIN32" macro, which is always defined
by the (Microsoft) compiler unless the "/u" option (or "/U _WIN32") is
specified. Looking for "WIN32" without the underscore is just asking
for trouble. The C sources should be fixed to look for _WIN32 instead,
and this option should be removed.

More importantly, for your purposes, "/Fo$@" is pointless. It means
"give the object file the name of the target". Which is what has to
happen anyway, for the makefile to work. It's redundant; its only
function here is to break the makefile, thanks to Microsoft's (also
unnecessary, but at least not irrelevant) batch inference rule.

So my choice would be to take that "/Fo$@" out of CFLAGS. And I'd add
the single-target .c.obj inference rule as well, because I like to see
what the compiler's doing in the make output.


--
Michael Wojcik