сделать установку только если файл изменился - PullRequest
2 голосов
/ 24 июля 2010

При написании хорошо созданного Make-файла, который сохраняет надлежащие зависимости и выполняет только необходимый минимум, если файл был изменен, создается впечатление, что цель install: часто игнорируется. Чаще всего цель установки не выглядит примерно так:

TRG := /trg
BIN_TRG := $(TRG)/bin
ETC_TRG := $(TRG)/etc
BIN_FILES := b1 b2 b3
ETC_FILES := e1 e2 e3

install:
    install $(BIN_FILES) $(BIN_TRG)
    install $(ETC_FILES) $(ETC_TRG)

.PHONY: install

То есть, фальшивая цель без каких-либо зависимостей, проверяющая, что когда-либо.

Проблема такого рода становится более серьезной, если вместо простой установки необходимо заполнить промежуточную область для подготовки бинарного пакета, например RPM-пакетов, или если следующий этап сборки зависит от этой промежуточной области. В этом случае дерево зависимостей отверстий ломается после этой стадии установки.

Вопрос: Каков наилучший подход к правилу установки, который отслеживает зависимости?

Ответы [ 3 ]

2 голосов
/ 25 июля 2010

Я не знаком с вашей функцией "установки", и ваши два решения используют ее по-разному, но как насчет этого:

TRG := /trg
BIN_TRG := $(TRG)/bin
ETC_TRG := $(TRG)/etc
BIN_FILES := b1 b2 b3
ETC_FILES := e1 e2 e3
INSTALLS := $(addprefix $(BIN_TRG)/,$(BIN_FILES)) \
        $(addprefix $(ETC_TRG)/,$(ETC_FILES))

install: $(INSTALLS)

$(BIN_TRG)/% $(ETC_TRG)/%: %
    install $< $@

.PHONY: install

РЕДАКТИРОВАТЬ: PS, если хотитеinstall шаг, чтобы заполнить область подготовки или что-то еще, сделать область подготовки отдельной целью со своим собственным правилом.

0 голосов
/ 11 февраля 2012

Поскольку make не поддерживает предварительные требования для фальшивых целей, вам придется создавать на диске настоящий фиктивный файл и прикасаться к нему каждый раз, когда запускается установка target.

.PHONY: install

install: dummy

dummy: $(FILES_THAT_WERE_CHANGED)  
       install $(BIN_FILES) $(BIN_TRG)  
       install $(ETC_FILES) $(ETC_TRG)  
       touch dummy
0 голосов
/ 24 июля 2010

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

trg_dir/my_file: my_file
    install $< $@

Для этого, однако, требуется немного магии gmake:

TRG := /trg
BIN_TRG := $(TRG)/bin
ETC_TRG := $(TRG)/etc
BIN_FILES := b1 b2 b3
ETC_FILES := e1 e2 e3
INSTALLS := $(addprefix $(BIN_TRG)/,$(BIN_FILES)) \
            $(addprefix $(ETC_TRG)/,$(ETC_FILES))

install: $(INSTALLS)

define install_rule
$(1)/$(2): $(2)
    install $(2) $(1)/$(2)
endef

$(foreach file,$(BIN_FILES),$(eval $(call install_rule,$(BIN_DIR),$(file))))
$(foreach file,$(ETC_FILES),$(eval $(call install_rule,$(ETC_DIR),$(file))))

.PHONY: install

Я чувствую, что этот код нуждается в некотором объяснении, это также моя главная проблема с ним - это сложнее, чем такая, казалось бы, обычная задача:

Цель install: остается фальшивой, но теперь она будет использоваться только для проверки актуальности отдельных правил установки.

Правила генерируются с оценкой результата вызова макроопределения отдельного правила. Мы используем функцию $(foreach ...) для итерации по каждому файлу и задаем правильные параметры при $(call ...) install_rule.


Я поставил вопрос и ответ здесь, хотя, похоже, уже решил его, потому что я не доволен этим решением. Любой более элегантный будет с нетерпением принят.

...