nmake modify macro based on target

坚强是说给别人听的谎言 提交于 2021-01-29 04:42:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!