1. 程式人生 > >使用交叉混合編譯從原始碼編譯龍芯上的llvm/clang-3.4

使用交叉混合編譯從原始碼編譯龍芯上的llvm/clang-3.4

目標:

使用交叉混合編譯(hybrid cross-compiling)從原始碼編譯龍芯上的llvm/clang-3.4。之所以是混合交叉編譯而不是交叉編譯,是因為編譯的過程中,大部分程式碼是由效能較高的主體(Host)平臺編譯,而少部分程式碼是由效能較低的目標(Target)平臺編譯。混合交叉編譯採用了類似 COMET: Code Offload by Migrating Execution Transparently (OSDI’12) 的思想。其原理是,在目標平臺上配置,之後開始編譯時,將所有檔案同步到主體平臺上,並使用主體平臺的交叉編譯器編譯。當需要執行目標平臺命令(例如llvm-config

)時,將所有檔案同步到目標平臺、執行命令,再同步回主體平臺,並繼續編譯。

準備工作:

編譯環境:

  • 主體平臺

    • CPU:Intel Xeon(R) E5620 * 16
    • OS:Ubuntu 14.04 + Linux 3.13.0
    • 編譯器:mipsel-linux-gnu-gcc-4.4/mipsel-linux-gnu-g++-4.4
  • 目標平臺

    • CPU:loongson 3.2.0-4-loongson-2f, mipsel
    • OS:Debian 3.2.51
    • 編譯器: gcc-4.6.3/g++-4.6.3

預先準備

  $ mkdir <common/path/prefix>/mips3/llvm
  $ cp *-3.4
.src.tar.gz <common/path/prefix>/mips3/llvm $ cd <common/path/prefix>/mips3/llvm $ tar -xvf *-3.4.src.tar.gz $ mv clang-3.4 llvm-3.4/tools/clang $ rm *-3.4.src.tar.gz

以上指令碼同時在兩個平臺上執行。其中<common/path/prefix>要求兩個平臺上的路徑名稱完全相同,這是因為./configure後的makefile中包含了使用絕對路徑的變數,因此如果路徑名稱不同,會導致編譯出錯。
3. 建立編譯器符號連結
類似的,在兩個平臺上的編譯器名稱也需要一致。本文中使用mipsel-common-g++為兩者的c++編譯器,mipsel-common-gcc為兩者的c編譯器。在主體平臺上:

 $ sudo ln -s /usr/bin/mipsel-common-g++ /usr/bin/mipsel-linux-gnu-g++
 $ sudo ln -s /usr/bin/mipsel-common-gcc /usr/bin/mipsel-linux-gnu-gcc

在目標平臺上

 $ sudo ln -s /usr/bin/mipsel-common-g++ /usr/bin/g++-4.6
 $ sudo ln -s /usr/bin/mipsel-common-gcc /usr/bin/gcc-4.6
  1. 同步編譯時間
    由於不同平臺的時間和時區可能都不同,而編譯時makefile會依賴檔案時間來確定生成檔案的新舊,因此需要同步兩者的系統時間。
    1. 同步時區
  $ sudo dpkg-reconfigure tzdata

之後選擇asia->Shanghai,以便兩者平臺的時區一致。
2. 同步時間
只要使得兩個平臺的時間相同即可,本文中利用ntp協議使得目標平臺的時間和主體平臺的時間一致。在目標平臺執行以下程式碼:

  $ sudo sntp -s <host-ip>

或者在安裝ntp之後

  $ sudo service ntp stop
  $ sudo ntpdate -s time.nist.gov
  $ sudo service ntp start
  1. 同步編譯檔案
    本文使用rsync同步主體平臺和目標平臺之間的檔案。
    1. 在主體平臺建立rsync配置檔案(因為主體平臺是同步伺服器)
 address = <host-ip>
 use chroot = yes
 read only = no
 pid file = /var/run/rsyncd.pid
 log file = /var/log/rsync.log
 [mips3]
 uid = <host-user-name>
 gid = <host-group-name>
 path = <common/path/prefix>/mips3
 hosts allow = <ip-mask>  #例如192.168.0.0/8
 auth users = mips3
 secrets file = /etc/rsyncd.secrets

其中/etc/rsyncd.secrets中儲存使用者名稱為mips3的密碼,內容如下

 mips3:<host-password>

此外,為了保證rsyncd可以使用,需要將/etc/rsyncd.secrets的許可權設定為600。
2. 啟動rsyncd:

 rsyncd --daemon
  1. 建立同步命令rsync-commitrsync-update分別用於將目標平臺上的程式提交到主體平臺上,以及從主體平臺上更新目標平臺上的程式。此外,建立rsync.password使用者存放密碼,以避免每次同步時輸入密碼。
 $ cat <common/path/prefix>/mips3/rsync-commit
 #!/bin/bash
 rsync --password-file=<common/path/prefix>/mips3/rsync.password -azv <common/path/prefix>/mips3/llvm [email protected]<host-ip>::mips3
 $ cat <common/path/prefix>/mips3/rsync-update
 #!/bin/bash
 rsync --password-file=<common/path/prefix>/mips3/rsync.password -azv [email protected]<host-ip>::mips3/llvm <common/path/prefix>/mips3
 $ cat <common/path/prefix>/mips3/rsync.password
 <host-password>

編譯

配置

在編譯前,需要在目標平臺上配置編譯環境:

$ cd <common/path/prefix>/mips3/llvm/llvm-3.4
$ CC=mipsel-common-gcc CXX=mipsel-common-g++ ./configure --enable-bindings=none --prefix=`pwd`/root --enable-targets=mips

開始編譯

配置完,即可開始編譯:

$ make

在出現開始編譯某個檔案時,CTRL+C終止編譯,因為在目標平臺上編譯太慢了。此時執行<common/path/prefix>/mips3/rsync-commit,將目標平臺上的編譯結果同步到主體平臺上。之後,在主體平臺上

$ make -j<n>

使用主體平臺上numa的並行性編譯。一旦主體平臺上的編譯過程中出現錯誤,立刻切換到目標平臺上

$ <common/path/prefix>/mips3/rsync-update
$ make
... # 開始編譯下一個檔案
CTRL+C
$ <common/path/prefix>/mips3/rsync-commit

來回切換50次以內,即可編譯完成。

優化編譯過程,提高編譯效率

由於頻繁CRTL+C、切換、同步非常耗時,而且是在不同平臺上的切換(不同的物理機器),因此減少切換次數可以大大提高自動化程度。

  • 只配置mips
    clang預設會配置所有的目標平臺,而在配置每一種目標平臺時,都要呼叫當前目標平臺上的編譯結果。這也是需要頻繁切換的原因之一。因此在配置時加上--enable-targets=mips,只配置當前的目標平臺,減少切換次數。
  • 使用主體平臺上的編譯結果
    clang在編譯可執行檔案和動態共享庫時,會呼叫llvm-config獲得當前應該連結的靜態庫。這是需要頻繁切換的原因之二。因此,將llvm-config替換成主體平臺也可以執行的、具有相同功能的llvm-config可以顯著減少切換次數。
    在主體平臺上,先使用相同的配置選項配置clang,之後會生成主體平臺上的mipsel交叉編譯clang。這裡我們用的不是交叉編譯clang,而是生成的副產品:llvm-config。在將其重新命名為llvm-config-amd64,將目標平臺上的對應檔案命名為llvm-config-mips3。在主體平臺上執行以下命令,替換原有的llvm-config,即可使用主體平臺上的編譯程式。
$ cp <path/to/llvm-config-amd64>/llvm-config-amd64 <common/path/prefix>/mips3/llvm/llvm-3.4/Release+Asserts/bin/llvm-config
  • 刪去單元測試和其他測試
    刪去clang中和test、unittest相關內容,刪去llvm中test目錄,這些在編譯時都不是必要的,並且會大大增加資料的傳輸量。

安裝

$ cd <common/path/prefix>/mips3/llvm/llvm-3.4
$ make install
$ <common/path/prefix>/mips3/rsync-commit

即可將編譯好的llvm/clang安裝到<common/path/prefix>/mips3/llvm/llvm-3.4/root目錄下。

編譯完成

在目標平臺上我們來測試一個helloworld程式:

#include <iostream>

using namespace std;

int main() {
    cout << "Hello World!" << endl;
    return 0;
}

儲存並將其命名為test.cpp。使用新安裝好的clang++編譯:

$ <common/path/prefix>/mips3/llvm/llvm-3.4/root/bin/clang++ test.cpp --target=mipsel-pc-linux
$ ./a.out
Hello World!

這裡需要加上--target=mipsel-pc-linux選項。這是因為目標平臺的龍芯屬於 mipsel 體系結構,即little endianness。 而系統uname -a的結果卻是mips64。因此,llvm的配置檔案會誤認為當前平臺是mipsel64,從而生成無法執行的程式碼。

相關推薦

使用交叉混合編譯原始碼編譯llvm/clang-3.4

目標: 使用交叉混合編譯(hybrid cross-compiling)從原始碼編譯龍芯上的llvm/clang-3.4。之所以是混合交叉編譯而不是交叉編譯,是因為編譯的過程中,大部分程式碼是由效能較高的主體(Host)平臺編譯,而少部分程式碼是由效能較低的目

CentOS 原始碼編譯並安裝 Nginx

Linux 系統要求 Nginx 在 Linux 作業系統下執行的時候,要想獲取高併發能力,要求 Linux 核心必須在 2.6 以上,可通過以下命令檢視 Linux 核心版本。 $ uname -r 2.6.18-128.e15 安裝 Nginx 的必備軟體 通過以下命令安裝使用

Linux原始碼編譯安裝程式詳解

1.原始碼編譯概述 1.1 使用原始碼安裝軟體的優點: 獲得最新的軟體版本,及時修復bug 根據使用者需要,靈活定製軟體功能 1.2 應用場合舉例 安裝較新版本的應用程式時 當前安裝的程式無法滿足需要時  需要為應用程式新增新的功能時

golang 原始碼編譯記錄

下載golang 原始碼 筆者寫此部落格的時候最新是go 1.10.1 版本。 原始碼目錄 /root/source_bk/go_source/go 基本編譯流程解釋 go 語言編譯器自1.5版本開始自舉 ( 使用go編譯器編譯go編譯器 ) 。所

Python3.7.1原始碼編譯安裝

#!/bin/bash #確保shell 切換到當前shell 指令碼資料夾 current_file_path= ( c

linux下原始碼編譯比特幣客戶端

下載原始碼 這個是master分支的,建議在tag裡選最新的穩定版,目前是v0.14.2 直接下載zip,別clone了,clone很慢。 編譯程式碼 不妨先看看官方的編譯說明 ps: 第一手的官方的資源一般都是最好的,有問題了最好

在win10裡原始碼編譯nodejs的安裝包和學習原始碼

大家其實都是從網站上下載直接安裝檔案的,為什麼還要從原始碼安裝呢?可能原因就兩個,一個想自己優化,新增一個特定的東西;另一個想學習nodejs的實現,知道為什麼這樣實現的。我這裡主要為學習nodejs的實現,所以要到下面的網站下載原始碼:https://nodejs.org/

ARM64原始碼編譯docker(v1.9.1)

在X86_64機器fedora系統下,不要使用官方編譯的rpm包,交叉編譯bootstrap會出現異常,使用原始碼編譯的go. 1.編譯X86_64的go binary cd /root git clone https://github.co

零開始學習區塊鏈技術(一)--原始碼編譯比特幣

寫在開始之前,為什麼你一定要學習區塊鏈技術? 技術的變革和迭代一直在飛速發展中,作為有著15年程式開發經驗的我,常常在思考現在的我們到底改如何做,到底應該學習些什麼,才能跟上新的時代變革,保持自身的競爭力,並且能為這個世界帶來更好的改變呢? 答案是,學習

OpenCV安裝流程及原始碼編譯方法 + 配置VS

本篇文章記錄了安裝OpenCV 3.4.2及配置VS2017的方法,以及利用CMake從原始碼編譯適用於老版本VS2013的OpenCV 3.4.2的編譯及配置流程。本文也可以作為其他OpenCV及VS版本安裝配置方法的參考。 1 安裝OpenCV 3.4.2

原始碼編譯TensorFlow CPU版本

1 安裝Python3 的依賴 sudo apt-get install python3-numpy python3-dev python3-pip python3-wheel 2從原始碼安裝Bazel sudo apt-get install ope

Linux 原始碼編譯安裝 OpenSSH

https://blog.csdn.net/bytxl/article/details/46639073   Linux 從原始碼編譯安裝 OpenSSH以及各問題解決 2015年06月25日 17:37:49 by

Ubuntu16.04 原始碼編譯LLVM+Clang

最近在安裝一個Vim自動補全外掛——YouCompleteMe,這個外掛可以根據語義補全,因此需要Clang這個庫,不過LLVM的官網並沒有提供Ubuntu的預編譯二進位制版本,所以需要自己從原始

原始碼編譯cef-chromium的正確步驟

之前編譯過cef-chromium的原始碼,但是找不到之前的原始碼工程了。幸好壓縮原始碼還存在電腦裡。 現在又要編譯一下,因為需要定製自己需要的功能,這裡就把編譯過程記錄一下,以免以後還會遇到,也分享給需要的讀者。 下載cef-chromium的原始碼需要到google網站

Qt Creator在編譯與安裝的方法

從QT官方網站上可以發現,提供的Qt Creator只有x86版的,不支援mips。下面這篇文章轉載自龍芯論壇,希望對大家有所幫助。他寫的還不是很具體,我也正在研究中。歡迎共同交流qtcreator1.1依賴於qt-4.5.1所以compile qtcreator1.1之前必須compile qt-4.5.1

Linux 原始碼編譯安裝 OpenSSH以及各問題解決

簡單的說 OpenSSH 是一組安全遠端的連線工具,主要包括了幾個部份:ssh、sshd、scp、sftp、ssh-keygen、ssh-agent、ssh-add。OpenSSH 安裝配置比較複雜,難點在配置,特別是在 VPS 中,配置不當就完全無法連結 VPS 了。

原始碼編譯OSG

Windows 下: 2。使用CMake工具編譯OSG。     1)把CMakeLists.txt 拖放到CMake軟體的GUI介面上,可以選擇更改安裝路徑:"Where to build the binaries"。該路徑是OSG的初始編譯路徑。     2)點選 '

原始碼編譯docker (moby)

下面是從原始碼編譯最新(2018-03-27)的 docker/cli 和 moby 的詳細過程第1步     安裝 ubuntu 16.04下載最新的 ubuntu-16.04.4-desktop-amd64.iso 安裝後# cat /etc/os-release NAM

【指導】原始碼編譯安裝Git-Ubuntu

1 下載原始碼包 2 編譯安裝Git 1)安裝編譯原始碼包的工具: $sudo apt-get installlibcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev 2)展開原始碼包,進入: $t

OpenWRT編譯——原始碼到韌體

接觸OpenWRT一年時間,大部分都在編譯韌體、刷機,遇到過不少問題。這裡記錄下以前摸索的步驟。 op編譯過程的wiki:https://wiki.openwrt.org/zh-cn/doc/howto/buildroot.exigence 以下步驟的操作環境為64位的Ub