Странная автоматизация поведения с “делает-f”

Каждая оболочка поступает по-своему расширения подсказки. ksh OpenBSD является pdksh. Посмотрите его быстрые настройки в руководстве, под PS1 параметр.

Путь ksh работы состоит в том, что это выполняет замену параметра, замену команды и арифметическую замену (весь $ расширения) на значении PS1 прежде, чем распечатать подсказку. Таким образом, Вы устанавливаете PS1 раз и навсегда, но значение повторно создано каждый раз. (Можно сделать это в ударе также, если Вы помещаете shopt -s promptvars в Вашем .bashrc.)

ksh OpenBSD поддерживает Escape обратной косой черты, подобные удару. С другими версиями ksh необходимо было бы перевести escape-последовательности подсказки удара в $ замены также.

PS1='$(if (($? == 0)); then print -n "\\033[32m"; else print -n "\\033[31m"; fi)'
PS1="$PS1"'[\u@\h \w]'$(print '\033')'[0m '

Простой перевод выше имеет несколько дефектов:

  • Это разветвляет процесс каждый раз, для анализа $?. Существует способ избежать этого, но это - hackish в ksh88.
  • Это вызывает ошибки перерисовки из-за управляющих последовательностей нулевой ширины. Этого можно избежать с грубым взломом, зарегистрированным в руководство.

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

escape=$(print '\033')
ctrla=$(print '\001')
PS1=$(print '\001\015')
PS1=$PS1$ctrla$escape'[$(($? ? 31 : 32))m'$ctrla
PS1=$PS1'[\u@\h \w]'
PS1=$PS1$ctrla$escape'[0m'$ctrla' '

7
26.05.2014, 01:12
1 ответ

То поведение не является ошибкой. Это - функция. Функция и возможная пользовательская ошибка быть точным.

Рассматриваемой функцией является одно из неявных правил, Делают. В Вашем случае неявное правило "создать" *.sh файлы. Пользовательская ошибка, Ваша ошибка, не изменяет рабочий каталог прежде, чем вызвать make-файл в подкаталогах.


TL; DR: для фиксации этого, можно сделать один или несколько из следующего:

  1. Исправьте сценарий оболочки для изменения рабочего каталога:

    #!/bin/bash
    
    for f in *; do
            if [[ -d $f && -f $f/makefile ]]; then
                    echo "Making clean in $f..."
                    (cd $f; make clean)
            fi
    done
    
  2. Сделайте пустые правила явными:

    clean: ;
    
  3. Сделайте clean фальшивые цели:

    .PHONY: clean
    

Подробное объяснение:

Сделайте имеет набор неявных правил. Это позволяет, для вызова делает на простых проектах, даже не пишущий make-файл.

Попробуйте это за демонстрацию:

  1. создайте пустой каталог и изменение в к каталогу
  2. создайте названный файл clean.sh.
  3. выполненный make clean

Вывод:

$ make clean
cat clean.sh >clean 
chmod a+x clean

BAM! Это - питание implict правил, делают. См. сделать руководство о неявных правилах для получения дополнительной информации.


Я попытаюсь ответить на остающийся нерешенный вопрос:

Почему это не вызывает неявное правило для первого make-файла? Поскольку Вы перезаписали неявное правило со своим явным clean правило.

Почему делает clean правило во втором make-файле не перезаписывает неявное правило? Поскольку это не имело никакого рецепта. Правила без рецепта не перезаписывают неявные правила, вместо этого они просто добавляют предпосылки. См. сделать руководство о нескольких правилах для получения дополнительной информации. См. также сделать руководство о правилах с явными пустыми рецептами.

Почему это - ошибка не изменить рабочий каталог прежде, чем вызвать make-файл в подкаталоге? Поскольку делают, не изменяет рабочий каталог. Составьте работу завещания в наследованном рабочем каталоге. Хорошо технически это - не обязательно ошибка, но большую часть времени это. Вы хотите, чтобы make-файлы в подкаталогах работали в подкаталогах? Или Вы хотите, чтобы они работали в родительском каталоге?

Почему действительно делает, игнорируют явное clean правило от первого make-файла во втором вызове clean.sh? Поскольку теперь конечный файл clean уже существует. Начиная с правила clean не имеет никаких предпосылок нет никакой потребности восстановить цель. См. сделать руководство о фальшивых целях, которое описывает точно эту проблему.

Почему действительно делает поиск цели three/makefile в третьем вызове? Поскольку всегда делают попытки переделать make-файлы прежде, чем сделать что-либо еще. Это особенно верно, если с помощью make-файл явно требуют -f но это не делает существует. См. сделать руководство о переделке make-файлов для получения дополнительной информации.

9
27.01.2020, 20:17
  • 1
    я думаю этот ответ, был бы улучшен путем добавления, которые для каждой соответствующей версии GNU делают (да, другие разновидности существуют и используются), make -npf /dev/null (или gmake в зависимости от системы), может использоваться для дампа базы данных неявных правил для той точной версии. Помог мне часто. –  0xC0000022L 26.05.2014, 00:45

Теги

Похожие вопросы