Создать каталог, если целевое имя имеет часть каталога - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть этот код make-файла:

$(DIRS):
    @echo   "   MKDIR   build/tmp/base/socket/$@"
    $(Q)mkdir -p        $@/


%.a.s:
    @echo   "   CC  build/tmp/base/socket/$@"
    $(Q)$(CC) $(CFLAGS_A) -S $< -o $@
%.so.s:
    @echo   "   CC  build/tmp/base/socket/$@"
    $(Q)$(CC) $(CFLAGS_SO) -S $< -o $@
%.o: %.s
    @echo   "   AS  build/tmp/base/socket/$@"
    $(Q)$(AS) $< -o $@


tcp/client.a.s: $(TCP_CLIENT_SRC) $(TCP_CLIENT_INC)
tcp/client.so.s: $(TCP_CLIENT_SRC) $(TCP_CLIENT_INC)

tcp/server.a.s: $(TCP_SERVER_SRC) $(TCP_SERVER_INC)
tcp/server.so.s: $(TCP_SERVER_SRC) $(TCP_SERVER_INC)

Я бы хотел добавить | tcp в предварительные условия для всех целей, у которых в имени есть ведущий tcp/, но я бы хотел чтобы иметь возможность сделать это в одну строку. Я бы не хотел добавлять это вручную к каждой нужной строке.

Я думал добавить новое правило:

tcp/%.s: | tcp

, но оно ничего не делает.

Я также подумал о более обобщенном c, который был бы лучше, но результаты те же:

%.s: | $(@D)

Как мне написать это?


Обходной путь будет каждый раз вызывать mkdir (включать его в правила% .as и% .so.s), но это добавит ненужные вызовы в mkdir, не так ли?

Ответы [ 3 ]

1 голос
/ 27 февраля 2020

Я не фанат шаблонных правил. Они слишком произвольны для моих вкусов. (То, что на самом деле происходит, зависит от того, какие файлы могут храниться на вашем жестком диске.)

Вы не можете просто добавить предварительное условие к данному набору целей, используя правило шаблона

Ну, вы можете, если вы используете stati c шаблон правил . Это гораздо приятнее идиома. Здесь мы добавляем префикс шаблона к фактическому списку источников, к которым вы хотите применить правило шаблона. Это хорошо, когда вы можете описать зависимости, используя make 's совпадение шаблонов.

Эскиз:

%.a: ; date >$@ # Pattern rule

tcp: ; mkdir -p $@ # Explicit rule

tcp/a.a: tcp/%.a: | tcp ; # Static pattern rule!

.PHONY: all
all: tcp/a.a
all: c.a
all: dir/b.a
all: ; : $@ Success

И у нас есть:

$ make all
mkdir -p tcp
date >tcp/a.a
date >c.a
date >dir/b.a
/bin/sh: dir/b.a: No such file or directory
make: *** [Makefile:3: dir/b.a] Error 1

Здесь мы сказали make , что перед сборкой (т. Е. "Запускает рецепт для") tcp/a.a, он должен сначала собрать tcp. Это работает. Мы не сказали make о каталоге для dir/b.a, так что это не удалось. Обратите внимание, что рецепт файла .a все еще находится в обычном шаблонном правиле. Это просто в виде экспозиции. Я определенно изменил бы это.

Да, в этом случае правило шаблона для tcp/ является чрезмерным. Однако учтите, что перед созданием tcp/a.a может потребоваться сначала создать auto/a.src (скажем).

tcp/a.a: tcp/%.a: auto/%.src | tcp ; # Static pattern rule!

Легко расширяемый.

targets := tcp/a.a tcp/b.a tcp/c.a
${targets}: tcp/%.a: auto/%.src | tcp ; # Static pattern rule!

[Кстати, в исходном make-файле ваш архив и общий объект должны зависеть от файлов .o, а не от источника (???)]

1 голос
/ 25 февраля 2020

Вы не можете просто добавить предварительное условие к данному набору целей, используя шаблонное правило. Это не то, как работают шаблонные правила: они правила : с ними должен быть связан рецепт. Правило шаблона без рецепта фактически удаляет это правило шаблона (см. Отмена неявных правил ).

Вы можете создать два набора правил шаблона, по одному для всех целей. и второй - только для целей, которые начинаются с tcp/, у которых есть дополнительная предварительная предпосылка, но вы должны написать полное правило шаблона дважды, включая рецепт, а не только линию шаблона.

Или просто поместите mkdir в рецепт. mkdir в каталоге, который уже существует, даже не будет заметен.

0 голосов
/ 27 февраля 2020

Этот ответ только для того, чтобы показать работающий Makefile, реализующий ответ @ bobbo go.

Этот Makefile является листом дерева Makefile, поэтому все переменные, не определенные здесь, экспортируются верхними Makefile.

Makefile:

#! /usr/bin/make -f

################################################################################
# *AUTHOR*
# FULL NAME     "Alejandro Colomar Andrés"
################################################################################

################################################################################

DIRS    =                               \
        $(CURDIR)/tcp

OBJ     =                                                               \
        $(CURDIR)/tcp/client.o                                          \
        $(CURDIR)/tcp/server.o                                        \
        $(CURDIR)/foo.o

SRC     =                                                               \
        $(SRC_DIR)/base/socket/tcp/client.c                             \
        $(SRC_DIR)/base/socket/tcp/server.c                             \
        $(SRC_DIR)/base/socket/foo.c

DEP             = $(OBJ:.o=.d)
BOTH_OBJ        = $(subst .a.o,.a.o ,$(join $(OBJ:.o=.a.o),$(OBJ:.o=.so.o)))
BOTH_ASM        = $(subst .a.s,.a.s ,$(join $(OBJ:.o=.a.s),$(OBJ:.o=.so.s)))
NEEDDIR         = $(DEP) $(BOTH_ASM)

################################################################################

PHONY := all
all: $(BOTH_OBJ)
        @:

$(DIRS): $(CURDIR)/%:
    @echo   "   MKDIR   build/tmp/base/socket/$*"
    $(Q)mkdir -p        $@

$(NEEDDIR): | $(DIRS)

$(CURDIR)/%.d: $(SRC_DIR)/base/socket/%.c
        @echo   "       CC -M   build/tmp/base/socket/$*.d"
        $(Q)$(CC) $(CFLAGS_A) -MG -MT"$@"                               \
                        -MT"$(CURDIR)/$*.a.s" -MT"$(CURDIR)/$*.so.s"    \
                        -M $< -MF $@
$(CURDIR)/%.a.s: $(SRC_DIR)/base/socket/%.c $(CURDIR)/%.d
        @echo   "       CC      build/tmp/base/socket/$*.a.s"
        $(Q)$(CC) $(CFLAGS_A) -S $< -o $@
$(CURDIR)/%.so.s: $(SRC_DIR)/base/socket/%.c $(CURDIR)/%.d
        @echo   "       CC      build/tmp/base/socket/$*.so.s"
        $(Q)$(CC) $(CFLAGS_SO) -S $< -o $@
$(CURDIR)/%.o: $(CURDIR)/%.s
        @echo   "       AS      build/tmp/base/socket/$*.o"
        $(Q)$(AS) $< -o $@

include $(DEP)


PHONY += clean
clean:
        $(Q)rm -rf *.o *.s *.d
################################################################################
# Declare the contents of the PHONY variable as phony.
.PHONY: $(PHONY)


################################################################################
######## End of file ###########################################################
################################################################################

вывод:

    MKDIR   build/tmp/base/socket/tcp
    CC -M   build/tmp/base/socket/foo.d
    CC -M   build/tmp/base/socket/tcp/server.d
    CC -M   build/tmp/base/socket/tcp/client.d
    CC  build/tmp/base/socket/tcp/client.a.s
    AS  build/tmp/base/socket/tcp/client.a.o
    CC  build/tmp/base/socket/tcp/client.so.s
    AS  build/tmp/base/socket/tcp/client.so.o
    CC  build/tmp/base/socket/tcp/server.a.s
    AS  build/tmp/base/socket/tcp/server.a.o
    CC  build/tmp/base/socket/tcp/server.so.s
    AS  build/tmp/base/socket/tcp/server.so.o
    CC  build/tmp/base/socket/foo.a.s
    AS  build/tmp/base/socket/foo.a.o
    CC  build/tmp/base/socket/foo.so.s
    AS  build/tmp/base/socket/foo.so.o

...