このブログは、旧・はてなダイアリー「檜山正幸のキマイラ飼育記 メモ編」(http://d.hatena.ne.jp/m-hiyama-memo/)のデータを移行・保存したものであり、今後(2019年1月以降)更新の予定はありません。

今後の更新は、新しいブログ http://m-hiyama-memo.hatenablog.com/ で行います。

ロクでもない仕様とロクでもないメッセージ:レシピがないとき

[追記]記述が混乱しているから取り消ししておく。[/追記]

Makeにとってゴールと認識できない項目(ノード)が初期ゴールまたは前提項目(導出されたゴール)として出現すると:

  • make: *** No rule to make target `XXXXX'. Stop.

となる。これはいい。ゴールとして認識できないとは:

  1. まったく未知で存在もしない項目。
  2. どのルールのターゲットとしても出現しない(前提には入っている)。

認識可能なゴールに関してレシピがないと

make: Nothing to be done for `XXXXX'.

を出す。擬似ターゲットの場合、特に別名として使っている擬似ターゲットなら、このメッセージは出すべきじゃない。だが、Makeはリソース生成ルールとタスク定義ルールと別名定義ルールの区別ができないので、常にこのメッセージを出す。

  • リソース定義(生成する)ルールなら、レシピがないならエラーにすべき。だが、リソース定義という概念がない。
  • タスク定義ならレシピがないならエラーにすべき。だが、タスク定義という概念がない。
  • 項目または項目リストに対する別名定義なら、Up to dateだとメッセージすべき。だが、別名定義の概念がない。

要するに、エラーにされると困る別名定義の技法的擬似ターゲット(なんちゃってタスクでPHONYされてない)の場合に合わせて、他の状況でもエラーにしてないだけ(消極的で致し方ないな理由)。分かりにくく、人為的ミスを発見しにくい仕様になっている。

もっと酷いのは空レシピ。パターンルールからのレシピ補完を排除したり、明示的に「何もしない」を表す空レシピは妥当だ。だが、なんと空レシピを指定するとターゲットが存在しなくても存在する扱いにする、という狂った仕様になっている。

.PHONYと空レシピを組み合わせると別名が定義できることにはなるが、行き当たりばったりでヒドすぎる。[追記].PHONYと空レシピを組み合わせても効果なしと判明! 参照[/追記]

[追記]以下、事実誤認があったので取り消し。クソであることに変わりはない。[/追記]

「Nothing to be done for `XXXXX'.」は、ゴールである項目(ノード)XXXXXをルートノードとする実行計画DAG(処理すべきノードからなる逆向きのDAG)のどのノードにも非空なレシピがないときに表示される。ひとつでも非空なレシピがあれば、それが実行されて、Makeからのメッセージも出ない。大変にクソなアルゴリズム

全般にグチャグチャで腐っているとしか言いようがないが、多少でも合理化するなら、

  • 空レシピはレシピではない(と考える)。ターゲットノードに付けられたDontCareフラグである。
  • DontCareフラグの効果により、そのノードは常に(リソース実体の存在・非存在に関わらず)up-to-dateとみなされる。
  • DontCareフラグがONのノードは実質的なレシピを持ってはならない。
  • DontCareフラグにより、パターンルールからのレシピの供給は拒否される。「ほっといてくれ!」というわけだ。
  • 空レシピはレシピではないので、レシピ検索には引っかからない。
  • DontCareフラグがなくレシピもない項目(ノード)はエラーとはしないが何もしない(何もできないから)。

事実とプラクティスとしては:

  • Nothing to be done for `XXXXX'. は仕様上は警告だがエラーメッセージとみなす!ただし、どうしても“エラー”を避けられないことがある。
  • .PHONYしても、別名擬似ターゲットではこの“エラーメッセージ”が出てしまうので、空レシピというDontCareフラグを併用する。[追記]併用してもダメだと判明! 参照[/追記]
  • ゴール自体ではなくて、その上流に Nothing to be done なノード(レシピを持たないノード)があっても、Makeはゴールをup-to-dateとみなす。up-to-dateなんて実は判断できないのでイイカゲンにメッセージしているだけ。メッセージは信用出来ない。
  • つまり、ビルドフローの上流に上記の“エラー”を起こす項目(ノード)があっても、Makeはエラーとして検出できず何もしてくれないので、レシピ内でエラーが起きるようにする。
  • 情けないが、レシピを防衛的に書くのが実効性がある手法。