C言語で静的・動的ライブラリを作成・使用する方法

#目的
Linuxで.a（静的）と.so（動的）の２種類ライブラリを作成できるが、コンパイルする時に同じような方法で使用される。
即ち、異なるライブラリのlibA.aとlibA.soが存在しても、コンパイルのコマンドではライブラリの拡張子が省略され、gcc xxx -lAのようになるため、どっちが使用されるかは曖昧になる。

libA.aとlibA.soが共存する場合の動作確認をしたく、メモする。

#先に結論
gcc -o main main.c -L. -lA
のように、ライブラリlibA（-lAで指定）が指定されている場合、libA.so（動的）はlibA.a（静的）より優先的にリンクされる。

***追記***
gcc -o main main.c -L. -static -lA
のように、「-static」を指定すれば、libA.a（静的）はリンクされる。

***追記2***
gcc -o main main.c -L. -static-libgcc -Wl,-Bdynamic,-lc,-Bstatic,-lA
のように、gccの「-Wl」オプションで「-Bdynamic」（動的）や「-Bstatic」（静的）を指定すれば、ライブラリを選択することは可能。
（@yumetodoさん本当にありがとうございました！）

#サンプルコード
下記記事のコードを使用する。
また、静的ライブラリでnumを5にして、動的ライブラリでnumを10にして、コンパイルの時に使用されたのはどっちかを判明できる。
>[C言語グローバル変数の宣言](https://qiita.com/Pirlo/items/c16aaff0adf63acca8c7)

#動的ライブラリの作成及び動作確認

```c:A.c
#include<stdio.h>
#include"A.h"

 void A(){
     num = 10;   //動的ライブラリでnumを10にする
     printf("inside A, num = %d\n", num);
 }
```

```shell
#Aの共有（動的）ライブラリを作成
[pirlo@centos8 02]$ gcc -shared -o libA.so -c A.c
・・・
#メイン処理をコンパイルして実行ファイルを作成
[pirlo@centos8 02]$ gcc -o main main.c -L. -lA -lB
#ファイル一覧
[pirlo@centos8 02]$ ls
A.c  A.h  B.c  B.h  libA.so  libB.so  main  main.c
```

```shell:実行結果
[pirlo@centos8 02]$ ./main 
inside A, num = 10
inside B, num = 10
```

#静的ライブラリの作成及び動作確認

```c:A.c
#include<stdio.h>
#include"A.h"

 void A(){
     num = 5;   //静的ライブラリのここだけは違う
     printf("inside A, num = %d\n", num);
 }
```

```shell
#Aの静的ライブラリを作成
[pirlo@centos8 02]$ gcc -c A.c B.c   #オブジェクト「.o」ファイルが作成される
[pirlo@centos8 02]$ ls
A.c  A.h  A.o  B.c  B.h  B.o  main.c
[pirlo@centos8 02]$ ar rcs libA.a A.o   #オブジェクトファイルから静的ライブラリを作成
[pirlo@centos8 02]$ ls
A.c  A.h  A.o  B.c  B.h  B.o  libA.a  main.c
・・・Bの関連処理を略・・・
#メイン処理をコンパイルして実行ファイルを作成（コマンドは動的の時と完全一致）
[pirlo@centos8 02]$ gcc -o main main.c -L. -lA -lB
#ファイル一覧
[pirlo@centos8 02]$ ls
A.c  A.h  A.o  B.c  B.h  B.o  libA.a  libB.a  main  main.c
```

```shell:実行結果
[pirlo@centos8 02]$ ./main 
inside A, num = 5
inside B, num = 5
```

#動的・静的ライブラリが共存する場合で再度確認

```shell
#ファイル一覧
[pirlo@centos8 02]$ ls
A.c  A.h  A.o  B.c  B.h  B.o  libA.a  libA.so  libB.a  libB.so  main.c
#同じコンパイルコマンドで実行ファイルを再作成
[pirlo@centos8 02]$ gcc -o main main.c -L. -lA -lB
```

```shell:実行結果
[pirlo@centos8 02]$ ./main 
inside A, num = 10
inside B, num = 10
```

#まとめ
動的・静的ライブラリが共存する場合、動的ライブラリが優先的に参照される。

***追記***
「-static」オプションを追加すれば、静的ライブラリは参照される。

```shell:実行結果
[pirlo@centos8 02]$ ls
A.c  A.h  A.o  B.c  B.h  B.o  libA.a  libA.so  libB.a  libB.so  main.c
#「-static」オプション無し
[pirlo@centos8 02]$ gcc -o main main.c -L. -lA -lB
[pirlo@centos8 02]$ ./main 
inside A, num = 10
inside B, num = 10
#「-static」オプション有り
[pirlo@centos8 02]$ gcc -o main main.c -L. -static -lA -lB
[pirlo@centos8 02]$ ./main 
inside A, num = 5
inside B, num = 5
```

***追記2***
gccの「-Wl」オプションで「-Bdynamic」（動的）や「-Bstatic」（静的）を指定すれば、ライブラリを選択することは可能。

```shell:実行結果
#AとBの静的ライブラリを使用
[pirlo@centos8 02]$ gcc -o main main.c -L. -static-libgcc -Wl,-Bdynamic,-lc,-Bstatic,-lA,-lB
[pirlo@centos8 02]$ ./main 
inside A, num = 5
inside B, num = 5
#すべての動的ライブラリを使用
[pirlo@centos8 02]$ gcc -o main main.c -L. -static-libgcc -Wl,-Bdynamic,-lc,-lA -lB
[pirlo@centos8 02]$ ./main 
inside A, num = 10
inside B, num = 10
```



#各参照先
##動的ライブラリの作成を下記内容を参考
>[17.3. GCC での動的ライブラリーの作成](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/developer_guide/creating-libraries-gcc_creating-dynamic-libraries-gcc)

##静的ライブラリの作成を下記内容を参考
>[17.4. GCC および ar での静的ライブラリーの作成](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/developer_guide/creating-libraries-gcc_creating-static-libraries-gcc)