Makefile
Make

超人的な速さでソース書き換えとmakeを繰り返すと更新がすっぽ抜けて死ぬ(タイムスタンプの精度より早くソースの書き換えとビルドを行うと更新漏れにつながる)


概要


  • makeはタイムスタンプを見てファイルの更新管理をしている



    • (依存物のタイムスタンプ) > (生成物のタイムスタンプ)⇒ 更新



  • タイムスタンプの精度は意外と荒い

  • 実行速度がタイムスタンプの精度に勝つと(ソース(更新前)のタイムスタンプ) == (ソース(更新後)のタイムスタンプ)になってしまうことがある

  • そうなると更新の必要性判定がうまく動いてくれず、更新がうまくいかなくなる

  • だからシェルやニンジャパワー1でファイルの書き換えとビルドを行うなら、ファイルの上書きとビルドをする時とかは気を付けよう


問題

Q ①のような状況で ②を実行したとき、 ファイル dst には何が書かれている?

(脳内bashで実行してみよう)



$ ls

Makefile dst src

$ cat Makefile
dst:src
cat src > dst

init:
> dst




make init 

echo "foo" >src
make dst

A fooが書かれてる

本当に?

筆者が使っているサーバで試したところ、以下のような結果となった

$ make init ;echo "foo" >src;make dst

> dst
cat src > dst
$ make init ;echo "foo" >src;make dst
> dst
make: `dst' は更新済みです

なぜか実行毎にdstが更新されたり更新済みだったりした


何が起こった?

シェルの実行速度がタイムスタンプの精度を上回った結果、

srcが前回から変更されてない→dstも更新する必要なしと判断された

makeはファイルのタイムスタンプを見て更新の不要必要を判断している

つまり、

(srcのタイムスタンプ) > (dstのタイムスタンプ) なら

『srcのほうがdstより新しい→最後にmakeしてからsrcが更新された→再ビルドが必要』となる

問題の例だと

1. make init で dst更新

2. echo "foo" >src でsrc更新

3. make dst(srcのタイムスタンプ) > (dstのタイムスタンプ) なら dst更新

という流れになる

しかし、1と2がタイムスタンプの精度より高速に終わると

`(srcのタイムスタンプ) == (dstのタイムスタンプ) という状況が成立し、

3でdstの更新が行われなくなる

現に3で更新に失敗した際、タイムスタンプは以下のようになっていた

dstとsrcのタイムスタンプが同じである

$ ls --full-time src dst

-rw-rw-r-- 1 fuyutsubaki fuyutsubaki 0 2018-06-26 12:31:16.196755342 +0900 dst
-rw-rw-r-- 1 fuyutsubaki fuyutsubaki 4 2018-06-26 12:31:16.196755342 +0900 src


対策


  • ファイルの上書きが発生する処理を避ける

  • ニンジャパワー2を手に入れてもむやみやたらに使わない





  1. ニンジャは早い 



  2. ニンジャは早い