1. 如何設置NDK的編譯選項
1. 概述
首先回顧一下 Android NDK 開發中,Android.mk 和 Application.mk 各自的職責。
Android.mk,負責配置如下內容:
(1) 模塊名(LOCAL_MODULE)
(2) 需要編譯的源文件(LOCAL_SRC_FILES)
(3) 依賴的第三方庫(LOCAL_STATIC_LIBRARIES,LOCAL_SHARED_LIBRARIES)
(4) 編譯/鏈接選項(LOCAL_LDLIBS、LOCAL_CFLAGS)
Application.mk,負責配置如下內容:
(1) 目標平台的ABI類型(默認值:armeabi)(APP_ABI)
(2) Toolchains(默認值:GCC 4.8)
(3) C++標准庫類型(默認值:system)(APP_STL)
(4) release/debug模式(默認值:release)
由此我們可以看到,本文所涉及的編譯選項在Android.mk和Application.mk中均有出現,下面我們將一個個詳細介紹。
2. APP_ABI
ABI全稱是:Application binary interface,即:應用程序二進制介面,它定義了一套規則,允許編譯好的二進制目標代碼在所有兼容該ABI的操作系統和硬體平台中無需改動就能運行。(具體的定義請參考 網路 或者 維基網路 )
由上述定義可以判斷,ABI定義了規則,而具體的實現則是由編譯器、CPU、操作系統共同來完成的。不同的CPU晶元(如:ARM、Intel x86、MIPS)支持不同的ABI架構,常見的ABI類型包括:armeabi,armeabi-v7a,x86,x86_64,mips,mips64,arm64-v8a等。
這就是為什麼我們編譯出來的可以運行於Windows的二進製程序不能運行於Mac OS/Linux/Android平台了,因為CPU晶元和操作系統均不相同,支持的ABI類型也不一樣,因此無法識別對方的二進製程序。
而我們所說的「交叉編譯」的核心原理也跟這些密切相關,交叉編譯,就是使用交叉編譯工具,在一個平台上編譯生成另一個平台上的二進制可執行程序,為什麼可以做到?因為交叉編譯工具實現了另一個平台所定義的ABI規則。我們在Windows/Linux平台使用Android NDK交叉編譯工具來編譯出Android平台的庫也是這個道理。
這里給出最新 Android NDK 所支持的ABI類型及區別:
那麼,如何指定ABI類型呢?在 Application.mk 文件中添加一行即可:
APP_ABI := armeabi-v7a //只編譯armeabi-v7a版本APP_ABI := armeabi armeabi-v7a //同時編譯armeabi,armeabi-v7a版本APP_ABI := all //編譯所有版本
3. LOCAL_LDLIBS
Android NDK 除了提供了Bionic libc庫,還提供了一些其他的庫,可以在 Android.mk 文件中通過如下方式添加依賴:
LOCAL_LDLIBS := -lfoo
其中,如下幾個庫在 Android NDK 編譯時就默認鏈接了,不需要額外添加在 LOCAL_LDLIBS 中:
(1) Bionic libc庫
(2) pthread庫(-lpthread)
(3) math(-lmath)
(4) C++ support library (-lstdc++)
下面我列了一個表,給出了可以添加到「LOCAL_LDLIBS」中的不同版本的Android NDK所支持的庫:
下面是我總結的一些常用的CFLAGS編譯選項:
(1)通用的編譯選項
-O2 編譯優化選項,一般選擇O2,兼顧了優化程度與目標大小
-Wall 打開所有編譯過程中的Warning
-fPIC 編譯位置無關的代碼,一般用於編譯動態庫
-shared 編譯動態庫
-fopenmp 打開多核並行計算,
-Idir 配置頭文件搜索路徑,如果有多個-I選項,則路徑的搜索先後順序是從左到右的,即在前面的路徑會被選搜索
-nostdinc 該選項指示不要標准路徑下的搜索頭文件,而只搜索-I選項指定的路徑和當前路徑。
--sysroot=dir 用dir作為頭文件和庫文件的邏輯根目錄,例如,正常情況下,如果編譯器在/usr/include搜索頭文件,在/usr/lib下搜索庫文件,它將用dir/usr/include和dir/usr/lib替代原來的相應路徑。
-llibrary 查找名為library的庫進行鏈接
-Ldir 增加-l選項指定的庫文件的搜索路徑,即編譯器會到dir路徑下搜索-l指定的庫文件。
-nostdlib 該選項指示鏈接的時候不要使用標准路徑下的庫文件
(2) ARM平台相關的編譯選項
-marm -mthumb 二選一,指定編譯thumb指令集還是arm指令集
-march=name 指定特定的ARM架構,常用的包括:-march=armv6, -march=armv7-a
-mfpu=name 給出目標平台的浮點運算處理器類型,常用的包括:-mfpu=neon,-mfpu=vfpv3-d16
-mfloat-abi=name 給出目標平台的浮點預算ABI,支持的參數包括:「soft」, 「softfp」 and 「hard」
2. 阿里平頭哥宣布,自研處理器已成功落地,它的性能如何
阿里巴巴宣布旗下的平頭哥半導體完成了安卓10對RISC-V的移植並開源了全部相關代碼。從平頭哥社區發布的信息來看,安卓10系統已經可以在玄鐵910晶元上流暢運行。至於玄鐵910,則是前年阿里巴巴旗下的平頭哥半導體發布的一款號稱是業界最強的RISC-V處理器內核IP。資料顯示,玄鐵910單核性能達到7.1 Coremark/MHz,主頻達到2.5GHz,比當時業界最好的RISC-V處理器性能高40%以上。據介紹,玄鐵910可以用於設計製造高性能端上晶元,應用於5G、人工智慧以及自動駕駛等領域。
3. 華為平板上的c編譯器怎麼用
華為平板上的c編譯器按照以下步驟使用:
1、下載安裝華為平板上的c編譯器並運行軟體,之後編寫代碼,寫完之後點擊運行,可以進行代碼的編譯組建以及運行。
2、第一次運行,所以需要安裝編譯模塊,直接點擊選擇安裝即可。
3、點擊運行之後,能夠得到程序的輸出,對於格式一類的,可以點擊右上角有個縮進可以進行調整格式。
4. a54sxa庫如何編譯
步驟如下:
1、在ModelSim安裝路徑下建立一個子文件夾src,例老此如:D:\ModelSim\Actel_lib\VHDL\src
將庫的源文件拷貝到src文件夾下
2、運行ModelSim。
3、改變工作路徑到D:\ModelSim\Actel_lib\VHDL:
cd D:/ModelSim/Actel_lib/VHDL
注意斜杠方向。(該路徑與src文件夾路徑一致即可)
4、建立晶元路徑:
vlib
例如想要編譯a54sxa系列,就輸入: vlib a54sxa。想編譯A3P1000晶元,就輸入:vlib proasic3。
5、將Actel庫映射到剛才的路徑下:
vmap D:/ModelSim/Actel_lib/VHDL/(其餘路徑亦可,用以指定編譯後的文件放在哪裡)
6、編譯庫。
vcom -work src/.vhd
以SX-A庫為例:vcom -work a54sxa src/54sxa.vhd
7、(可選)編譯migration library,只有在需要migration library的情況下才需要此步驟,還沒搞懂什麼是migration library……執行語句渣含斗是這樣如磨的
vcom -work src/_mig.vhd
編譯verilog庫也是一樣的步驟,只不過在.vhd的地方改成編譯.v文件。
5. 突破封鎖!國產晶元終於有了自己的指令集
在半導體晶元領域, 指令系統是一切軟硬體生態的起點 。
以大家最熟悉的ARM和X86為例,它們就分別隸屬於RISC精簡指令集和CISC復雜指令集。
隨著物聯網、5G、AI新興領域的興起,RISC-V和MIPS兩大精簡指令集架構也頻繁出現在我們的視野內。
所謂晶元,其實都是由半導體堆出來的硬體電路,晶體管越多往往代表性能和功能越強。但無論是超級計算機還是智能手環, 它們搭載的處理器都只能識別二進制數據 。
想讓這些晶元正常運行,處理復雜的應用場景,首先就要教會它們學會類似九九乘法表的「演算法口訣」和「數學公式」, 而這些演算法口訣/公式其實就是所謂的「指令集」 。
換句話說, 指令集的功能和效率(演算法口訣/公式的類型),在很大程度上就決定了各類晶元的成就和算力的上限 。
雖然海思麒麟、龍芯、兆芯、海光、紫光、澎湃等國產晶元都在各自領域取得了不俗的成績,但無論是它們,還是其他採用X86、ARM、MIPS、RISC-V、Alpha和Power,選擇封閉、授權還是開源的國產晶元項目,其底層的指令集根基都掌握在別人手裡。
因此, 只有從指令系統的根源上實現自主,才能打破軟體生態發展受制於人的枷鎖 。
好消息是,日前龍芯中科就正式發布了自主指令系統架構「Loongson Architecture」,簡稱為「龍芯架構」或者「LoongArch」。它包括基礎架構部分,以及向量擴展LSX、高級向量擴展LASX、虛擬化LVZ、二進制翻譯LBT等擴展部分,總共接近2000條指令。同時不包含龍芯此前使用的MIPS指令系統, 並具有完全自主、技術先進、兼容生態三個方面的特點 。
目前,採用LoongArch的龍芯3A5000處理器晶元已經流片成功,完整操作系統也已穩定運行,它能對多種國際主流指令系統的高效二進制翻譯鏈,並成功演示了運行基於其它主流指令系統的復雜應用程序。
LoongArch對MIPS指令的翻譯效率是100%性能,對ARM指令翻譯的效率是90%性能,對x86的翻譯效率是80%性能。
此外,龍芯中科還在聯合產業鏈夥伴在適當的時間建立開放指令系統聯盟,在聯盟成員內免費共享LoongArch及有關龍芯IP核。
所謂IP核,我們可以理解為ARM旗下的Cortex-A78和Cortex-A55等,後置都是基於ARMv8指令集打造的核心IP架構,並授權給了高通、三星、聯發科等晶元商開發SoC移動平台。
目前,ARM剛剛發布了ARMv9指令集,如果不出意外將在下半年發布的Cortex-A79和Cortex-X2架構就將採用這套指令集。
近10年來32位手機處理器都是基於ARMv7指令集打造,在A75之前的處理器則是基於ARMv8-A設計,隨後都是ARMv8.2-A一統江湖
ARM指令集可以細分為Cortex-A(ARMv-A)、Cortex-R(ARMv-R)和Cortex-M(ARMv-M),分別適用於不同類型的晶元
比如車載晶元使用的就是Cortex-R(ARMv-R)核心IP
總之, 設計出一個純國產的自主指令集只是萬里長征的第一步 ,關鍵是後續要做出懂這個指令集的CPU(已經有了龍芯3A5000),再往後還需要讓和人類交互的「翻譯家」——編譯器懂這個指令集。也就是需要不斷完善軟硬體生態,讓我們熟悉的系統、辦公、 娛樂 和 游戲 程序都能運行在這套指令集打造的晶元之上。如果做不到這一步,國產指令集和相關晶元也只是空中樓閣而已、
作為國人,我們真心希望LoongArch這種國產指令集可以取得成功,今後無論手機、電腦、車載還是其他半導體晶元都能以使用國產指令集為榮,並走向世界。
擴展小知識
那麼,指令集又是如何影響晶元執行效率的?
我們以RISC和CISC,讓它們分別執行「清潔地面」的命令為例,看看其背後的指令邏輯差異。
邏輯上,「清潔地面」的大概思路是先拿起掃帚,掃地;拿起簸箕,用掃帚把垃圾掃進簸箕;放下掃帚和簸箕,潤濕墩布;再用墩布擦地,直至清潔地面完成。
對CISC復雜指令集而言,很容易理解「清潔地面」這套邏輯,下達「清潔地面」命令後,就能按照規則和順序,一步步自動完成。
對於RISC精簡指令集而言,它一下子可理解不了如此復雜的邏輯,必須將復雜的邏輯順序拆分,然後按照一項項簡單的命令去完成復雜的操作。
比如,想讓RISC精簡指令集完成「清潔地面」命令,就必須依次下達「拿起掃帚」、「掃地」、「拿起簸箕」、「把垃圾掃進簸箕」、「放下掃帚和簸箕」、「潤濕墩布」、「墩地」……
看起來CISC復雜指令集方便又強大?沒錯,如果要同時清潔無數房間地面,你只要對著不同的房屋說「清潔地面」、「清潔地面」、「清潔地面」……即可。
而對RISC精簡指令集,你需要對著每個房間都重復一整套復雜的命令,如果下達指令的人嘴巴不夠快(帶寬不夠大),那清潔地面的效率自然受到影響,難以和CISC復雜指令集抗衡。
但是, 現實生活中,並非所有房間的地面都需要一整套的清潔流程,比如你只需要墩地一個步驟。
對RISC精簡指令集而言,你只需對著需要清潔的房間說「墩地」、「墩地」、「墩地」即可。而由於CISC復雜指令集沒有單獨的「墩地」動作,操作起來就要麻煩許多,完成相同的墩地操作會消耗更多資源,翻譯過來就是發熱更高更費電。
這就是RISC和CISC的本質區別。 說不上誰好誰壞,只能說它們所擅長的領域各不相同。
以ARM架構為代表的RISC精簡指令集,最適合針對常用的命令進行優化,賦予它更簡潔和高效的執行環境,對不常用的功能則通過各種精簡指令組合起來完成。
RISC是將復雜度交給了編譯器,犧牲了程序大小和指令帶寬,從而換取了簡單和低功耗的硬體實現。
對以X86架構為代表的CISC復雜指令集,則適合更加復雜的應用環境。
CISC是以增加處理器本身復雜度作為代價,以犧牲功耗為代價去換取更高的性能。不過,X86架構則可通過對新型指令集的支持(如SSE4.1、AVX-512等),在一定程度上提高指定任務的執行效率和降低功耗。
現在晶元領域是RISC攻,CISC守的格局。以蘋果M1為代表的ARM架構RISC指令集晶元正在染指傳統的X86 PC市場,而且大概率會取得成功。雖然以英特爾為代表的X86陣營曾多次試圖反擊Android生態(如早期的Atom晶元),但最終卻都以失敗告終。ARM最新發布的ARMv9指令集,就給了ARM晶元入侵X86 PC大本營更多彈葯,也許用不了多久Windows ARM版PC也將成為一個更加重要的PC品類。
6. 請問有沒有DSP晶元的免費編譯器
有啊,各晶元公司都自己提供。
比如TI公司的CCS,這些都是不收費的。