问题
I've got a Makefile.mak where I optionally create a test.exe or a DLL from my C-based source code. I'm using CL.EXE and NMAKE.
I'd like to modify my CFLAGS macro like this when the target is TEST.EXE:
CFLAGS = $(CFLAGS) -DMAIN
And, of course, I use this in my C code:
#ifdef MAIN
... int main()... yada yada
#endif
I had tried
!IF $@ == "test.exe"
but it crashed out and doesn't work logically since the $@, target, isn't deterministic in that part of the makefile.
The logical place to define the additional macro is when defining the target but I don't see how to do that without NMAKE interpreting it as DOS command.
test.exe: test.obj
CFLAGS = $(CFLAGS) -DMAIN
$(LINKER) /out:$@ $(LIB) $*.obj $(LIBS)
It'd be easier with gmake, I know. I don't have that option.
回答1:
I will present two solutions: one which does what you request, namely modifying CFLAGS
based on the target, and a second one which may be a better approach.
Suppose you have a file multiply.c
:
#include <stdio.h>
int multiply(int a, int b) {
return a * b;
}
#ifdef MAIN
int main() {
printf("Unit test: multiply(2, 3) = %d\n", multiply(2, 3));
}
#endif
which you would like to add to a static library my_lib.lib
, and also use as a stand-alone unit test.
One standard way of adding -DMAIN
to CFLAGS
is to use NMAKE recursively. The second invocation of NMAKE could use a different makefile or, as as presented here, use the same makefile with a flag to prevent an infinite recursive loop.
TARGETS = my_lib.lib multiply.exe
CFLAGS = -W4 -O2 -nologo -Zi
all: $(TARGETS)
my_lib.lib: multiply.obj
my_lib.lib:
lib -nologo -out:$@ $**
!ifndef RECURSE
multiply.exe:
nmake -nologo CFLAGS="-DMAIN $(CFLAGS)" RECURSE= $@
!endif
multiply.obj: .FORCE
.FORCE:
If RECURSE
is defined, the built-in rule is used to create the test program multiply.exe
.
This solution works. But it requires that multiply.obj
be remade every time it is used, because there are two versions of it floating around: one with a main
and one without.
The second solution distinguishes between these object files.
TARGETS = my_lib.lib multiply.exe
CFLAGS = -W4 -O2 -nologo -Zi
all: $(TARGETS)
my_lib.lib: multiply.obj
multiply.exe: $*.TEST_obj
my_lib.lib:
lib -nologo -out:$@ $**
multiply.exe:
link -nologo -out:$@ $**
.c.TEST_obj:
$(CC) -DMAIN $(CFLAGS) -c $< -Fo$@
This gives:
>nmake -nologo
cl -W4 -O2 -nologo -Zi /c multiply.c
multiply.c
lib -nologo -out:my_lib.lib multiply.obj
cl -DMAIN -W4 -O2 -nologo -Zi -c multiply.c -Fomultiply.TEST_obj
multiply.c
link -nologo -out:multiply.exe multiply.TEST_obj
Trying to create a .exe
file directly from the .c
file, as in:
.c.exe:
$(CC) -DMAIN $(CFLAGS) $<
does not work, because this still creates a .obj
file which clobbers the other version.
Edit: .SUFFIXES: .TEST_obj
does not seem to be needed.
来源:https://stackoverflow.com/questions/57893687/how-do-i-use-a-conditional-in-nmake