Что делает выражение sed в Makefile? - PullRequest
0 голосов
/ 21 мая 2019

У меня есть Makefile из более старого проекта, который я должен изменить для новой системы. Он имеет следующие глобальные определения для своих исходных и объектных файлов:

SRCFILES = $(wildcard *.c) $(wildcard tasks/*.c) 
SRCDIR = .
OBJDIR = objdir
OBJFILES = $(SRCFILES:%.c=${OBJDIR}/%.o)

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * '' '' '- был беспорядок, и мне пришлось его сильно изменить Мне удалось скомпилировать код и сгенерировать файлы .o из исходного кода .c. Ожидаемый .elf файл также скомпилирован правильно.

проблема в том, что я не могу понять, что делает код в следующих строках. Я искал так много сайтов, но не повезло. есть идеи?

 sed 's,^\(.*\)\.o[ :]*,$(@D)/\1.o $(@D)/\1.d : ,g' < $@.$$$$ > $@; \
 rm -f $@.$$$$

makefile выглядит следующим образом

lwip.elf: build_echo $(OBJFILES)
 @set -e; echo Linking the object files...; \
 sparc-elf-gcc $(OBJFILES) -o $@;
 @echo Successfully linked the files
 @echo lwip.elf file ready to load...

build_echo: httpserver_raw/fsdata.c
 @echo Building the source files first...
 @echo The Modified or New source code to be build are :

clean:
 - rm -f lwip.elf 

$(OBJDIR)/%.o: $(SRCDIR)/%.c
 @set -e; echo '    $<'; \
 sparc-elf-gcc-4.4.2 -Wall -O2 -g -msoft-float -mcpu=v8 -c -o $@ $(CFLAGS) -I. -I lwip/include -I lwip/include/ipv4 -I lwip/leon3 $<

$(OBJDIR)/%.d: $(SRCDIR)/%.c
 @set -e; rm -f $@; mkdir -p $(@D); \
 sparc-elf-gcc -MM -I. -I lwip/include -I lwip/include/ipv4 -I lwip/leon3 $< > $@.$$$$; \
 sed 's,^\(.*\)\.o[ :]*,$(@D)/\1.o $(@D)/\1.d : ,g' < $@.$$$$ > $@; \
 rm -f $@.$$$$

-include $(patsubst %.c,$(OBJDIR)/%.d,$(SRCFILES))

Примечание: sparc-elf-gcc - это специальный кросс-компилятор, используемый для архитектуры sparcV8.

1 Ответ

0 голосов
/ 21 мая 2019

Там много чего происходит:

sed 's,^\(.*\)\.o[ :]*,$(@D)/\1.o $(@D)/\1.d : ,g' < $@.$$$$ > $@; \
 rm -f $@.$$$$

Давайте разберемся с этим.

  1. Сама команда sed: sed 's,^\(.*\)\.o[ :]*,$(@D)/\1.o $(@D)/\1.d : ,g',
  2. , чей ввод перенаправляется (<) из файла, обозначенного @.$$$$, и
  3. , чей вывод перенаправляется (>) в файл, обозначенный $@, затем
  4. есть секунда команда, rm -f $@.$$$$.

Кроме того, это в контексте большого списка команд, который устанавливает его с помощью

@set -e; rm -f $@; mkdir -p $(@D); \
 sparc-elf-gcc -MM -I. -I lwip/include -I lwip/include/ipv4 -I lwip/leon3 $< > $@.$$$$;

При интерпретации этого вы должны сначала распознать несколько make неявных переменных:

  • $@, представляющий название цели правила
  • $(@D), представляющий каталог с целевым именем (, т.е. * у цели dirname)
  • $<, что представляет собой первое условие

Далее вам нужно признать, что знак доллара имеет особое значение для make, поэтому, если вы хотите, чтобы литерал $, вам нужно удвоить его. $$$$ просто повторяют это, так что то, что передается оболочке, это всего два знака доллара ($$). Оболочка, в свою очередь, заменяет его собственным идентификатором процесса - относительно распространенной (но тем не менее небезопасной) идиомой для генерации уникальных имен файлов.

Таким образом, часть команды, которую вы пропустили в вызове, гарантирует, что целевой каталог существует, а затем запускает (cross-?) Gcc с флагами, которые заставляют его выдавать информацию о зависимостях заголовка. Они записываются в файл, что-то вроде objdir/src.d.12345, затем в части, которую вы вызвали, этот файл перенаправляется в sed, с выводом, идущим к конечной цели, что-то вроде objdir/src.d, после чего промежуточный файл удаляется.

Команда sed сама выполняет подстановку (s) во всех строках, заменяя каждое вхождение (g) шаблона ^\(.*\)\.o[ :]* заменой, к которой я сейчас вернусь. Сначала шаблон. ^ привязывает шаблон к началу строки. \(\) - это метасимволы, ограничивающие группу захвата, а .* внутри соответствует любому количеству любых символов. После этого должны быть буквальная десятичная точка, \., o и ноль или более вхождений или символы пробела и двоеточия ([ :]*). Например, это будет соответствовать этому, но не включая имя заголовка:

objdir/tasks/t1.o : my_header.h

При замене используется вышеупомянутый $(@D) - который расширяется на make, а не на оболочку или sed - и \1, который sed расширяется до соответствующего текста первой группой захвата. Таким образом, это преобразовало бы приведенную выше примерную строку в следующее:

objdir/tasks/t1.o objdir/tasks/t1.d : my_header.h

Короче говоря, все это говорит о том, что он создает вычисленный список зависимостей, чтобы сделать файл зависимостей, который является целью самого списка правил, как зависящий от всех тех же файлов, что и соответствующий объектный файл.

...