Почему AWK не работает правильно в make файле?
ВНИМАНИЕ: Экранирование не проблема, выборка из оболочки - это только пример, в Makefile $$.
GNU Makefile man говорит, почему он не работает:
Обратите внимание, что расширение с использованием ‘% в шаблонных правилах происходит после любого расширения переменных или функций, которые происходят, когда make файл читать.
--Orig. Вопрос:
В чистой оболочке следующий скрипт работает правильно:
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;}'
Фильтр первый: 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 [email protected] $^
$(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 [email protected] $(addprefix -I,$(LOCAL_PATHS_HEADERS))
Итак, я взял простой в Makefile, проверил значение f и нашел странную длину f
...%.cpp $(SOURCES) | awk '{print ("file1.cpp" ~ $$1)"."$$1"."length($$1)}' )
awk возврат не выполнен по сравнению;
print возвращает "0.file1.cpp.5" с ошибкой длины, потому что она забыла .cpp
значение%, информация ниже. Я попытался исправить это:
...%.cpp $(SOURCES) | awk 'BEGIN{RS=" "}{if(NR == 1) f=$$0".cpp"; print ("file1.cpp.cpp" ~ f)"."("file1.cpp" ~ f)"."f"."length(f)}' )
но возвращение awk во всех сравнивается; print возвращает "0.0.file1.cpp.cpp.9".
Я проверяю awk в ручном режиме, например:
...%.cpp $(SOURCES) : $(shell echo %.cpp $(SOURCES) | awk '{print "src/"$$1}' )
Это работает нормально, но это не вариант, потому что это убьет автоматический режим.
--Add
Информация о потерянной длине от параметра% до AWK
...%.cppppppp $(SOURCES) | awk '{print ("file1.cpp" ~ $$1)"."$$1"."length($$1)}' )
print возвращает "0.test2.cppppppp.10"
--Upd, какая-то проблема
Выше я печатал возвращаемое значение из $<
Но перенаправление файлов показывает, что значение% не работает в предварительных условиях (перенаправление файлов: "0.%. Cpp.5").
Могу ли я использовать любую автоматическую переменную со значением в предварительных условиях?
Ответы
Ответ 1
Почти всегда, когда задан вопрос об awk в Makefile, решение состоит в том, чтобы правильно избежать символов $
. Не совсем понятно, каков ваш вопрос, но есть некоторые существенные недоразумения, которые необходимо решить. В частности, следующие "работы", но вряд ли по причинам, которые вы думаете:
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;}'
Вы почти наверняка не хотите $$
в любом из случаев, когда они появляются здесь. awk
обычно ищет значки с одним долларом, и когда они появляются в Makefile, они удваиваются, потому что Make анализирует $$
и вызывает awk
с одним $
. В приведенном примере образец $$0
в первой записи эквивалентен $test2.cpp
, но переменная test2.cpp
не инициализирована и поэтому имеет значение 0, поэтому на первом проходе f устанавливается значение $ 0 (строка " test2.cpp ").
Короче говоря, если вы вызываете awk из оболочки, используйте одиночный $
. В Makefile используйте $$
и awk увидит только $
.