#bash #makefile #gnu-make
#bash #makefile #gnu-make
Вопрос:
Я хочу проверить, содержит ли строковая переменная указанную подстроку в Makefile. Цель состоит в том, чтобы очистить вложенные папки. Я использовал приведенный ниже код, но он не сработал.
SERVICES_LIST = A_Service B_Service C_Service #example
SPECIFIC_SERVICE_LIST = A_Service B_Service
clean:
@list='$(SERVICES_LIST)';for subdir in $$list;do
echo "clean in $$subdir";
if [[ "*$$subdir*" == "$(SPECIFIC_SERVICE_LIST)" ]];then
make $$subdir clean;
fi;
done;
Комментарии:
1. Пожалуйста, отформатируйте свой вопрос, используя функции форматирования SO, чтобы его было легче читать. Кроме того, задавая вопросы, пожалуйста, не говорите что-то вроде «это не сработало»; это никому не поможет понять ситуацию. Вместо этого покажите введенную вами команду и полученный результат (или, если вывода много, по крайней мере, все сообщения об ошибках, а не только последние строки!! На самом деле ПЕРВЫЕ сообщения об ошибках почти всегда важнее последних, хотя лучше включать все ошибки, если их не слишком много).
2. Измените порядок проверки на равенство и поместите звездочки вне кавычек:
if [[ "$(SPECIFIC_SERVICE_LIST)" == *"$$subdir"* ]]
3. В любом случае, @Beta
==
выполняет сравнение строк, а не сравнение соответствия шаблону.4. @JohnBollinger: И в этом случае это работает.
Ответ №1:
Это не имеет большого отношения к make
, потому что практически вся задействованная логика выражена на языке оболочки. В частности, вы, похоже, предполагаете bash
.
Проблема здесь:
if [[ "*$$subdir*" == "$(SPECIFIC_SERVICE_LIST)" ]];then
Похоже, вы пытаетесь сопоставить ( make
расширение) "$(SPECIFIC_SERVICE_LIST)"
с шаблоном глобуса, сформированным как ( make
расширение) "*$$subdir*"
. Но левая часть заключена в кавычки, поэтому она не интерпретируется как шаблон, и ==
оператор выполняет (точное) сопоставление строк, а не сопоставление с образцом.
Один из основных способов применения таких тестов сопоставления с образцом на языке оболочки case
— это использовать конструкцию, поскольку выражения выбора, используемые с ней, всегда интерпретируются как глобусы. Это может выглядеть так в вашем makefile:
case "$(SPECIFIC_SERVICE_LIST)" in *$$subdir*) make $$subdir clean ;; esac
Но все это кажется довольно неидиоматичным. Вообще говоря, makefile настроен на проект. Даже если она генерируется динамически частично или полностью, разумно и целесообразно спроектировать вашу систему сборки так, чтобы чистая цель могла делать что-то более похожее на это:
clean:
for subdir in $(SPECIFIC_SERVICE_LIST); do make -C $$subdir clean; done
… или, может быть, так:
clean: clean_services
...
clean_services:
for subdir in $(SPECIFIC_SERVICE_LIST); do make -C $$subdir clean; done
Комментарии:
1. Я меняю на if [[ «$(SPECIFIC_SERVICE_LIST)» == *»$$subdir»* ]], но, похоже, как вы сказали, это не совпадение с шаблоном, просто сравнение строк. Просто для подтверждения, нет ли способа использовать if для сопоставления строки шаблона в части команды Make? Спасибо!
Ответ №2:
Я бы сделал это более make
простым путем, определив цель для очистки любой поддерживаемой службы, а затем вызвал все необходимые чистые цели в качестве предварительного условия clean
. Это имеет дополнительное преимущество для параллельной очистки при запуске с -j
опцией, в отличие от строго последовательного цикла оболочки.
$ cat Makefile
SERVICES_LIST = A_Service B_Service C_Service #example
SPECIFIC_SERVICE_LIST = A_Service B_Service
.PHONY: $(addsuffix -clean, $(SERVICES_LIST))
$(addsuffix -clean, $(SERVICES_LIST)): %-clean:
$(MAKE) -C $* clean
.PHONY: clean
clean: $(addsuffix -clean, $(SPECIFIC_SERVICE_LIST))