nmake警告U4006:未定义特殊宏:'$ @“'

问题描述 投票:1回答:2

我想做一件简单的事情,如果目标名称是“ enclose_io_memfs.obj”-使用clang进行构建,如果它的另一个目标-使用通用cl进行构建。所以我在Makefile中有下一个代码:

.c.obj:
    $(ECHO) target $@
    $(ECHO) target $(@)
!if "$@" == "enclose_io_memfs.obj"
    clang-cl -c enclose_io_memfs.c
    $(ECHO) clang used
!else
    cl -nologo -c enclose_io_memfs.c
    $(ECHO) cl used
!endif

但是输出是:

./win32/Makefile.sub(1162) : warning U4006: special macro undefined : '$@"'
target enclose_io_memfs.obj
target enclose_io_memfs.obj
        cl -nologo -c enclose_io_memfs.c
enclose_io_memfs.c
cl used
compiling repu1sion_02 enclose_io_memfs.c

几个问题:

  • 为什么$ @在上一行可用而在if语句中不可用?
  • 还有其他检测所需目标的方法吗?因为.c.obj调用时有30个不同的目标]
windows makefile clang nmake cl
2个回答
2
投票

!if/!then的工作是在读取makefile时完成的,而不是在调用目标时完成的。您正在尝试等效于在C中的预处理器条件语句中使用变量。

用您的makefile在其中执行文件的shell环境以任何方式使if/then。我不是nmake / dos shell专家,但对于bash来说,它类似于:

.c.obj:
    $(ECHO) target $@
    if [[ "$@" == "enclose_io_memfs.obj" ]] ;\
    then                                     \
        clang-cl -c $(@:.obj=.c)            ;\
        $(ECHO) clang used                  ;\
    else                                     \
        cl -nologo -c $(@:.obj=.c)          ;\
        $(ECHO) cl used                     ;\
    fi

0
投票

[正如Carl Norum在其answer中指出的(也请参见How do I use a conditional in nmake中的注释),当makefile为parsed时使用!IF,而仅当makefile时$@才有意义运行after被解析。

一个解决方案是以下makefile:

all: foo.obj bar.obj

.c.obj:
    @cmd /c if $(@B)==foo (                         \
    echo clang will be used to create $@ from $**   \
    ) else (                                        \
    echo cl will be used create $@ from $**         \
    )

给出:

clang will be used to create foo.obj from foo.c
cl will be used create bar.obj from bar.c

更新:更好的,更可扩展的解决方案是以下makefile:

CLANG_SOURCES = foo1.c foo2.c
CL_SOURCES    = bar1.c bar2.c

CLANG_OBJECTS = $(CLANG_SOURCES:.c=.obj)
CL_OBJECTS    = $(CL_SOURCES:.c=.obj)

all: $(CLANG_OBJECTS) $(CL_OBJECTS)

$(CLANG_OBJECTS):
    @echo using clang to create $@ from $?

$(CL_OBJECTS):
    @echo using cl to create $@ from $?

然后,nmake -nologo将给出(假设*.c文件存在):

using clang to create foo1.obj from foo1.c
using clang to create foo2.obj from foo2.c
using cl to create bar1.obj from bar1.c
using cl to create bar2.obj from bar2.c

更新2:一个完整的工作示例。生成文件:

CLANG_SOURCES = foo1.c foo2.c
CL_SOURCES    = bar1.c bar2.c

CLANG_OBJECTS = $(CLANG_SOURCES:.c=.obj)
CL_OBJECTS    = $(CL_SOURCES:.c=.obj)
OBJECTS       = $(CLANG_OBJECTS) $(CL_OBJECTS)

CFLAGS        = -nologo
CLANG_CL      = C:\Progra~2\LLVM32\bin\clang-cl

all: $(OBJECTS)

$(OBJECTS): some_header.h

$(CLANG_OBJECTS):
    $(CLANG_CL) $(CFLAGS) -c $*.c

clean:
    del $(OBJECTS) 2>NUL

给予,nmake -nologo

        C:\Progra~2\LLVM32\bin\clang-cl -nologo -c foo1.c
        C:\Progra~2\LLVM32\bin\clang-cl -nologo -c foo2.c
        cl -nologo /c bar1.c bar2.c
bar1.c
bar2.c
Generating Code...

为方便起见,我们使用nmake的预定义推理规则来生成$(CL_OBJECTS)

[注意nmake在这里不允许$<,并且some_header.h会导致$?$**出现问题。我以前的建议与此有关。

也请注意,尽管在上面并不明显,但是nmake保留了目标文件对相应源文件的隐式依赖性,即使添加了clang规则也是如此。例如:

C:\Users\Joe>nmake -nologo

C:\Users\Joe>copy /b foo1.c +,,
        1 file(s) copied.

C:\Users\Joe>nmake -nologo
        C:\Progra~2\LLVM32\bin\clang-cl -nologo -c foo1.c

C:\Users\Joe>copy /b bar1.c +,,
        1 file(s) copied.

C:\Users\Joe>nmake -nologo
        cl -nologo /c bar1.c
bar1.c

((copy命令在此处用作“触摸”:请参见https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/copy/上的示例。)

© www.soinside.com 2019 - 2024. All rights reserved.