やりたかったこと
他の静的ライブラリに依存した静的ライブラリを使用してプログラムをビルドしたいと考えました。結論から言うと静的ライブラリのリンク順に気を付ければよいだけだったのですが、少し嵌ったので記事として残しておきます。
実際にやろうとしたことはもう少し複雑だったのですが、この記事では問題を簡単化して以下のような構成とします。
パス | 内容 |
main.cpp | プログラムのソースコード |
add10/add10.cpp | add10関数を実装したソースコード |
add10/add10.hpp | add10関数のプロトタイプ宣言を含んだヘッダファイル |
add10/libadd10.a | add10.cppから作成した静的ライブラリ |
add20/add20.cpp | add20関数を実装したソースコード add10.hppをインクルードし、add10関数を使用 |
add10/add20.hpp | add20関数のプロトタイプ宣言を含んだヘッダファイル |
add20/libadd20.a | add20.cppから作成した静的ライブラリ |
main.cppをlibadd10.aとlibadd20.aを利用してビルドすることが最終的な目標です。
ソースコードはそれぞれ以下のようなコードです。
// add10.hpp
int add10(int x);
// add10.cpp
#include "add10.hpp"
int add10(int x) {
return x + 10;
}
// add20.hpp
int add20(int x);
// add20.cpp
#include "add20.hpp"
#include "../add10/add10.hpp"
int add20(int x) {
return add10(add10(x));
}
// main.cpp
#include <iostream>
#include "add20/add20.hpp"
extern int add20(int x);
int main(int argc, char *argv[]) {
auto x = 10;
x = add20(x);
std::cout << "add20(10)=" << x << std::endl;
return 0;
}
add20.cppで実装されているadd20関数はadd10関数に依存しています。つまり、libadd20.aはlibadd10.aに依存している状態です。
静的ライブラリの生成
add10.cppからlibadd10.aを作成するには以下の手順を踏みます。
- add10.cppからadd10.oを生成
- add10.oからlibadd10.aを生成
1.のadd10.cppからadd10.oを生成するのは次のようにg++ -cを使うだけです。
$ g++ -c add10.cpp
2.のadd10.oからlibadd10.aを生成するのには次のようにarコマンドを使います。
$ ar r libadd10.a add10.o
このように2つのコマンドでadd10.cppからlibadd10.aを作ることが出来ます。
libadd20.aも同様の手順で作成することができます。libadd20.aの生成時にlibadd10.aは必要ありません。
libadd20.aとlibadd10.aを利用したプログラムのビルド
libadd20.aとlibadd10.aが生成できたので、これらを利用してmain.cppをビルドします。libadd10.aとlibadd20.aをリンクするので、-ladd10と-ladd20を付加することになりますが、以下のように先に-ladd20を指定することがポイントです。
$ g++ main.cpp -Ladd20 -ladd20 -Ladd10 -ladd10
-ladd10を先に指定するとundefined reference to `add10(int)'
となってしまいビルドに失敗します。
まとめ
この記事のまとめは以下のようになります。
- 静的ライブラリの作成にはg++ -cとar rを使用
- 静的ライブラリは依存先を後に指定
コメント