我想做一件简单的事情,如果目标名称是“ 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/!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
[正如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/上的示例。)