为什么AWK在makefile中无法正常工作?

Ant*_*iab 13 bash awk makefile sh

注意:转义没有问题,来自shell的示例只是示例,在Makefile $$中.

GNU Makefile的人说为什么它不起作用:

请注意,模式规则中使用'%'的扩展发生在读取makefile之后发生的任何变量或函数扩展之后.

--orig.问题:
在纯shell中,下一个脚本正常工作:

echo "test2.cpp src2/test2.cpp src1/test1.cpp src1/test.cpp" | \
awk 'BEGIN{RS=" "}{if(NR == 1) f=$0; else if(match($0, f)) print $0;}'
Run Code Online (Sandbox Code Playgroud)

过滤器是第一个:test1.cpp
它返回:src1/test1.cpp

但是在Makefile中它无法正常工作(与awk相比错误):

OBJ_DIR:=obj    
SOURCES:=$(wildcard */*.cpp *.cpp)
OBJECTS_LOCAL:= $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:.cpp=.o)))
LOCAL_PATHS_HEADERS:=$(sort $(dir $(wildcard *.h */*.h)))

TARGET:=libcommon.a

all:$(TARGET)

$(TARGET): $(OBJECTS_LOCAL)
        ar -rcs $@ $^

$(OBJECTS_LOCAL): $(OBJ_DIR)/%.o : $(shell echo %.cpp $(SOURCES) | awk 'BEGIN{RS=" "}{if(NR == 1) f=$$0; else if($$0 ~ f) print $$0;}' )
        @mkdir -p $(OBJ_DIR)
        @$(CC) -c $< -o $@ $(addprefix -I,$(LOCAL_PATHS_HEADERS))
Run Code Online (Sandbox Code Playgroud)

所以我在Makefile中使用简单并检查值f,并发现了一些奇怪的f长度

...%.cpp $(SOURCES)  | awk '{print ("file1.cpp" ~ $$1)"."$$1"."length($$1)}' )
Run Code Online (Sandbox Code Playgroud)

awk返回失败比较; print返回"0.file1.cpp.5"以使长度失败,因为它忘记.cpp了%,info below的值.我试图纠正它:

...%.cpp $(SOURCES) | awk 'BEGIN{RS=" "}{if(NR == 1) f=$$0".cpp"; print ("file1.cpp.cpp" ~ f)"."("file1.cpp" ~ f)"."f"."length(f)}' )
Run Code Online (Sandbox Code Playgroud)

但awk返回失败的所有比较; print返回"0.0.file1.cpp.cpp.9".

我在手动模式下检查awk,如下所示:

...%.cpp $(SOURCES) : $(shell echo %.cpp $(SOURCES) | awk '{print "src/"$$1}' )
Run Code Online (Sandbox Code Playgroud)

它工作正常,但它不是变种,因为它会杀死自动模式.

- 添加
有关从参数%到AWK的丢失长度的信息

...%.cppppppp $(SOURCES) | awk '{print ("file1.cpp" ~ $$1)"."$$1"."length($$1)}' )
Run Code Online (Sandbox Code Playgroud)

print返回"0.test2.cppppppp.10"

--Upd,一些问题
上面,我正在打印返回值$<
但是文件重定向显示值%在先决条件中不起作用(文件重定向:"0.%.cpp.5").

我可以在先决条件中使用任何具有值的自动变量吗?

Wil*_*ell 42

几乎无一例外,当在Makefile中询问关于awk的问题时,解决方案是正确地逃避$符号.目前还不完全清楚你的问题是什么,但有一些重大的误解需要解决.特别是,以下"工作",但几乎没有你认为的原因:

echo "test2.cpp src2/test2.cpp src1/test1.cpp src1/test.cpp" | \
awk 'BEGIN{RS=" "}{if(NR == 1) f=$$0; else if(match($$0, f)) print $$0;}'
Run Code Online (Sandbox Code Playgroud)

你几乎肯定不希望$$他们出现在这里的任何情况. awk通常会查找单个美元符号,当它们出现在Makefile中时,它们会加倍,因为Make会解析$$awk使用单个调用$.在引用的示例中,$$0第一个记录相当于$test2.cpp,但变量test2.cpp未初始化,因此值为0,因此在第一次传递时f设置为$ 0的值(字符串"test2.cpp").

简而言之,如果您从shell调用awk,请使用single $.在Makefile中,使用$$和awk只会看到$.