0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

mikanosに挑戦中に突然Makefileがおかしくなった件

Posted at

ここ数か月、仕事の合間を見て少しずつ「ゼロからのOS自作入門」に挑戦。
どうせならすべてを自分で作ってみようと一つずつ、こつこつとやっていると、ある日突然makeをするとエラーが出るようになった。

Makefile:2: *** 分離記号を欠いています. 中止.

昨日までできていたのに!?なにこのそっけないメッセージは!!と思いながら、解決まで苦労したので、その奮闘過程をお納めください。

まずは結論から

以下、長々と発見に至った過程を綴りますが、結論は「ゼロからのOS自作入門」に記載されているMakefileの以下の修正すればOKです。

Makefileの修正点(.d 依存ファイルを作るところを修正)
%.o: %.cpp Makefile
	clang++ $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@

.%.d: %.cpp
- 	clang++ $(CPPFLAGS) $(CXXFLAGS) -MM $< > $@
+ 	clang++ $< $(CPPFLAGS) $(CXXFLAGS) -MM -MF $@ 	
	$(eval OBJ = $(<:.cpp=.o))
	sed --in-place 's|$(notdir $(OBJ))|$(OBJ)|' $@

%.o: %.c Makefile
	clang $(CPPFLAGS) $(CFLAGS) -c $< -o $@

.%.d: %.c
-	clang $(CPPFLAGS) $(CFLAGS) -MM $< > $@
+	clang $< $(CPPFLAGS) $(CFLAGS) -MM -MF $@
	$(eval OBJ = $(<:.c=.o))
	sed --in-place 's|$(notdir $(OBJ))|$(OBJ)|' $@

なんと、あっけない。。以下は駄文でございます。

原因の特定

突然、makeが通らなくなった。分離記号を欠いてます。missing separator. Stop.
シンプルだけど冷たいメッセージね。

気を取り直して、makeによって生成される「.o」ファイルや「.d」ファイルをすべて手作業で削除してもう一度makeを試した。(kernelフォルダだけでなく、そのサブフォルダのusbフォルダや、さらにそのサブフォルダのusb/xhci、usb/classdriverフォルダの中の「.o」ファイルや「.d」ファイルも削除しないとやり直せないのでお気をつけあれ)

すると、makeができた!なんだ、一時的なあれか。(←あれの原因はよくわからないけど、再起動すると直る的な・・)

そして、しばらくソースコードをいじってると、またあのエラーが出てきた!!

なんで??makeファイルは全然触ってないのに!ちなみに、make cleanすらもできない。だから、また手動で.oや.dを削除すると、またmakeが通った

この時点で一つの仮説にたどり着く(というほど大げさなものでもないが)

Visual Studio Codeでソースコード(Makefileとは全然違うmain.cppとかでも)を編集すると、そのあとからmakeができなくなる。

「Visual Studio Code makefile 分離記号」でググると早速以下のサイトがヒット!
(楽勝解決!)

VSCodeで作ったMakefileが”分離記号を欠いています”エラーになる

なになに、そうか!makefileの文字コードがVisual Studio CodeによってUTF-8のBOMありになっちゃうんだ!文字コードを正しいものに設定しよう。

・・・・。結論、文字コードを変えても症状は全く変わりませんでした。

原因を再特定

おかしい、おかしいとうなりながら、いろいろ見てると、新事実を発見!
Visual Studio Codeで対象のディレクトリを開くと「.d」ファイルが書き換えられとる!!
そもそも、.dファイルは各ソースファイルが依存しているファイルを自動的に特定してmakefileに依存性「DEPENDS」としてお知らせしてもらうために作られるもの。
だから、その中身はこんな感じになっているはず。

main.dの中身
main.o: main.cpp \
    /HOME/osbook/devenv/x86_64-elf/include/c++/v1/cstddef \
    /HOME/osbook/devenv/x86_64-elf/include/c++/v1/__config \

以下省略・・

でも、Visual Studio Codeで開いた後はなぜか、.dファイルがこんな感じに変わってしまっている。

  clang
  -MM
  -I/Home/osbook/devenv/x86_64-elf/include/c++/v1/cstddef

以下省略

なんじゃこりゃあ!
全然違うものに変わっとる。
そりゃ、分離記号も欠けてしまうわ。分離記号がなんなのかわからんが。

ということで解決を

どうやらVisual Studio Codeを立ち上げてディレクトリを読み込んだ際に、Makefile toolsという拡張機能が動いて、dry-runを行うことが原因っぽい。
dry-runというのは、実際にはmakeはやらない(.oファイルや.dファイルを作らない)けど、とりあえずやった時に出てくるメッセージを見てみるためのお試しコマンド

え、.dファイルを作らない(作るコマンドを実行しない)ならいいじゃんと思いきや、以下の部分に罠があった。

clang++ $(CPPFLAGS) $(CXXFLAGS) -MM $< > $@

これは、わかりやすく書くとこんな感じの意味をもつ。
(いろんなフラグ系は省略)

clang++ -MM main.cpp > .main.d

-MMオプションは依存関係を調べて標準出力に出力することだから、依存関係の情報をそのまま、.main.dファイルに突っ込んでいる。依存ファイルが出来上がって、よいことだ。

でも、dry-runをしてしまうとこれが問題になる。
dry-runでは実際にclang++コマンドを実行しないので、依存ファイルの情報は吐き出されない。じゃあ、何が .main.dに突っ込まれるかというとコマンドそのもの(この場合、clang++ -MM main.cppが.main.dに突っ込まれる)

おお。そういうことか。

今度こそ解決

.main.dファイルにリダイレクトしてしまうことが問題なので、そうではなくて、clang++のコマンドで依存関係をファイルに保存するオプションを使う。
それが -MF

clang++ $< $(CPPFLAGS) $(CXXFLAGS) -MM -MF $@

これでOK。ちなみに、-MFオプションの直後に保存するファイル名がこないといけないので、少し並びを変更している。

はぁ、疲れた。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?