この記事で解決したいこと
cargo-make
をWindows 環境にもクロスプラットフォーム対応したいプロジェクトで採用したところ、 yarn
などの一部のコマンドの処理で NotFound
エラーにより実行不能となるトラブルに見舞われた。どうにかしたい。
例
プロジェクトの一部に npm パッケージを yarn
したいワークスペースがあり下記のように yarn
を command
とした Makefile.toml
を記述した。
[tasks.repro]
args = [ "build" ]
command = "yarn"
↓ cargo make repro
を Windows 環境で実行
[cargo-make] INFO - cargo make 0.35.7
[cargo-make] INFO - Build File: Makefile.toml
[cargo-make] INFO - Task: repro
[cargo-make] INFO - Profile: development
[cargo-make] INFO - Running Task: legacy-migration
[cargo-make] INFO - Execute Command: "yarn"
[cargo-make] ERROR - Error while executing command, error: Error {
kind: NotFound,
message: "program not found",
}
[cargo-make] WARN - Build Failed.
原因と回避方法
原因
yarn
を一般的な GNU/Linux や Mac へ導入すると実行形式のコマンド本体は shebang を伴うテキスト形式のスクリプトファイルで適当な拡張子を持つファイル名であっても一般的には PATH の効いた場所に拡張子の無い実行可能なシンボリックリンクが生成される。しかし Windows ではファイル名の拡張子への実行処理の依存性が高く、また広義的にシェルに相当する処理系での拡張子への関連付けとスクリプト処理系の接続にも不便があり、結果としてこの例では yarn
は yarn.cmd
を叩く必要 がある。
※PS> gcm yarn
がyarn.cmd
となるのは導入方法がWindowsネイティブのインストーラーを用いた場合。ちなみにnpm
経由で導入する場合はPS> yarn
はyarn.ps1
を返すが cargo-make
の command
が NotFound
する現象は同様に発生する。
回避策
[tasks.workaround]
args = [ "build" ]
command = "yarn"
[tasks.workaround.windows]
args = [ "build" ]
command = "yarn.cmd"
または
[tasks.workaround]
args = [ "build" ]
command = "yarn"
[tasks.workaround.windows]
args = [ "-C", "yarn build" ]
command = "powershell"
参考
anyhow, to incorporate that into cargo-make would mean, before each invocation to search the path for all combinations first and that is a perf hit that i would like to avoid.
cargo-make
の Author の sagiegurari の考えでは今回の例のような現象に対して cargo-make
本体で対応を行いユーザーが tasks.workaround.windows
のような回避策を実装する手間を省こうとすると .cmd
等々の実行可能な拡張子を含めたパス検索に伴う性能低下が懸念されるため、この場合は便利よりも性能要求へ cargo-make
としての判断の舵を切りたい、とのことのようでした。