LoginSignup
10
5

More than 5 years have passed since last update.

gcc/clang の -save-temps オプションでプリプロセッサ出力とアセンブラコードを確認する

Posted at

C/C++ コンパイルの流れ

$ gcc test.c

のように C のソースファイルから実行ファイルを作るとき、ざっくり言うと以下のような流れで処理されています。

  1. プリプロセッサ処理 (#ifdef#define マクロの展開)
  2. 1 の結果からアセンブラコードを出力 (狭義のコンパイル)
  3. 2 の結果からアセンブラが機械語コードを出力 (*.o)
  4. 3 の結果を複数集めてリンク

たいていのプログラムは複数のソースコードで構成されるので、3. の出力である *.o は目にする機会が多いと思いますが、 1-3 は gcc コマンドが内部的に処理してしまうので、 1 や 2 の結果は気にすることは少ないと思います。

この 1 や 2 の結果をファイルとして出力させるのが -save-temps オプションです。

-save-temps オプション

Store the usual “temporary” intermediate files permanently; place them in the current directory and name them based on the source file. Thus, compiling foo.c with -c -save-temps produces files foo.i and foo.s, as well as foo.o. This creates a preprocessed foo.i output file even though the compiler now normally uses an integrated preprocessor.

このオプションをつけてコンパイルすると、例えば foo.c (foo.cc) というソースファイルに対して

  • プリプロセッサ出力: foo.i (C の場合) / foo.ii (C++ の場合)
  • アセンブリコード: foo.s

を出力します。

マクロが実際にはどのように展開されているか見たい場合や、最適化の結果どのようなアセンブラコードが吐かれているのかをみたいときなどに役立ちます。

なお、 それぞれ gcc -Egcc -S でも出力できますが、これらは *.o を作らないので、大きなビルドの中に組み込むのは不便です。 -save-temps なら、ビルド自体は通常通り行いつつ中間成果物を確認することができます。

-save-temps=obj

単に -save-temps だと foo.i / foo.s はカレントディレクトリに生成されますが、
-save-temps=obj とすると foo.o と同じディレクトリに生成されます。

ビルドシステムへの組み込み

このオプションを簡単に有効にできるよう、プロジェクトのビルドシステムに組み込んでおくとよいでしょう。
(オーバーヘッドはあるはずなので常に有効にしておくようなものではないかなと)

例えば make なら

ifneq ($(SAVETEMPS),)
CFLAGS += -save-temps=obj
endif

としておいて有効にしたいときには

$ make SAVETEMPS=1

とする、みたいな話です。

warning が変わる (ことがある)

-save-temps を付けるとコンパイル時の warning の出方が変わる場合があります(-save-temps をつけると warning が増える、またその逆)。

これは、gcc は通常はプリプロセス・コンパイルを一気に行うのに対して、 --save-temps をつけると2段階で行うようになるためです。これについては別途書こうと思います。

10
5
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
10
5