社会人1年目の時、仕事でC言語を使っていて、はじめて共有ライブラリの存在を理解した。
学生の時からC言語を触っていたが、ライブラリを作ったのはそれが初めてだった。
そのときに感じた疑問をふと思い出したので、つれづれなるままに記事にしてみる。
まえがき
昔々、学生だった頃に「〇〇関数を使って〜するプログラムを作れ」というC言語の課題が出たことを思い出した。
詳細は忘れたが、ざっくり言うと
- 課題1:〜を〜する
kadai1()
関数を作れ - 課題2:
kadai1()
関数を使って〜するプログラムを作れ
みたいな内容だった。
要するに「課題1」ができないと「課題2」は絶対にできない仕組みなわけだ。
課題の難易度はそれほど高くなく、授業内容を理解していれば難なく解けるレベルだったが、なぜか大学側からkadai1()
関数の実装がオブジェクトファイルになって提供されていた。
たぶん、課題1が解けない学生のための救済措置だったのだと思う。
課題2の注釈に「課題1が解けない場合はgcc -o kadai2 kadai2.c kadai1.o
でコンパイルして課題2に取り組め」みたいな記述があった気がする。
そんな些細な記憶が、今になって疑問になった。
これって、要するにkadai1()
関数のソースコードは隠蔽して、動作だけ保証する何かを提供する行為だから、*.so
とか*.a
みたいなライブラリ提供にするのが一般的なんじゃないか、と。
オブジェクトファイルとライブラリ
ライブラリはオブジェクトファイルをまとめたもの。そう自分は思っている。
ただ、ライブラリは動的だったり静的だったり共有だったり、と種類があって、用途に応じてメモリロードされるタイミングに違いをもたせられる、という認識だ。
先ほどの課題2の例で言うと、kadai1
関数が使えればいいだけで、メモリロードのタイミングを意識する必要はないのでkadai1.o
でもkadai1.so
でもkadai1.a
でも問題ない。
しかし、世の中に公開するプログラムを作るなら、その提供形態はライブラリが一般的だ。オブジェクトファイルを剥き出しで提供しているソフトウェアは少ないだろう。
Javaでいうなら、.jar
で提供することはあっても、.class
で提供することは稀ということだ。
でもライブラリパスを知らないとつまずく
ライブラリで提供するのが一般的、というはそうかもしれない。
だが、課題をこなす上で必要な「コンパイル」と「動作確認」の行為においては、オブジェクトファイルのままのほうが楽なのだ。
たとえば、*.so
で提供した場合は
$ gcc -o kadai2 kadai2.c kadai1.so
$ ./kadai2
./kadai2: error while loading shared libraries: kadai1.so: cannot open shared object file: No such file or directory
こんな感じで「コンパイルは通るのに実行できない」という状況に陥り、LD_LIBRARY_PATH
の存在を知らないと解決できない 課題の目的以外の環境問題 でつまずく学生が多発するだろう。
また、gcc
の-l
や-L
オプションの存在も無視できない。
例えば「math.h
を使いたければ-lm
オプションをつける」ことは当時の私も知っていたが、その実態がlibm.so
を参照していて、そこにライブラリパスが通っているから、という理屈を知っているわけではなく「おまじない」として習慣化しているに過ぎなかった。
ライブラリ名もkadai1.so
ではなくlibkadai1.so
にしないといけない、などという理由も必要になってくる。
課題1が解けない学生のための救済措置なのに、そんなことを強いていては本末転倒、というのが大学側の判断だったのだろう。
ライブラリの使い方を知るタイミング
OpenCVやOpenGLなどの著名なライブラリを学生時代から触っていて、ライブラリの使い方や自作、提供方法を知っている人もいるかもしれない。
だが、自分の場合は会社に入ってからだった。
たまたまそういう機会に恵まれなかっただけかもしれないが、おそらく知らずに学生を卒業してしまうほうが多数派ではないかと思う。
会社に入ってから勉強すればいい。
それもそうだ。学生のうちは巨大なプログラムの保守について話しても実感が得られないだろう。
だが、自分の場合は運が悪いのか、とても苦労した。
というのも、1行修正しただけのソースコードを全プラットフォームに対してmake実行すると、数時間ビルドが終わらないような巨大なプログラムをいきなり任されたからだ。
そんなプログラムを例に初めてライブラリのいろはを勉強しようと思っても、Makefileのニッチな記述方法やメンテされていないシェルスクリプトの読解など、別のことが邪魔をして、
「だから、このソースのここをブレークポイントで止めるにはgcc
の-g
をどこにつけばいいの?」を解読するだけでめちゃくちゃ苦労した。
-g
この2バイトの文字をつけるだけでなんでこんな苦労するんだって思った。
結言
そういうこともあり、ライブラリの知識をもっと身近な手段で知る機会はないものか。学生の時にできれば知る機会が欲しいものだ、と感じた。