我有这个文件:
src = $(notdir $(wildcard src/*.cpp))
obj = $(src:.cpp=.o)
libname ?= libtest
importlib_flags = -ldl -lboost_filesystem
parser: $(obj)
g++ -o $@ $^
%.o: src/%.cpp
ifeq ($<,src/$(libname).cpp)
g++ -fpic -c $(libname).cpp -o $(libname).o
g++ -shared -Wl,-soname,$(libname).so.1 -o $(libname).so.1.0.1 $(libname).o -lc
else
g++ -c $< -o $@ $(if $(findstring importlib, $<), $(importlib_flags))
endif
.PHONY: clean
clean:
rm -rf *.o *.so* parser
运行make之后,我得到了:
g++ -c src/libtest.cpp -o libtest.o
g++ -c src/importlib.cpp -o importlib.o -ldl -lboost_filesystem
g++ -c src/token.cpp -o token.o
g++ -c src/main.cpp -o main.o
g++ -o parser libtest.o importlib.o token.o main.o
第一行表示makefile转到else
分支,但它应该转到ifeq
,因为$ <扩展为src/libtest.cpp
,它在扩展后等于src/$(libname).cpp
。我没有通过命令行设置libname
。为什么不起作用?
答案 0 :(得分:0)
IIRC扩展发生在规则实际运行之前,因此$<
可能会扩展为空。即makefile在运行规则之前先分析if / else。
然后,当规则运行时,它已经“预选”了else部分,因为它做出的决定$<
并不是规则期间的内容。
所以您可以做的是使用shell脚本(我假设是bash),诸如此类:
%.o: src/%.cpp
if [[ "$<" == "src/$(libname).cpp" ]] ; then \
g++ -fpic -c $(libname).cpp -o $(libname).o ; \
g++ -shared -Wl,-soname,$(libname).so.1 -o $(libname).so.1.0.1 $(libname).o -lc ; \
else \
g++ -c $< -o $@ $(if $(findstring importlib, $<), $(importlib_flags)) ; \
fi
注意:bash / shell var的写法类似于$${shell_var}
,makefile var的写法是$(make_var)
-以防万一您需要它们!
还请注意,如果要专门使用BASH,请将其添加到makefile的顶部:
SHELL:=/bin/bash