GNU Make 和 Windows Powershell:"Remove-Item -ErrorAction Ignore" 不起作用
GNU Make and Windows Powershell : "Remove-Item -ErrorAction Ignore" does not work
我正在 Windows PowerShell 控制台中将 Makefile(在 linux bash 中工作)转换为 运行。我使用 GNU Make 4.2.1。我在将 rm bash 命令转换为等效的 PowerShell
时遇到问题
例如,在这个简单的 makefile
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] Error 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。
我对 PowerShell 一无所知,但 make 不关心调用的命令打印的文本是什么。它只关心退出代码。
根据您的经验,如果文件不存在,PowerShell Remove-Item
似乎仍然以非 0(失败)退出代码退出,而 Ignore
操作只是告诉它不存在打印错误。
请注意,您的批处理文件不是 make 所做的。它的作用更像是:
powershell " Remove-Item -ErrorAction Ignore aaa.txt"
if ERRORLEVEL 1 <fail>
如果你想让 make 忽略错误并继续,你可以使用 the -
prefix 作为配方行:
clean:
-powershell " Remove-Item -ErrorAction Ignore aaa.txt"
powershell " Remove-Item -ErrorAction Ignore bbb.txt"
提供了有用的背景信息和 PowerShell 外部 的实用解决方法。
关于为什么PowerShell报告退出码1
:
当使用带有(隐含的)-Command
参数的 CLI 时,它是(最后)语句的成功状态,反映在布尔自动变量 $?
中,即映射到退出代码 0
($true
) 和 1
($false
).
Remove-Item -ErrorAction Ignore aaa.txt
的故意 沉默 失败令人惊讶地反映在 $?
作为 $false
尽管如此,导致退出代码 1
.
- this GitHub issue 中讨论了这种令人惊讶的行为。
解决方法(如果问题需要从 PowerShell 中解决):
在最简单的情况下,附加 ; $null
(转义为 ; $null
以便在 Makefile 中使用):
clean:
powershell "Remove-Item -ErrorAction Ignore aaa.txt; $$null"
powershell "Remove-Item -ErrorAction Ignore bbb.txt; $$null"
通过 CLI 输出 $null
是安静、成功的无操作,将退出代码重置为 0
。
另一个选项 - 仅适用于 v6.x - 是将命令括在括号中:
clean:
powershell "(Remove-Item -ErrorAction Ignore aaa.txt)"
powershell "(Remove-Item -ErrorAction Ignore bbb.txt)"
(...)
将一个命令变成一个表达式,这个表达式本身被认为是成功的,即使包含的命令报告一个(非终止)错误,它将 $?
重置为 $true
因此导致退出代码 0
.
请注意,这种行为也令人惊讶,如 this GitHub issue, which is why it was changed in v7.0, to better support &&
and ||
, the pipeline-chain operators
中所讨论
我正在 Windows PowerShell 控制台中将 Makefile(在 linux bash 中工作)转换为 运行。我使用 GNU Make 4.2.1。我在将 rm bash 命令转换为等效的 PowerShell
时遇到问题
例如,在这个简单的 makefile
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] Error 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。
我对 PowerShell 一无所知,但 make 不关心调用的命令打印的文本是什么。它只关心退出代码。
根据您的经验,如果文件不存在,PowerShell Remove-Item
似乎仍然以非 0(失败)退出代码退出,而 Ignore
操作只是告诉它不存在打印错误。
请注意,您的批处理文件不是 make 所做的。它的作用更像是:
powershell " Remove-Item -ErrorAction Ignore aaa.txt"
if ERRORLEVEL 1 <fail>
如果你想让 make 忽略错误并继续,你可以使用 the -
prefix 作为配方行:
clean:
-powershell " Remove-Item -ErrorAction Ignore aaa.txt"
powershell " Remove-Item -ErrorAction Ignore bbb.txt"
关于为什么PowerShell报告退出码1
:
当使用带有(隐含的)
-Command
参数的 CLI 时,它是(最后)语句的成功状态,反映在布尔自动变量$?
中,即映射到退出代码0
($true
) 和1
($false
).Remove-Item -ErrorAction Ignore aaa.txt
的故意 沉默 失败令人惊讶地反映在$?
作为$false
尽管如此,导致退出代码1
.- this GitHub issue 中讨论了这种令人惊讶的行为。
解决方法(如果问题需要从 PowerShell 中解决):
在最简单的情况下,附加 ; $null
(转义为 ; $null
以便在 Makefile 中使用):
clean:
powershell "Remove-Item -ErrorAction Ignore aaa.txt; $$null"
powershell "Remove-Item -ErrorAction Ignore bbb.txt; $$null"
通过 CLI 输出 $null
是安静、成功的无操作,将退出代码重置为 0
。
另一个选项 - 仅适用于 v6.x - 是将命令括在括号中:
clean:
powershell "(Remove-Item -ErrorAction Ignore aaa.txt)"
powershell "(Remove-Item -ErrorAction Ignore bbb.txt)"
(...)
将一个命令变成一个表达式,这个表达式本身被认为是成功的,即使包含的命令报告一个(非终止)错误,它将 $?
重置为 $true
因此导致退出代码 0
.
请注意,这种行为也令人惊讶,如 this GitHub issue, which is why it was changed in v7.0, to better support &&
and ||
, the pipeline-chain operators