⑴ android 靜態庫 怎麼push
要有adb
小機要root
用USB線連接小機和PC,在命令行下按以下順序執行
1.adb root
2.adb remount
3.adb push 要push的.so push到小機的路徑
Linux庫有動態與靜態兩種,動態通常用.so為後綴,靜態用.a為後綴。例如:libhello.so libhello.a
為了在同一系統中使用不同版本的庫,可以在庫文件名後加上版本號為後綴,例如: libhello.so.1.0,由於程序連接默認以.so為文件後綴名。所以為了使用這些庫,通常使用建立符號連接的方式。
ln -s libhello.so.1.0 libhello.so.1
ln -s libhello.so.1 libhello.so
動態庫和靜態庫的區別:
當要使用靜態的程序庫時,連接器會找出程序所需的函數,然後將它們拷貝到執行文件,由於這種拷貝是完整的,所以一旦連接成功,靜態程序庫也就不再需要了。然而,對動態庫而言,就不是這樣。動態庫會在執行程序內留下一個標記『指明當程序執行時,首先必須載入這個庫。由於動態庫節省空間,linux下進行連接的預設操作是首先連接動態庫,也就是說,如果同時存在靜態和動態庫,不特別指定的話,將與動態庫相連接。
兩種庫的編譯產生方法:
第一步要把源代碼編繹成目標代碼。以下面的代碼hello.c為例,生成hello庫:
/* hello.c */
#include
void sayhello()
{
printf("hello,world\n");
}
用gcc編繹該文件,在編繹時可以使用任何全法的編繹參數,例如-g加入調試代碼等:
gcc -c hello.c -o hello.o
1.連接成靜態庫
連接成靜態庫使用ar命令,其實ar是archive的意思
$ar cqs libhello.a hello.o
2.連接成動態庫
生成動態庫用gcc來完成,由於可能存在多個版本,因此通常指定版本號:
$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o
另外再建立兩個符號連接:
$ln -s libhello.so.1.0 libhello.so.1
$ln -s libhello.so.1 libhello.so
這樣一個libhello的動態連接庫就生成了。最重要的是傳gcc -shared 參數使其生成是動態庫而不是普通執行程序。
-Wl 表示後面的參數也就是-soname,libhello.so.1直接傳給連接器ld進行處理。實際上,每一個庫都有一個soname,當連接器發現它正在查找的程序庫中有這樣一個名稱,連接器便會將soname嵌入連結中的二進制文件內,而不是它正在運行的實際文件名,在程序執行期間,程序會查找擁有 soname名字的文件,%B
⑶ 如何生成靜態庫和動態庫
靜態庫
靜態庫的後綴是.a,它的產生分兩步
Step 1.由源文件編譯生成一堆.o,每個.o里都包含這個編譯單元的符號表
Step 2.ar命令將很多.o轉換成.a,成為靜態庫
動態庫的後綴是.so,它由gcc加特定參數編譯產生。具體方法參見後文實例。123123
在 GNU/Linux 系統中靜態鏈接文件實際上就是多個 .o 文件的壓縮包。假設我們有 cool.h cool.c 和 some.c 文件,要得到靜態鏈接庫 libcool.a。首先使用如下指令得到相應的 object 文件 cool.o 和 some.o:
gcc -c cool.c
gcc -c some.c1212
用這種方法生成的 object 文件稱為 PDC 即位置相關代碼(position-dependence code)。再使用如下指令可以得到靜態鏈接文件 libcool.a:
ar -r libcool.a cool.o some.o
ranlib libcool.a1212
靜態鏈接庫 libcool.a 遵從 GNU/Linux 規定的靜態鏈接庫命名規范,必須是」libyour_library_name.a」
動態庫
在 GNU/Linux 中動態鏈接文件,必需通過鏈接器 ld 生成。假設我們有 hot.c other.c 等文件要生成動態鏈接庫 libhot.so 。首先使用如下指令得到相應的 object 文件 hot.o 和 some.o
gcc -fPIC -c hot.c
gcc -fPIC -c other.c1212
參數 -fPIC 指定生成的 object 文件為位置無關代碼(position-independence code),只有 PIC 可以被用作生成動態鏈接庫。然後使用如下指令得到動態庫:
ld -Bshared -o libhot.so hot.o other.o11
或者可以使用編譯器的ld wrapper:
gcc -shared -o libhot.so hot.o other.o11
也可以使用編譯器直接生成動態庫:
gcc -fPIC -shared -o libhot.so hot.c other.c11
這里選項 -shared 指示目標文件的類型是動態鏈接庫,動態庫的命名規范是」libyour_library_name.so」
⑷ makefile 生成動態庫和靜態庫的區別
生成動態庫的時候要注意,編譯生成目標文件的時候加上-fPIC參數,生成位置無關的可重定位代碼,然後鏈接的時候加上-shared生成動態共享庫。比如一個hello.c,生成靜態庫:
gcc-ohello.o-chello.c
arrcslibhello.ahello.o
生成動態庫的命令:
gcc-fPIChello.o-chello.c
gcc-shared-olibhelllo.sohello.o
還有一個區別是:靜態庫參與鏈接過程,而動態庫不鏈接到可執行文件中,可執行程序在運行的時候,對應的動態庫也要載入到內存中,否則可執行程序運行不了。
更多詳細細節,可以網路搜索視頻教程:Makefile工程實踐
⑸ 靜態庫和動態庫的區別以及使用
我們通常把一些公用函數製作成函數庫,供其它程序使用。
函數庫分為靜態庫和動態庫兩種。
靜態庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態庫。
動態庫在程序編譯時並不會被連接到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態庫存在。
本文主要通過舉例來說明在Linux中如何創建靜態庫和動態庫,以及使用它們。
在創建函數庫前,我們先來准備舉例用的源程序,並將函數庫的源程序編譯成.o文件。
第1步:編輯得到舉例的程序--hello.h、hello.c和main.c;
hello.h(見程序1)為該函數庫的頭文件。
hello.c(見程序2)是函數庫的源程序,其中包含公用函數hello,該函數將在屏幕上輸出"Hello XXX!"。
main.c(見程序3)為測試庫文件的主程序,在主程序中調用了公用函數hello。
程序1: hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
程序2: hello.c
#include
void hello(const char *name)
{
printf("Hello %s!/n", name);
}
程序3: main.c
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
第2步:將hello.c編譯成.o文件;
無論靜態庫,還是動態庫,都是由.o文件創建的。因此,我們必須將源程序hello.c通過gcc先編譯成.o文件。
在系統提示符下鍵入以下命令得到hello.o文件。
# gcc -c hello.c
#
(注1:本文不介紹各命令使用和其參數功能,若希望詳細了解它們,請參考其他文檔。)
(注2:首字元"#"是系統提示符,不需要鍵入,下文相同。)
我們運行ls命令看看是否生存了hello.o文件。
# ls
hello.c hello.h hello.o main.c
#
(注3:首字元不是"#"為系統運行結果,下文相同。)
在ls命令結果中,我們看到了hello.o文件,本步操作完成。
下面我們先來看看如何創建靜態庫,以及使用它。
第3步:由.o文件創建靜態庫;
靜態庫文件名的命名規范是以lib為前綴,緊接著跟靜態庫名,擴展名為.a。例如:我們將創建的靜態庫名為myhello,則靜態庫文件名就是libmyhello.a。在創建和使用靜態庫時,需要注意這點。創建靜態庫用ar命令。
在系統提示符下鍵入以下命令將創建靜態庫文件libmyhello.a。
# ar cr libmyhello.a hello.o
#
我們同樣運行ls命令查看結果:
# ls
hello.c hello.h hello.o libmyhello.a main.c
#
ls命令結果中有libmyhello.a。
第4步:在程序中使用靜態庫;
靜態庫製作完了,如何使用它內部的函數呢?只需要在使用到這些公用函數的源程序中包含這些公用函數的原型聲明,然後在用gcc命令生成目標文件時指明靜態庫名,gcc將猛鍵會從靜態庫中將公用函數連接到目標文件中。注運知廳意,gcc會在靜態庫名前加上前綴lib,然後追加擴旁隱展名.a得到的靜態庫文件名來查找靜態庫文件。
在程序3:main.c中,我們包含了靜態庫的頭文件hello.h,然後在主程序main中直接調用公用函數hello。下面先生成目標程序hello,然後運行hello程序看看結果如何。
# gcc -o hello main.c -L. -lmyhello
# ./hello
Hello everyone!
#
我們刪除靜態庫文件試試公用函數hello是否真的連接到目標文件 hello中了。
# rm libmyhello.a
rm: remove regular file `libmyhello.a'? y
# ./hello
Hello everyone!
#
程序照常運行,靜態庫中的公用函數已經連接到目標文件中了。
我們繼續看看如何在Linux中創建動態庫。我們還是從.o文件開始。
第5步:由.o文件創建動態庫文件;
動態庫文件名命名規范和靜態庫文件名命名規范類似,也是在動態庫名增加前綴lib,但其文件擴展名為.so。例如:我們將創建的動態庫名為myhello,則動態庫文件名就是libmyhello.so。用gcc來創建動態庫。
在系統提示符下鍵入以下命令得到動態庫文件libmyhello.so。
# gcc -shared -fPCI -o libmyhello.so hello.o
#
我們照樣使用ls命令看看動態庫文件是否生成。
# ls
hello.c hello.h hello.o libmyhello.so main.c
#
第6步:在程序中使用動態庫;
在程序中使用動態庫和使用靜態庫完全一樣,也是在使用到這些公用函數的源程序中包含這些公用函數的原型聲明,然後在用gcc命令生成目標文件時指明動態庫名進行編譯。我們先運行gcc命令生成目標文件,再運行它看看結果。
# gcc -o hello main.c -L. -lmyhello
# ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory
#
哦!出錯了。快看看錯誤提示,原來是找不到動態庫文件libmyhello.so。程序在運行時,會在/usr/lib和/lib等目錄中查找需要的動態庫文件。若找到,則載入動態庫,否則將提示類似上述錯誤而終止程序運行。我們將文件 libmyhello.so復制到目錄/usr/lib中,再試試。
# mv libmyhello.so /usr/lib
# ./hello
Hello everyone!
#
成功了。這也進一步說明了動態庫在程序運行時是需要的。
我們回過頭看看,發現使用靜態庫和使用動態庫編譯成目標程序使用的gcc命令完全一樣,那當靜態庫和動態庫同名時,gcc命令會使用哪個庫文件呢?抱著對問題必究到底的心情,來試試看。
先刪除 除.c和.h外的 所有文件,恢復成我們剛剛編輯完舉常式序狀態。
# rm -f hello hello.o /usr/lib/libmyhello.so
# ls
hello.c hello.h main.c
#
在來創建靜態庫文件libmyhello.a和動態庫文件libmyhello.so。
# gcc -c hello.c
# ar cr libmyhello.a hello.o
# gcc -shared -fPCI -o libmyhello.so hello.o
# ls
hello.c hello.h hello.o libmyhello.a libmyhello.so main.c
#
通過上述最後一條ls命令,可以發現靜態庫文件libmyhello.a和動態庫文件libmyhello.so都已經生成,並都在當前目錄中。然後,我們運行gcc命令來使用函數庫myhello生成目標文件hello,並運行程序 hello。
# gcc -o hello main.c -L. -lmyhello
# ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory
#
從程序hello運行的結果中很容易知道,當靜態庫和動態庫同名時, gcc命令將優先使用動態庫。
⑹ linux下使用nm指令查看靜態庫/動態庫編譯內容
在Linux環境下,當你遇到鏈接庫問題時,深入理解庫的編譯內容變得尤為重要。這時,nm指令就成為一個有效的工具,幫助我們揭示靜態庫和動態庫內的編譯細節。
首先,對於靜態庫,我們可以使用命令
nm -g libname.a
執行後,如圖所示,它會列出靜態庫中的全局變數和函數介面,讓你清晰地看到庫的內部結構。
而對於動態庫,其查看方式為
nm -g libname.so
同樣會顯示出動態庫的編譯內容,包括函數和符號,這對於定位和修復與庫相關的bug時非常有用。
因此,在鏈接第三方庫或處理bug時,記得利用nm指令來記錄和分析庫的編譯內容,它能提供寶貴的線索和信息。
⑺ Cmake命令之find_library介紹
該命令用於查找庫(動態庫或者靜態庫),當構建依賴於第三方庫/系統庫,可以使用該命令來查找並使用庫(Cmake中有另外一個命令 find_package ,能獲取庫的更多信息,具體可以參考 Cmake命令之find_package介紹 )
通過一個例子來看下基本的使用,假設我們目錄和文件樹如下,:
我們在 mylib 中生成最終的庫 libmymath.a ,然後在頂層的 CMakeLists.txt 中查找這個庫文件,幾個文件的具體內容如下:
在 ./mylib/ 下執行 cmake . 和 make 以便生成庫 libmymath.a ,然後在 ./ 目錄下執行 cmake . 和 make ,得到可執行文件 test ,運行 test 的結果為:
庫的搜索路徑分為兩大類: 默認搜索路徑 和 附加搜索路徑 。
默認搜索 路徑包含 cmake 定義的以 CMAKE 開頭的一些變數(例如 CMAKE_LIBRARY_ARCHITECTURE 、 CMAKE_PREFIX_PATH 、 CMAKE_LIBRARY_PATH 、 CMAKE_FRAMEWORK_PATH )、標準的系統環境變數(例如系統環境變數 LIB 和 PATH 定義的路徑)、系統的默認的庫安裝路徑(例如 /usr 、 /usr/lib 等);
附加搜索路徑 即 find_library 命令中通過 HINTS 或 PATHS 指定的路徑;
1) 通過命令行使用 -D 指定的 CMAKE_XXX_PATH 變數,也就是形如 cmake . -DCMAKE_XXX_PATH=paths 的格式。其中 CMAKE_XXX_PATH 包含如下幾個:
CMAKE_PREFIX_PATH :指定搜索目錄的前綴,如果前綴有多個,需要以 分號分割的列表 方式提供,該變數默認為空,一旦該變數非空,那麼會搜索該變數提供的目錄,以及 ${CMAKE_PREFIX_PATH}/lib ;例如 CMAKE_PREFIX_PATH=A;B ,那麼 find_library 會從 A 、 B 以及 A/lib 、 B/lib 中搜索庫是否存在;
CMAKE_LIBRARY_ARCHITECTURE :如果該變數被設置,那麼會搜索目錄 ${CMAKE_PREFIX_PATH}/lib/${CMAKE_LIBRARY_ARCHITECTURE} ;
CMAKE_LIBRARY_PATH :指定 find_library 的庫查找目錄,默認值為空,多個值時需要以分號分割列表指定;
CMAKE_FRAMEWORK_PATH *:指定 macOS 的框架作為搜索路徑。
2) 通過在 環境變數 中指定 CMAKE_XXX_PATH 變數,例如在 window 的環境變數中增加 CMAKE_XXX_PATH (以 ; 分割多個路徑)、 Linux 中 shell 配置文件中添加(以 : 分割多個路徑)。用法和 cmake -D 指定類似,例如在我的機器中( macOS ),在 .zshrc (我的命令行配置文件)中增加 export CMAKE_LIBRARY_PATH="/XXX/……/mylib" ,即可在將該目錄加入到搜索路徑中。
3) HINTS 選項指定的路徑。
4) 系統環境變數指定的目錄,默認是 LIB 和 PATH 指定的路徑。例如在 PATH 中指定庫搜索目錄;
也可以通過 find_library 中的 PATHS ENV 環境變數名稱 ( cmake 中使用環境變數名稱的格式為 $ENV{環境變數名稱} )來指定從哪個環境變數名稱中獲取路徑,例如定義一個 TESTPATH 環境變數並賦值為 ./mylib ,並在 find_library 命令中指定使用該環境變數:
5)跟當前系統相關的平台文件路徑,一般來說指的是當前系統安裝軟體的標准目錄,不同的操作系統對應的路徑有所不同。 camke 中 find_library 與此相關的也有如下幾個, CMAKE_SYSTEM_XXX_PATH 變數,這些:
CMAKE_SYSTEM_PREFIX_PATH :指定安裝目錄的前綴,例如在 Windows 下的 /XXXX/Program Files , Linux 下的 /usr 或 /usr/local 等。 find_library 命令會搜索這些前綴目錄,也會以這些目錄加上 lib 進行搜索,例如搜索 /usr/local/lib ;
CMAKE_SYSTEM_LIBRARY_PATH :默認是當前系統的標准目錄,不建議修改它;例如在我的系統,這個變數的值是 /usr/lib/X11 ;
CMAKE_SYSTEM_FRAMEWORK_PATH : macOS 框架路徑,默認是當前系統的標准目錄,不建議修改它;例如在我的系統,這個變數的值包含了路徑 /Library/Frameworks ;
6) PATHS 選項指定的路徑。