GNU Make и Windows Powershell: «Remove-Item -ErrorAction Ignore» не работает - PullRequest
1 голос
/ 01 апреля 2019

Я конвертирую Makefile (работающий в linux bash), чтобы запустить его в консоли Windows PowerShell.Я использую GNU Make 4.2.1.У меня проблема с преобразованием команды rm bash в эквивалент PowerShell
Например, в этом простом make-файле

clean: powershell " Remove-Item -ErrorAction Ignore aaa.txt" powershell " Remove-Item -ErrorAction Ignore bbb.txt"

, если aaa.txt не существует,ошибка возникает даже с флагом ErrorAction Ignore и, очевидно, второе действие (удаление bbb.txt) не выполняется.Следующее сообщение печатается make: *** [makefile: 2: clean] Ошибка 1 .

Почему это не работает? (я читал, что Ignore не добавляет сообщение об ошибке в автоматическую переменную $ Error)

Какиепараметр, который я должен использовать в команде Remove-Item?

Для информации, если я запусту следующий файл mybat.bat , он отлично работает, даже еслиесли файл aaa.txt не существует, файл bbb.txt удаляется.

powershell " Remove-Item -ErrorAction Ignore aaa.txt"
powershell " Remove-Item -ErrorAction Ignore bbb.txt"

Rq: powershell " Remove-Item -ErrorAction Ignore aaa.txt, bbb.txt" работает в этом простом случае, но это не хорошее решение, потому что я использую makefile, который вызывает многоmakefile в разных каталогах.

Ответы [ 2 ]

3 голосов
/ 02 апреля 2019

Полезный ответ MadScientist предоставляет полезную справочную информацию и практический обходной путь, внешний для PowerShell.

Что касается , почему PowerShell сообщил код выхода 1:

  • При использовании интерфейса командной строки с (подразумеваемым) параметром -Command именно статус успешного выполнения (последнего) оператора, как отражено в булевой автоматической переменной $?, сопоставляется с кодами выхода 0 ($true) и 1 ($false).

  • Намеренно тихий сбой Remove-Item -ErrorAction Ignore aaa.txt неожиданно отражается в $? как $false, тем не менее, в результате получается код выхода 1.

Обходной путь (если проблему необходимо решить из PowerShell):

В простейшем случае добавьте ; $null (экранированный как ; $null для использования в Makefile):

clean:
    powershell "Remove-Item -ErrorAction Ignore aaa.txt; $$null"
    powershell "Remove-Item -ErrorAction Ignore bbb.txt; $$null"

Вывод $null через CLI - тихий, успешный no-op, который сбрасывает код выхода на 0.

Другой вариант - заключить команду в скобки:

clean:
    powershell "(Remove-Item -ErrorAction Ignore aaa.txt)"
    powershell "(Remove-Item -ErrorAction Ignore bbb.txt)"

(...) превращает команду в выражение, и это выражение считается успешным само по себе, даже если вложенная команда сообщает о (не прекращающейся) ошибке, которая сбрасывает $? в $true и поэтому приводит к выходу код 0.
Обратите внимание, что это поведение тоже удивительно, как обсуждалось в этой проблеме GitHub .

2 голосов
/ 01 апреля 2019

Я ничего не знаю о PowerShell, но make не заботится о том, какой текст печатается вызываемыми командами. Это только заботится о коде выхода.

Исходя из вашего опыта, кажется, что PowerShell Remove-Item по-прежнему завершается с кодом выхода, отличным от 0 (сбой), если файл не существует, а действие Ignore просто говорит ему не печатать ошибку.

Обратите внимание, что ваш пакетный файл не тот, что делает make. Это делает что-то вроде:

powershell " Remove-Item -ErrorAction Ignore aaa.txt"
if ERRORLEVEL 1 <fail>

Если вы хотите, чтобы make игнорировал ошибки и продолжал в любом случае, вы можете использовать префикс - для строки рецепта:

clean:
        -powershell " Remove-Item -ErrorAction Ignore aaa.txt"
        powershell " Remove-Item -ErrorAction Ignore bbb.txt"
...