nmake 警告 U4006:特殊宏未定义:'$@"'
Posted
技术标签:
【中文标题】nmake 警告 U4006:特殊宏未定义:\'$@"\'【英文标题】:nmake warning U4006: special macro undefined : '$@"'nmake 警告 U4006:特殊宏未定义:'$@"' 【发布时间】:2019-12-09 23:07:32 【问题描述】:我想做一个简单的事情,如果目标名称是“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 个不同的目标【问题讨论】:
以下两个答案似乎都没有回答您的问题。或许您可以详细说明它们为何不足? 【参考方案1】:!if/!then
的内容是在读取 makefile 时完成的,而不是在调用目标时完成的。您正在尝试在 C 中的预处理器条件语句中使用变量。
以任何方式创建您的if/then
,使您的makefile 在其中执行文件。我不是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
【讨论】:
这当然需要你有一个 UNIX shell 并让nmake
来调用它而不是标准的 Windows 命令 shell...
是的;这就是我在回答中所说的。希望 OP 至少现在了解问题的根源并可以根据需要进行调整。【参考方案2】:
正如 Carl Norum 在他们的 answer 中指出的那样(也可以在 How do I use a conditional in nmake 中查看我的评论),!IF
在 makefile 被解析时使用,而 $@
只有意思是当makefile在被解析之后运行。
一种解决方案是以下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/ 的示例。)
【讨论】:
编辑:对于touch
,另见devblogs.microsoft.com/oldnewthing/?p=3843。以上是关于nmake 警告 U4006:特殊宏未定义:'$@"'的主要内容,如果未能解决你的问题,请参考以下文章