home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

C言語系/memos/gcc

C言語系/memos/gcc

C言語系 / memos / gcc
id: 479 所有者: msakamoto-sf    作成日: 2009-11-16 11:05:49
カテゴリ: C言語 

gccのオプションなど自分なりのmemo


基本

#include <stdio.h>
 
int main(int argc, char **argv)
{
        printf("Hello, World!\n");
        return 0;
}

何も指定しない場合はa.outで出力する。

$ gcc hello.c
$ ls
a.out*  hello.c
$ ./a.out
Hello, World!

出力ファイル名を指定したい場合は、 "-o" オプションを使う。

$ gcc -o hello hello.c
$ ls
hello*  hello.c
$ ./hello
Hello, World!

オブジェクトファイル(*.o)までの生成にしておきたい場合は "-c" オプションを使う。

$ gcc -c hello.c
$ ls
hello.c  hello.o

"-c" オプションと "-o" オプションの併用例:

$ gcc -c -o hello_obj.o hello.c
$ ls
hello.c  hello_obj.o

コマンドラインオプション

"--save-temps", "-v" : 途中成果物の保存と実行内容詳細表示

$ gcc --save-temps -v hello.c
Using built-in specs.
Target: i386-redhat-linux
(...)
 as -V -Qy -o hello.o hello.s
GNU assembler version 2.17.50.0.6-6.el5 (i386-redhat-linux) using BFD version 2.17.50.0.6-6.el5 20061020
 /usr/libexec/gcc/i386-redhat-linux/4.1.2/collect2 (...)

$ ls
a.out  hello.c  hello.i  hello.o  hello.s
$ ./a.out
Hello, World!

"-E", "-S" : プリプロセスまで/アセンブルまで

gccに "-E" or "-S" を指定する事で、成果物の段階を指定できる。

"-E" : プリプロセスまで

"-E"オプションを指定すると、プリプロセッサまでが実行される。"-o"をつけないと標準出力に出力される。

$ gcc -E hello.c
# 1 "hello.c"
(...)
# 2 "hello.c" 2

int main(int argc, char **argv)
{
 printf("Hello, World!\n");
 return 0;
}

$ ls
hello.c

"-o"オプションを指定してみる。

$ gcc -E -o hello.i hello.c
$ ls
hello.c  hello.i

(プリプロセスの出力ファイルからコンパイルを継続することも出来る)
$ gcc hello.i
$ ls
a.out*  hello.c  hello.i

$ ./a.out
Hello, World!

"-v"をつけてみると、cppパッケージの"cc1"コマンドの実行まで処理している事が確認できる。

$ gcc -v -E -o hello.i hello.c
Using built-in specs.
Target: i386-redhat-linux
コンフィグオプション: ../configure --prefix=/usr (...)
スレッドモデル: posix
gcc バージョン 4.1.2 20071124 (Red Hat 4.1.2-42)
 /usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1 \
     -E -quiet -v hello.c -o hello.i -mtune=generic
存在しないディレクトリ \
"/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/include" \
を無視します
#include "..." の探索はここから始まります:
#include <...> の探索はここから始まります:
 /usr/local/include
 /usr/lib/gcc/i386-redhat-linux/4.1.2/include
 /usr/include
探索リストの終わり

$

※CentOS 5.2 の場合、cppコマンドは "cpp" というRPMパッケージに"cc1"と併せて収録されている。では"cpp"パッケージは"gcc"とは別物か?となるが、RPMパッケージ情報を調べると下記の通り Source RPMは"gcc"になっている。RPMパッケージングの際に、バージョニングの都合などで分離されたものと思われる(cc1まで入れてしまったら分離する意味が無いような気もするが・・・)。

$ rpm -qi cpp
Name        : cpp                          Relocations: (not relocatable)
Version     : 4.1.2                             Vendor: CentOS
Release     : 42.el5                        Build Date: 2008年05月27日 07時17分35秒
Install Date: 2008年08月02日 13時40分43秒      Build Host: builder16.centos.org
Group       : Development/Languages         Source RPM: gcc-4.1.2-42.el5.src.rpm
                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^
"-S" : アセンブラまで

"-S"オプションを指定すると、アセンブラまでが実行される。

$ ls
hello.c  hello.i

$ gcc -v -S hello.i
Using built-in specs.
Target: i386-redhat-linux
コンフィグオプション: ../configure --prefix=/usr (...)
スレッドモデル: posix
gcc バージョン 4.1.2 20071124 (Red Hat 4.1.2-42)
 /usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1 -fpreprocessed hello.i -quiet \
     -dumpbase hello.i -mtune=generic -auxbase hello -version -o hello.s
GNU C version 4.1.2 20071124 (Red Hat 4.1.2-42) (i386-redhat-linux)
        compiled by GNU C version 4.1.2 20071124 (Red Hat 4.1.2-42).
GGC heuristics: --param ggc-min-expand=64 --param ggc-min-heapsize=64436
Compiler executable checksum: 6b8fcfb678815bd99e272234accc87cd

$ ls
hello.c  hello.i  hello.s

この後、"-c"オプションでオブジェクトファイルの生成までを行える。

$ gcc -v -c hello.s
Using built-in specs.
Target: i386-redhat-linux
コンフィグオプション: ../configure --prefix=/usr (...)
スレッドモデル: posix
gcc バージョン 4.1.2 20071124 (Red Hat 4.1.2-42)
 as -V -Qy -o hello.o hello.s
GNU assembler version 2.17.50.0.6-6.el5 (i386-redhat-linux) using BFD version 2.17.50.0.6-6.el5 20061020

$ ls
hello.c  hello.i  hello.o  hello.s

最後にオブジェクトファイルを入力として、実行形式のファイルを作成する。

$ gcc -o hello hello.o
Using built-in specs.
Target: i386-redhat-linux
コンフィグオプション: ../configure --prefix=/usr (...)
スレッドモデル: posix
gcc バージョン 4.1.2 20071124 (Red Hat 4.1.2-42)
 /usr/libexec/gcc/i386-redhat-linux/4.1.2/collect2 (...)
$ ls
hello*  hello.c  hello.i  hello.o  hello.s
$ ./hello
Hello, World!

"-I", "-L", "-l"オプション

"#include"パスの追加指定は"-I"オプションを使う。

gcc (...) -I/usr/include/xxxyyy -I/opt/include/zzzz (...)

コンパイル時の"*.so"のディレクトリ指定は"-L"オプションを使う。

gcc (...) -L/usr/lib/xxxyyyy (...)

"libxyz(.<major>.<minor>.<minor2>).so"を指定したい場合は、"-l"オプションで"xyz"の部分だけを指定する。

gcc (...) -lxyz (...)

"-I", "-L", "-l" 共に、値との間に空白は挟まない。

NG:
gcc (...) -I /usr/include/xxyyzz (...)
            ^

ライブラリの作成とリンク例

静的・動的のそれぞれの作成とリンクのサンプルを載せる。(なお、以降出てくるgccのオプションで"-Wall"が付いていないのはサンプルだから、ということでご了承願います)

ソースコード構成:

$ ls
calc/  call_calc.c
$ ls calc/
calc.h  calc1.c  calc2.c

call_calc.c:

#include <stdio.h>
#include "calc.h"
 
int main(int argc, char **argv) {
        int x = 1;
        int y = 2;
        int z1 = calc1(x, y);
        int z2 = calc2(x, y);
 
        printf("calc1(%d, %d) = %d\n", x, y, z1);
        printf("calc2(%d, %d) = %d\n", x, y, z2);
        return 0;
}

calc/calc.h:

int calc1(int a, int b);
int calc2(int a, int b);

calc/calc1.c: (足し算)

int calc1(int a, int b)
{
        return a + b;
}

calc/calc1.c: (掛け算)

int calc2(int a, int b)
{
        return a * b;
}

calc1, calc2を含んだライブラリを静的・動的それぞれのパターンで作成し、call_calc.cとリンクさせてみる。

静的ライブラリの作成とリンク

binutilsのarコマンドでlibcalc.aを生成する。"-r"で格納するアーカイブファイル名を指定する。"-s"オプションで、リンクを早くする為に予め索引を作っておく。作成された索引は "nm -s" で確認できる。

$ cd ./calc
$ ls
calc.h  calc1.c  calc2.c
$ gcc -c -o calc1_nofpic.o calc1.c
$ gcc -c -o calc2_nofpic.o calc2.c
$ ar -s -r libcalc.a calc1_nofpic.o calc2_nofpic.o
ar: creating libcalc.a
$ ar t libcalc.a
calc1_nofpic.o
calc2_nofpic.o
[msakamoto@akane calc]$ nm -s libcalc.a

Archive index:
calc1 in calc1_nofpic.o
calc2 in calc2_nofpic.o

calc1_nofpic.o:
00000000 T calc1

calc2_nofpic.o:
00000000 T calc2

$ ls
calc.h  calc1.c  calc1_nofpic.o  calc2.c  calc2_nofpic.o  libcalc.a

続いてcall_calc.cをコンパイル・リンクする。"-I"でcalc.hのあるディレクトリを指定する。リンク時には、libcalc.aを後ろに指定する。

$ cd ../
$ ls
calc  call_calc.c

$ gcc -Wall -I./calc -c -o call_calc.o call_calc.c

$ ls
calc  call_calc.c  call_calc.o

$ gcc -v -o call_calc_static call_calc.o ./calc/libcalc.a
Using built-in specs.
Target: i386-redhat-linux
コンフィグオプション: ../configure (...)
スレッドモデル: posix
gcc バージョン 4.1.2 20071124 (Red Hat 4.1.2-42)
 /usr/libexec/gcc/i386-redhat-linux/4.1.2/collect2 \
     (...) -o call_calc_static (...) call_calc.o ./calc/libcalc.a (...)

$ ls
calc  call_calc.c  call_calc.o  call_calc_static*

$ ./call_calc_static
calc1(1, 2) = 3
calc2(1, 2) = 2
動的ライブラリの作成とリンク

calc1.c, calc2.cを "-fPIC" 付で位置独立コードとしてコンパイルする。

$ cd ./calc
$ ls
calc.h  calc1.c  calc1_nofpic.o  calc2.c  calc2_nofpic.o  libcalc.a
$ gcc -fPIC -c -o calc1_pic.o calc1.c
$ gcc -fPIC -c -o calc2_pic.o calc2.c
$ gcc -shared -o libcalc.so calc1_pic.o calc2_pic.o
$ ls
calc.h
calc1.c  calc1_nofpic.o  calc1_pic.o
calc2.c  calc2_nofpic.o  calc2_pic.o
libcalc.a
libcalc.so*

※今回のサンプルでは"-Wl,-soname=xxxx"は使わない。後日このオプションについて検証する。

続いてcall_calc.cをコンパイル・リンクする。"-I"でcalc.hのあるディレクトリを指定する。リンク時には、"-L"でlibcalc.soの存在するディレクトリを指定し、"-l"でライブラリ名("calc")を指定する。今回はシステムのライブラリディレクトリにはインストールしないので、一時的にLD_LIBRARY_PATHでlibcalc.soがあるディレクトリを指定し、実行する。

$ cd ../
$ ls
calc  call_calc.c  call_calc.o  call_calc_static*

$ gcc -v -L./calc -lcalc -o call_calc_so call_calc.o
Using built-in specs.
Target: i386-redhat-linux
コンフィグオプション: ../configure (...)
スレッドモデル: posix
gcc バージョン 4.1.2 20071124 (Red Hat 4.1.2-42)
 /usr/libexec/gcc/i386-redhat-linux/4.1.2/collect2 (...) \
 -o call_calc_so (...) -L./calc (...) -lcalc call_calc.o (...)

$ export LD_LIBRARY_PATH=./calc; ./call_calc_so
calc1(1, 2) = 3
calc2(1, 2) = 2

"-Wa,...", "-Wl,..."

gcc-4.1.2 のmanページから抜粋:

-Wa,option
    option  をアセンブラに対するオプションとして渡します。
    option がコンマを含む場合は、そのコンマで区切られた複数のオプションとして与えられます。
-Wl,option
    オプション option をリンカに渡します。
    option がコンマを含む場合は、それらのコンマで複数のオプションとして分割されます。

TIPS

他、書籍・雑誌記事・Webなどから拾い読みしたTIPSなど。

gccオプション:

-print-prog-name=XXXXX : gccがkickする外部コマンドの絶対パス表示
-Wall : 全ての警告を表示
-Werror : 警告をエラーと見なす

cppオプション:

-H : indent形式でインクルードの状況を表示
-M : Makefile形式で外部依存ファイルリストを表示
-dM : 全てのマクロ定義文表示。空のファイルを読ませれば、ビルトイン定義を表示してくれる。
-nostdinc : ヘッダーファイル検索パスを初期化
-v : 詳細表示


プレーンテキスト形式でダウンロード
現在のバージョン : 2
更新者: msakamoto-sf
更新日: 2009-11-28 13:28:12
md5:b6ce6fcdeea92a7b5728c04d57de2f06
sha1:1b473597cab8a2660b636565c69b7f1a6f288904
コメント
コメントを投稿するにはログインして下さい。