makeって何するもん?

オブジェクトファイルって?


オブジェクトファイル

単独のファイルで完結しているプログラム、例えば次のコード

      #include <stdio.h>
      int main(void)
      {
          printf("hello, world!\n");
      }

は、ファイル名をhello.cとすれば、

      $ gcc hello.c

によりそれだけで実行可能なa.outというファイルが生成されます。 もし生成されるファイル名をhelloにしたいのなら

      $ gcc hello.c -o hello

と-oオプションを使えばよいのでした。

では、元のページの例のファイルmycat.cのように単独のファイルで完結していない場合はどうなのでしょうか。 とりあえず、コンパイルしてみましょうか。

        $ gcc mycat.c
        /tmp/cca236321.o: In function `mycat':
        /tmp/cca236321.o(.text+0x1d): undefined reference to `getline'
        /tmp/cca236321.o(.text+0x5d): undefined reference to `copy'

なんだかごちゃごちゃと不平を言われてますね。 a.outは作られたでしょうか?

        $ ls
        copy.c getline.c mycat.c mycat.o

必要な関数などが不足しているのだから、当然ながら、実行可能なa.outは作られていません。

でも、よく見てください。 代わりにmycat.oというファイルが出きています。 このmycat.oが、mycat.cに対応するオブジェクトファイルです。 .oのoはオブジェクト(object)のoです。 もちろん、mycat.c単独では実行可能なファイルは作れませんから、このオブジェクトファイルは実行できません。 このmycat.oには、mycat.cに記述されている内容に対応する機械語のコード(実行可能なa.outの一部)が収められているのです。


リンク: 実行可能ファイルを作る

mycat.oの他に、getline.ccopy.cから生成できるオブジェクトファイル getline.oやcopy.oがあれば、それらを結合させることでプログラム全体の機械語のコードを作れます。 やってみましょう。まず、

      $ gcc -c getline.c
      $ gcc -c copy.c
      $ ls
      copy.c copy.o getline.c getline.o mycat.c mycat.o

とすることで、getline.oとcopy.oが出来ました。 -cオプションで、「ソースファイルからオブジェクトファイルを生成しなさい」という指定をしています。 今度は

      $ gcc mycat.c

としたときに表示された「不平」を言われませんでしたね? このときは、無理な注文「実行可能ファイルa.outを生成せよ」をしているから不平を言われたのですが、-c付きだと可能な注文「オブジェクトファイルを生成せよ」なので不平を言われないわけです。

さて、これらを結合させましょう。 オブジェクトを結合させることを「リンク(link)する」と言います。

      $ gcc copy.o getline.o mycat.o -o mycat
      $ ls
      copy.c copy.o getline.c getline.o mycat.c mycat.o mycat

これで実行可能なファイルmycatが作れました。

この例のように複数に分割されたソースファイルをコンパイルするには、

      $ gcc copy.c getline.c mycat.c -o mycat

とgccに全てのソースファイルを指定することでも可能です。 しかし、内部的には、

      $ gcc -c copy.c
      $ gcc -c getline.c
      $ gcc -c mycat.c
      $ gcc copy.o getline.o mycat.o -o mycat

とするのと全く同じ手順を踏んでいます。 gccというコマンドはいわゆるラッパー(wrapper)で、コンパイル作業を実際に行なうのはcc1というコマンド、リンクを行なうのはリンカーと呼ばれるldコマンドです。

なお、リンクの作業では、オブジェクトファイルcopy.o getline.o mycat.oを結合するだけでなく、printf()などの標準関数のライブラリ(機械語のコード)やコマンドプロンプトから実行するためのローダーなども結合します。

ついでながら、a.outの名前は「アセンブラ(Assembler)の出力(OUTput)」の意味だそうです。


makeって何するもん?
小栗栖 修
メールアドレス: ogurisu[AT]kanazawa-u.ac.jp ([AT]を@におきかえてください)