15
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

脱初心者のためのgccコマンド覚書

Posted at

さっきの記事を投稿したのはいいが、肝心の「いろは」の部分を記述していなかった。

かれこれ5年以上前の知識で大半は忘れてしまったが、それでも覚えている部分は多分重要な部分だからだろう、ということで備忘録として残すことにした。

コンパイルとは

某有名落ちものパズルゲーを作った会社のことではないw。

ソースコードから実行できるファイルを生成することを指す、こっちのことだ。
gcc sample.c -o sampleでソースコードsample.cから実行ファイルsampleを生成する、この行為のことだが、その過程は大きく以下の3つに分けられている。

  1. 前処理(プリプロセス)
  2. オブジェクトファイル生成(コンパイル)
  3. リンク

gccだと -E -c のオプションで段階的に処理結果を確認できる。

前処理だけ行う

gcc -E sample.c

マクロ関数(#include#ifdefなども)はこれで展開されて中身を確認できる。
自分はしないように気をつけていても、何かの事情でマクロ関数だけで画面2スクロールさせるくらい処理を書いてる変人がいることもある。
そんな過去の人が書いたコードを数十年保守するのが新人Cプログラマーの役目だと悟った時の絶望は今でも忘れない。

その時だけのマクロ定義

-Dオプションを指定すると、そのコンパイル時にだけ有効になるマクロを定義することができる。
例えば、隠し機能をコードに埋めておいて、デバッグ用のコンパイル時にだけ有効にする、みたいな使い方ができる。

オブジェクトファイルの生成

gcc -c sample.c

コンパイルのメイン処理。オブジェクトファイルを生成する。最適化やデバッグオプションを指定するならここで指定する。

デバッガオプション

gdbを利用するときに-g指定する。実はレベルを指定できて-g3はマクロ関数の呼び出しが可能なデバッガオプション。
デバッガを利用するときは最適化なし(-O0)を合わせて指定するのがいい。

gcc -O0 -g3 sample.c 

最適化オプション

何を優先で最適化するかによりコマンドが違うので、詳細はmanコマンドで要確認。
デバッガを使うときは、最適化しない-O0を指定。

リンク

    gcc sample.o

コンパイルしたオブジェクトファイルをリンクして実行ファイルにする。
math.hなど別のライブラリにある関数を利用する場合は-lmなどのオプションを指定する。

ライブラリの生成

ライブラリの生成には-shared -fPICのオプションを指定する。
/lib, /usr/lib とかにある共有ライブラリ lib*.so ファイルを作成することができる。
-fPICは動的リンクするライブラリにしたいときに指定する。
出力する共有ライブラリは必ず lib〜.so ファイル名にする。(先頭のlibがないと利用できないので注意)

gcc -shared infile1.c infile2.c ... -o liboutfile.so

ライブラリのリンク

ライブラリをリンクするときは、-Lでライブラリファイルのある ディレクトリを 指定する。(環境変数LIBRARY_PATHに追加してもいい)
同様に、ライブラリのヘッダファイルは-Iでヘッダファイルのある ディレクトリを 指定する。
また、ライブラリ名がliboutfile.soの場合は、-lオプションで-loutfileと指定する。
lib〜.so部分を指定するのがポイント。

gcc sample.o -I./headerdirname -L./libdirname -loutfile

実行するときはLD_LIBRARY_PATH

リンク時はLIBRARY_PATHにライブラリのディレクトリを指定するが、実行時にライブラリが見つからずエラーになることがある。
そんなときは配置したディレクトリを環境変数 LD_LIBRARY_PATH に追加する。
経験上「コンパイルできるのに動かない」ときは、だいたいこれか、リンク時のオプション忘れが原因。

知っておいたほうが便利なコマンド

どのライブラリがリンクできていないかを知りたい

lddコマンドで確認できる。

ldd liboutfile.so

not foundになっていたらLD_LIBRARY_PATHに追加できていない。
共有ライブラリの中から別の共有ライブラリを参照することもあるので、再帰的に確認したほうがいい。

このライブラリがあるディレクトリを知りたい

locateコマンドが便利。

locate libm.so

たまにupdatedbが実行されていなくて期待を裏切られることもある。
(おまえのことだぞ、cygwin)

そんなライブラリないんだけど

そもそも必要なライブラリがインストールされていない可能性も考慮するならググったほうがいい。
Ubuntuの場合は apt-file というパッケージが存在するので、ライブラリファイル名から必要なパッケージが検索できる。

このライブラリが提供する関数を知りたい

共有ライブラリの中に存在する関数を確認するときはnmコマンドが便利。

nm liboutfile.so

この命名規則に従っていない関数作ったやつ誰だ。このライブラリはあそこの部署か、またか、みたいな犯人探しができるw

15
16
2

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
15
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?