nmake 根据目标修改宏

nmake modify macro based on target

我有一个 Makefile.mak,我可以在其中从基于 C 的源代码中选择创建一个 test.exe 或一个 DLL。我正在使用 CL.EXE 和 NMAKE。

当目标是 TEST.EXE 时,我想像这样修改我的 CFLAGS 宏:

1
CFLAGS = $(CFLAGS) -DMAIN

当然,我在我的 C 代码中使用了这个:

1
2
3
#ifdef MAIN
... int main()... yada yada
#endif

我试过

1
!IF $@ =="test.exe"

但它崩溃了,并且在逻辑上无法正常工作,因为目标 $@ 在 makefile 的那部分中不是确定性的。

定义附加宏的逻辑位置是在定义目标时,但如果没有 NMAKE 将其解释为 DOS 命令,我不知道如何做到这一点。

1
2
3
test.exe: test.obj
  CFLAGS = $(CFLAGS) -DMAIN
  $(LINKER) /out:$@ $(LIB) $*.obj $(LIBS)

我知道,使用 gmake 会更容易。我没有那个选项。


我将介绍两种解决方案:一种满足您的要求,即根据目标修改 CFLAGS,另一种可能是更好的方法。

假设你有一个文件 multiply.c:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int multiply(int a, int b) {
   return a * b;
}

#ifdef MAIN
int main() {
   printf("Unit test: multiply(2, 3) = %d\
", multiply(2, 3));
}
#endif

您想将其添加到静态库 my_lib.lib,并用作独立单元测试。

-DMAIN 添加到CFLAGS 的一种标准方法是递归地使用NMAKE。 NMAKE 的第二次调用可以使用不同的 makefile,或者如此处所示,使用带有标志的相同 makefile 以防止无限递归循环。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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:

如果定义了RECURSE,则使用内置规则创建测试程序multiply.exe

此解决方案有效。但是它要求每次使用 multiply.obj 时都要重新制作它,因为它有两个版本浮动:一个带有 main 和一个没有。

第二种解决方案区分这些目标文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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$@

这给出:

1
2
3
4
5
6
7
>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

尝试直接从 .c 文件创建 .exe 文件,如:

1
2
.c.exe:
    $(CC) -DMAIN $(CFLAGS) $<

不起作用,因为这仍然会创建一个破坏其他版本的 .obj 文件。

编辑:.SUFFIXES: .TEST_obj 似乎不需要。