1. 程式人生 > >經驗總結---編譯出可以在Android上執行的可執行檔案

經驗總結---編譯出可以在Android上執行的可執行檔案

作為一手包攬Ubuntu和Android裝置的初級開發者,我不止一次地嘗試把這兩個同是用Linux核心的作業系統統一起來——讓Ubuntu下的可執行程式能夠在Android裝置上執行。於是我不止一次地嘗試,不止一次地查詢資料,終於如願以償。

我把我的經驗在這裡與大家分享。

準備工具

【宿主機】

(1)glibc-arm2.1.7庫檔案——讓Android系統能夠跑起自己編譯好的程式

(2)arm-linux-gcc4.4.3——嵌入式ARM系統的應用程式編譯器,這個就不必多說了。執行之前請務必保證設定好環境變數。

【Android裝置】

(1)要求已經Root——在沒有開啟Root許可權的情況下,本教程中編譯好的程式會無法執行,出現Segmentation Fault的錯誤。

(2)RE管理器——Android上的檔案管理工具,在這裡用於複製檔案

(3)終端模擬器(建議用Terminal Emulator)——用於除錯我們的程式

具體步驟

1.在宿主機上,通過預先用arm-linux-gcc編譯,獲取程式直譯器和共享庫檔名

a.在終端中執行:


arm-linux-gcc-o <輸出檔名><原始碼檔名>

得到可執行檔案

b.在終端中執行:


readelf -l <輸出檔名>

仔細找找,就可以找到程式直譯器的檔名了。一般用方括號擴起,並有”interpreter”(程式直譯器)的註明。

c.執行


readelf -d <輸出檔名>    

在輸出結果中找到”NEEDED”一行。該行最右邊就是共享庫的檔名。有多少個檔名就有多少個共享庫。

d.搞定之後,把輸出檔案刪掉。

之所以要進行這一步,是因為不同的程式對應的程式直譯器可能不同。

2.在宿主機上用arm-linux-gcc正式編譯出可執行檔案

這一步編譯出來的可執行檔案是要直接放到裝置上執行的。

必須使用以下格式:


arm-linux-gcc-o <輸出檔名> <原始碼檔名> -Wl,-dynamic-linker=/yourpath/<程式直譯器檔名>

其中:-dynamic-linker後接程式直譯器在裝置上的完整路徑(注意:不是宿主機上面的路徑),下文中該路徑直接簡稱為yourpath。

3.把程式直譯器、共享庫複製出來

進入glibc-arm解壓目錄中的”lib”資料夾,在其中找到我們之前看到的幾個檔案。

值得注意的是,一般情況下,glibc-arm的一些庫檔案會用符號連結,指向另外的庫檔案。在檔案管理器中,符號連結是帶有小箭頭的。可以通過右擊符號連結,選擇“屬性”,看到它們的對應關係。

如:

ld-linux.so.3==>ld-2.17.so

libc.so.6==>libc-2.17.so

這時我們要把被連結的庫檔案複製出來,不能只複製帶有小箭頭的符號連結,否則等於沒複製!

4.把可執行檔案和庫檔案複製到裝置中。

(1)把可執行檔案放到system、data、cust這些分割槽中(它們使用的是ext3、yaffs2等檔案系統,對Linux命令相容較好。放到FAT檔案系統中很容易出現各種PermissionDenied)。然後設定許可權為rwxrwxrwx.

(2)安放程式直譯器

a。用RE管理器把被連結的程式直譯器庫檔案放到system、data、cust這些分割槽的任意目錄中,記下它所在的路徑。

b.接著設定其許可權為rwxrwxrwx。(長按該檔案,選擇“許可權”)

c。開啟終端,輸入:ln-s <被連結的程式直譯器庫檔名完整路徑>/<該庫檔案的檔名>/yourpath/<程式直譯器庫檔名>

在裝置上建立符號連結。這樣就安放好了。

注:Ubuntu下不方便用adb,所以我的做法是:開啟裝置的USB儲存連線,把需要的檔案統統拷進去,剩下的複製貼上、符號連結建立就用RE管理器了。

(3)把共享庫放到Android的庫目錄中

Android系統可用的庫目錄有/system/lib,/vendor/lib,用哪個都行。可在裝置上開啟終端模擬器,執行echo$LD_LIBRARY_PATH檢視。(值得注意的是,在沒有執行su的情況下,會看到不止一個目錄;但是在su之後,只能使用上述的兩個目錄。)

安放的方法和(2)類似:

a.用RE管理器把被連結的共享庫檔案放到/system/lib或/vendor/lib目錄中。

b.接著設定其許可權為rwxrwxrwx。

c.開啟終端,輸入:


ln -s <被連結的共享庫檔名完整路徑>/<該庫檔案的檔名> /system/lib/<共享庫檔名>

或輸入:


ln -s <被連結的共享庫檔名完整路徑>/<該庫檔案的檔名> /vendor/lib/<共享庫檔名>

在裝置上建立符號連結。這樣就安放好了。

4.在裝置上開啟終端模擬器進行除錯

先執行su,開啟root許可權,然後切換到可執行檔案所在的目錄,輸入

./<可執行檔名>
回車,即可看到效果。


如果覺得上面的步驟看起來有些暈,不妨看看我在下面舉的具體例子!

例項說明

我打算把下面的這段C原始碼編譯出來,放到我的Android手機上面執行:

【程式碼內容】

#include<stdio.h>
 
int main()

int i=0;
 printf("HELLO ANDROID!");
 for(i=0;i<=100;i++)
   printf("%d ",i);
printf("END");
return 0;
}


【可執行檔案放在】/system/

【可執行檔名】hello4

【程式直譯器放在】/system/(我把檔案放到/vendor/lib/)

【共享庫檔案放在】/vendor/lib/

【宿主機上的工作目錄】/home/administrator/complie/

【具體步驟】

1.預先編譯。

在終端中輸入:


arm-linux-gcc-o hello41 hello.c

得到臨時的可執行檔案hello41。

然後執行


readelf -l hello41
得知程式直譯器的名字(ld-linux.so.3)。再執行readelf-d hello41,得知共享庫的名字(libc.so.6)。

如圖所示:

2.正式編譯

在終端中執行:


arm-linux-gcc-o hello4 hello.c-Wl,-dynamic-linker=/system/lib-linux.so.3
回車即得輸出的可執行檔案hello4.

3.找到庫檔案

進入glibc-arm解壓目錄的lib子目錄,找到lib-linux.so.3和libc.so.6兩個檔案。但它們是帶有小箭頭的符號連結。

這時右擊lib-linux.so.3,選擇“屬性”,檢視它連結到的檔案,是ld-2.17.so;類似地,得知libc.so.6連結到的檔案是libc-2.17.so。

把ld-2.17.so和libc-2.17.so複製出來。

4.把檔案複製到裝置上。

連上手機,開啟USB儲存裝置,把可執行檔案hello4,和上面的兩個庫檔案ld-2.17.so和libc-2.17.so都複製到裝置的SD卡中。接著關閉USB儲存裝置,稍等片刻開啟RE管理器:

把可執行檔案hello4複製到/system/目錄中,然後長按該檔案,選擇“許可權”,把上面的9個勾全部勾上(也就是設定rwxrwxrwx許可權)。

同理,把ld-2.17.so和libc-2.17.so複製到/vendor/lib/中,用同樣的方法設定許可權為rwxrwxrwx。

接著開啟終端模擬器建立符號連結,執行:

su                                                  //開啟管理員許可權
 
ln-s /vendor/lib/ld-2.17.so /system/ld-linux.so.3
 
ln-s /vendor/lib/libc-2.17.so /vendor/lib/libc.so.6


就可以了。

P.S.以上建立符號連結的操作也可以用RE管理器搞定,方法:長按檔案,把選單拖到最下面,選擇”連結到檔案”,進到需要建立符號連結的目錄,點選“建立連結”,最後按上面ln命令的寫法給符號連結重新命名就可以了。

5.開啟終端模擬器測試

依次輸入

su            //開啟管理員許可權
 
cd system     //切換到/system目錄
 
./hello4      //執行程式


就可以成功看到如下的執行結果:

至此,順利成功!

相關資源

glibc-arm 庫檔案:http://download.csdn.net/detail/remme123/5422131  (感謝remme提供)

參考資料

[1]基於glibc的程式在android上的移植—轉,andy_1982,http://www.eoeandroid.com/thread-22046-1-1.html

[2][11]缺少動態連線庫.so--cannotopen shared object file: No such file or directory,SmartVessel,http://www.cnblogs.com/smartvessel/archive/2011/01/21/1940868.html

[3]bash:***: No such file or directory , seamus,http://blog.csdn.net/dlutxie/article/details/8645051

[4]關於-/bin/sh:命令:notfound的解決辦法,micheal7500,http://blog.chinaunix.net/uid-20539088-id-115759.html


--------------------- 
作者:愛拼安小匠 
來源:CSDN 
原文:https://blog.csdn.net/u012303373/article/details/37694597 
版權宣告:本文為博主原創文章,轉載請附上博文連結!