Redhat環境下編譯安裝Google Bazel


Redhat環境下編譯安裝bazel##

作者:Jack47

目前Google Bazel沒有提供各個操作系統下的二進制安裝包,只提供源代碼,需要我們自己編譯安裝,詳情可以見我翻譯的中文版Google Bazel FAQ。Google Bazel官方安裝文檔在這里,里面只介紹了在Ubuntu(14.04,14.10)和Mac OS X下的編譯安裝。而我們公司的構建機器是Redhat Linux系列,在編譯Bazel的時候遇到了很多問題,在這里跟大家分享下解決思路和方法,為了照顧像作者這樣的小白,文章寫的稍微有點啰嗦,見諒。

編譯##

我編譯Bazel的系統環境配置是:

系統環境###

操作系統:Redhat Enterprise 5.7
內核版本:2.6.32-220
gcc:	4.1.2	

后來發現需要JDK 1.8, 支持C++ 11的編譯器才可以順利編譯Bazel,下文會介紹如何安裝這些依賴。

下載代碼###

$ git clone https://github.com/google/bazel/

編譯###

直接執行./compile.sh腳本來編譯Bazel

$ ./compile.sh

報錯:

Package libarchive was not found in the pkg-config search path.
Perhaps you should add the directory containing 'libarchive.pc' to the PKG_CONFIG_PATH environment variable
No package 'libarchive' found`

可以看到提示是 libarchive 包不在PKG_CONFIG_PATH下。利用Redhat Linux下的包管理工具yum查看到底安裝了這個包沒有:

$ rpm -qa | grep libarchive

發現就沒有安裝這個包,於是進行安裝。libarchive是一個支持多種格式的檔案和壓縮的庫。

安裝libarchive###

從官方網站下載最新版本的 libarchive :

$ wget http://libarchive.org/downloads/libarchive-3.1.2.tar.gz

解壓縮得到源碼:

$ gunzip libarchive-3.1.2.tar.gz
$ tar libarchive-3.1.2.tar

然后通過查看libarchive-3.1.2目錄下的 INSTALL 文件,找到編譯安裝方法:

編譯:

$ ./configure
$ make

安裝[需要管理員權限]:

$ sudo make install

此時再次執行Bazel的編譯腳本:

$ ./compile.sh

發現還是跟沒安裝之前報一樣的錯誤:

Package libarchive was not found in the pkg-config search path.
Perhaps you should add the directory containing 'libarchive.pc' to the PKG_CONFIG_PATH environment variable
No package 'libarchive' found

提示是說在pkg-config的搜索路徑下找不到 libarchive 這個包,需要把libarchive.pc這個文件的路徑添加到PKG_CONFIG_PATH這個環境變量里。回過頭查看 libarchive 的安裝過程中打印出的信息,可以看到:

/usr/bin/install -c -m 644 build/pkgconfig/libarchive.pc '/usr/local/lib/pkgconfig

發現libarchive.pc是安裝到了 /usr/local/lib/pkgconfig 目錄下。
於是設定環境變量PKG_CONFIG_PATH:

$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH

再編譯Bazel,發現又出錯了:

JDK version is lower than 1.8, please set $JAVA_HOME.

是jdk的版本不對,看了一下當前環境下的java版本:

$ java -version
java version "1.6.0_20"

安裝jdk 1.8###

從Oracle官網下載jdk1.8, 由於我的機器是x86架構,64位機器,於是下載這個版本。如果直接 wget 會失敗,需要在網頁里同意License才可以下載,所以從瀏覽器中下載jdk1.8。如果是遠程登錄到服務器,可以在本地下載,然后使用scp命令上傳到服務器:

$scp jdk-8u45-linux-x64.rpm usename@hostname:~/

安裝####

$ sudo rpm -ivh jdk-8u45-linux-x64.rpm

bazel需要通過環境變量$JAVA_HOME來得到jdk的安裝路徑。而jdk rpm安裝包不會自動幫助我們設置環境變量JAVA_HOME,需要我們自己設置。

設置JAVA_HOME####

很奇怪,安裝后包名稱變了,使用如下rpm命令查看安裝后jdk 1.8的包名稱:

$ rpm -qa | grep jdk
jdk1.8.0_45-1.8.0_45-fcs

查看這個包中文件都安裝到哪些路徑下了:

$ rpm -ql jdk1.8.0_45-1.8.0_45-fcs

發現安裝到/usr/java/jdk1.8.0_45/這個目錄下去了。

於是設置JAVA_HOME:

$ export JAVA_HOME=/usr/java/jdk1.8.0_45/

查看JAVA_HOME是否設置正確:

$ echo $JAVA_HOME
/usr/java/jdk1.8.0_45/

可以看到確實設置成功了。
再次編譯Bazel,終於看到編譯的輸出了:

$ ./compile.sh
Compiling Java stubs for protocol buffers...
Compiling Bazel Java code...
Extracting helper classes for Bazel Java...
Creating libblaze.jar...
Compiling SingleJar tool code...
Extracting helper classes for SingleJar tool...
Creating SingleJar_deploy.jar...
Compiling JavaBuilder tool code...
Extracting helper classes for JavaBuilder tool...
Creating JavaBuilder_deploy.jar...
Compiling client .cc files...
cc1plus: error: unrecognized command line option "-std=c++0x"

看起來是不支持這個選項: "-std=c++0x"。

如何查看到底./compile.sh這個腳本執行了哪些語句,到底是哪條命令失敗了?編輯這個shell腳本,在開頭寫入set命令

set -x

然后再次運行Bazel編譯,此時可以看到 ./compile.sh 腳本的每一行命令。最終出錯誤的命令是:

g++ -I. -std=c++0x -c '-DBLAZE_JAVA_CPU="k8"' -DBLAZE_OPENSOURCE=1 -o output/objs/blaze_startup_options.cc.o src/main/cpp/blaze_startup_options.cc

看起來是 g++ 不支持 c++0x標准。上網搜了一下,發現gcc 4.6以上的版本才支持 C++ 11。怎么在Redhat Linux下安裝更高版本的gcc呢?

上網搜索后,發現Red Hat Enterprise Linux下有開發工具套件 devtoolset,可以方便的安裝各個版本的gcc,而且是可以多個版本並存的,方便的解決了我等小白在源碼編譯、安裝gcc時可能出現的問題。但官方的那一套東西,需要付費,而公司的這個Red Hat版本不支持。后來發現Redhat Linux的社區版本--Centos下有人已經構建好了Redhat Developer Toolset的相關rpm包,參照此文來進行devtoolset的安裝。

$ sudo wget http://people.centos.org/tru/devtools-2/devtools-2.repo -O /etc/yum.repos.d/devtools-2.repo
$sudo yum install devtoolset-2-gcc  devtoolset-2-binutils devtoolset-2-gcc-c++

安裝完成后,使用scl命令在shell環境中啟用devltoolset-2
$ scl enable devtoolset-2 bash

然后驗證此時gcc的版本:

$ gcc -v

可以看到此時已經是gcc 4.8.2版本了。有興趣的同學可以查看一下enable這個腳本的實現,非常簡潔,會讓你收獲一些東西,路徑是:/opt/rh/devtoolset-2/

再次編譯Bazel,發現又出錯了:

src/main/tools/namespace-sandbox.c: In function ‘main’:
src/main/tools/namespace-sandbox.c:140:36: error: ‘CLONE_NEWUTS’ undeclared (first use in this function)    CHECK_CALL(unshare(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER));

在網上看到unshare這個函數的CLONE_NEWUTS參數在我的這個系統版本里2.6.32 里面應該是已經支持了得。后來發信給bazel郵件組求助,他們說是我得系統內核版本太老了,不支持namespace,讓我把namespace-sandbox的編譯去掉,不影響正常功能。

於是注釋掉,sandbox的編譯:

#if [[ $PLATFORM == "linux" ]]; then
#  log "Compiling sandbox..."
#  "${CC}" -o output/namespace-sandbox -std=c99 src/	main/tools/namespace-sandbox.c
#fi`

再次編譯,編譯終於成功了!
Build successful! Binary is here: /home/jack47/bazel/output/bazel

明天如果把bug修完了,會更新一篇如何上手bazel的文章,大家周末愉快!

后記:

其實我在搞明白可以簡單的使用devltoolset來安裝高版本的gcc之前,自己源碼編譯,安裝gcc后,遇到了一些稀奇古怪的錯誤,比如系統頭文件里的某些宏沒有定義,libstdc++中找不到GLIBCXX_3.4.20等,還是花了好幾天時間在上面的。所以讀者朋友們,你們是幸福的啊,按照我的這篇文章,半天時間怎么着也能編譯出Bazel來。

做個調查,C++程序員,你能分清楚這幾個名詞之間的區別和聯系嗎?不清楚的默默給我點下文章右下角的“推薦”按鈕吧,哈哈。其實我寫這篇文章之前也不太清楚glibc和libstdc++這兩個東東的:)

GCC
glibc
libstdc++

參考資料:

  1. Redhat Developer toolset的介紹:很有意思,解釋了這套工具解決的問題,背后的原理等
  2. Google軟件構建工具Bazel原理及使用方法介紹


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM