1. 程式人生 > >學習筆記:多個靜態庫連線成一個動態庫例子

學習筆記:多個靜態庫連線成一個動態庫例子

目標:

將多個靜態庫連結為一個動態庫,提供統一的介面給外部使用。

看一下例子的目錄檔案:


編譯後將生成 libAdd.a libMutiply.a , 然後將這兩個.a靜態庫和apl_myApi.o 連結成為一個動態庫 libMyApi.so。提供這個動態庫給app.cpp使用。

(1)apl_add.cpp 及 apl_add.h 的內容

#include "apl_add.h"

int add(int a, int b)
{
	return a + b;
}
int add(int, int);
(2) apl_mutiply.cpp 及 apl_mutiply.h的內容
#include "apl_mutiply.h"

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

#include "apl_mutiply.h"

int mutiply(int a, int b);
(3) apl_myApi.cpp 及 apl_myApi.h的內容
#include "apl_add.h"
#include "apl_mutiply.h"
#include "apl_myApi.h"

int my_add(int a, int b)
{
	return add(a,b);
}

int my_mutiply(int a, int b)
{
	return mutiply(a, b);
}

int my_add(int a, int b);
int my_mutiply(int, int);

(4)app.cpp內容
#include <iostream>
#include "apl_myApi.h"
using namespace std;

int main()
{
	int a = 10, b = 15;
	int sum = my_add(a, b);
	cout << "sum = " << sum << endl;
	int mut = my_mutiply(a, b);
	cout << "mutiply = " << mut << endl;
	return 0;
}
(5)allMake.sh 這個shell指令碼是編譯全部檔案,內容如下:

#!/bin/bash

echo "start building libAdd.a libMutiply.a libMyApi_so.so app......"

g++ -c -fPIC apl_add.cpp
ar -rcs libAdd.a apl_add.o

g++ -c -fPIC apl_mutiply.cpp
ar -rcs libMutiply.a apl_mutiply.o

# two static .a lib link to a dynamic .so lib
g++ -c -fPIC apl_myApi.cpp
g++ -shared -fPIC apl_myApi.o -o libMyApi_so.so -L. -lAdd -lMutiply

g++ -c app.cpp
g++ app.o -o app -L. -lMyApi_so

sudo cp libMyApi_so.so /usr/lib
echo "build done.........."


注意: 這往下是想把LibAdd.a 和 libMutiply.a 連結成LibMyApi_a.a, 發現不行在編譯app.cpp的時候還是需要將這兩個庫加上不然編譯不過。
或者直接將apl_add.o 和apl_mutiply.o 和 apl_myApi.o 一起編譯成 libMyApi.a。
echo "start building libAdd.a libMutiply.a libMyApi_a.a app_s......"

g++ -c apl_add.cpp
ar -rcs libAdd.a apl_add.o

g++ -c apl_mutiply.cpp
ar -rcs libMutiply.a apl_mutiply.o

# two static .a lib link to a static .a lib
g++ -c apl_myApi.cpp
ar -rcs libMyApi_a.a apl_myApi.o #apl_add.o apl_mutiply.o #`ar -x ./libAdd.a ./libMutiply.a`

g++ -c app.cpp
g++ app.o -o app_s -L. -lMyApi_a -lAdd -lMutiply

echo "end building................"
(6)clearAll.sh shell指令碼是清除目標檔案
#!/bin/bash

sudo rm -rf *.a *.o *.so app *.bak


例子比較簡單,記錄下生成靜態庫和動態庫的套路。

補充:

問題描述:

假如apl_add.c,apl_add.h 用gcc 編譯為aplAdd.a靜態庫; apl_mutiply.cpp, apl_mutiply.h 用g++編譯為aplMutiply.a靜態庫。 這時候如果apl_myApi.cpp在包含標頭檔案 apl_add.h的時候如果沒有使用extern "C" {} ,編譯也不會報錯,但是生成的libMyApi.so 在被app.cpp連結的時候會報錯:apl_add.c中的函式add沒有定義。原因是因為

aplAdd.a是gcc編譯出來的,而編譯連結libMyApi.so使用的是g++編譯器。因此在apl_myApi.cpp中必須這樣:

extern "C"

{

     #include "apl_add.h"

}