這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
源碼的編譯-Why?
Fabric源碼的編譯是建立在已經基本掌握了Fabric的部分模組或者很多模組的代碼的基礎上.但是為什麼要編譯Fabric的源碼呢,大神們不是已經寫好了Fabric這個項目架構並編譯好了嗎,拿來用不就好了嗎?
1.部署Fabric網路的docker容器是通過編譯Fabric裡的peer/Order/fabric-ca/模組的代碼形docker鏡像建立的.固有的已編譯好的鏡像讓我們要開發的系統也禁錮住了,每個要開發的應用系統都有自身的特點,我們需要通過編譯Fabric的改寫的模組代碼產生應用系統所需要的鏡像.比如說,阿里通過基於OpenJDK定製的TaobaoVM,也是自身編譯的軟體開發包.
2.編譯Fabric源碼可以驗證自己的想法,當閱讀Fabric源碼時候,代碼如何的運行只是通過我們理論上的猜想,通過實際的編譯代碼可以驗證我們的猜想.
3.定位錯誤,修改bug.源碼的編譯是建立在Fabric的源碼的閱讀上的,當系統啟動並執行日誌裡出現錯誤時,根據錯誤提示能定位到源碼中的錯誤點,根據源碼能修改bug.
準備工作
1.編譯環境的安裝,go的安裝,Fabric的源碼下載,在Fabric的源碼的閱讀一篇中講述了.
2.安裝其他必要的組件.
假設GOPATH為/home/gopath該檔案夾下有兩個檔案夾:src用於存放Fabric源碼.bin用於存放go編譯好的可執行檔.
2.1安裝go的包管理工具gopm.
export GOPATH=/home/gopath
go get -u github.com/gpmgo/gopm
/home/gopath/bin目錄下將有gopm,go get是下載和編譯的意思
2.2通過 gopm安裝 goimports.(go代碼格式化工具,自動修正import的package)
export GOPATH=/home/gopath
gopm get -g -d golang.org/x/tools/cmd/goimports
再使用 go install 安裝 goimports
go install golang.org/x/tools/cmd/goimports
/home/gopath/bin目錄下將有goimports
2.3安裝 gocov(go的單元測試覆蓋率檢查工具)
GOPATH=/home/gopath
gopm get -g -d golang.org/x/tools/cover
gopm get -g -d github.com/axw/gocov/gocov
go install github.com/axw/gocov/gocov
/home/gopath/bin目錄下將有gocov
2.4安裝 gocov-xml
GOPATH=/home/gopath
gopm get -g -d github.com/AlekSi/gocov-xml
go install github.com/AlekSi/gocov-xml
/home/gopath/bin目錄下將有 gocov-xml
2.5安裝其他組件
yum install -y gcc libtool libltdl-dev libtool-ltdl-devel openssl
3.Makefile檔案的文法理解.
Fabric的源碼鏡像是通過make按照Makefile中檔案的編譯規則來編譯鏡像的.
簡要介紹Makefile的文法規則.
3.1 Makefile檔案的一般形式.
target ... : prerequisites ...
command
...
...
其中...表示多個.
target是一個目標檔案,可以是Object File,也可以是執行檔案。也可以是一個標籤(Label),make就不會自動去找lable後的檔案的依賴性,也就不會自動執行其後所定義的命令。 需要明確使用make Label。才會執行命令。
prerequisites是要產生target所需要的檔案或是目標。
command也就是make需要執行的命令。(任意的Shell命令)
說明,上面的一般形式是一個檔案的依賴關係.target這一個或多個的目標檔案依賴於prerequisites中的檔案,其建置規則定義在command中。特別的,prerequisites中如果有一個以上的檔案比target檔案要新的話,command所定義的命令就會被執行。這就是Makefile的規則。
3.2依賴關係的實質上就是說明了目標檔案是由哪些檔案產生的,換言之,目標檔案是哪些檔案更新的。
3.3偽目標使用方法的終端編譯命令是make lable,避免當前檔案夾下也有檔案叫lable。
偽目標eg: .PHONY lable.PHONY避免同名 lable: rm *.o
終端使用make labe,執行的操作是刪除所有的.o檔案.
一般形式的eg : main.o : main.c defs.h cc -c main.c #make最後產生 main.o檔案依賴於main.c defs.h兩個檔案,cc -c main.c執行可執行檔main.c進行編譯.
3.4 Makefile中的第一個目標會被作為其預設目標。
How
1.進入Fabric源碼目錄/home/gopath/src/hyperledger/fabric.並添加gopath的環境變數,一定要加.
export GOPATH= /home/gopath
sudo su
2.編譯產生 protoc-gen-go
cd $GOPATH
gopm get -g -d github.com/golang/protobuf/protoc-gen-go
go install github.com/golang/protobuf/protoc-gen-go
/home/gopath/bin出現protoc-gen-go執行檔案
3.根據Fabric源碼目錄下的Makefile檔案中的說明.在源碼目錄下開啟終端,根據1中方框的targets偽目標,選擇你要編譯的target,執行命令make peer/all/orderer...
執行make命令後會在當前檔案夾下產生一個build檔案夾.編譯後的鏡像或者可運行工具都是在這個檔案夾裡找.
編譯peer模組的程式碼範例
說明:peer網路節點啟動時啟動並執行命令是peer node start
,實際上Fabric網路節點的peer docker容器中執行的便是通過Fabric源碼編譯的peer可執行檔來操作peer下的命令.本例中在peer節點下通過修改代碼並編譯來添加test命令.
1.在/home/gopath/src/hyperledger/fabric/peer下添加test包.並在test包下建立test.go檔案.
package testimport ( "github.com/hyperledger/fabric/common/flogging" "github.com/spf13/cobra")var logger = flogging.MustGetLogger("testCommand")func Cmd() *cobra.Command { return testCommond}var testCommond = &cobra.Command{ Use: "test", Short: "test the node.", Long: `test a node that interacts with the network.`, Run: func(cmd *cobra.Command, args []string) { logger.Info("Build test by JinaWenJun----------------------") },}
2.在/home/gopath/src/hyperledger/fabric/peer下的main.go檔案中添加
mainCmd.AddCommand(version.Cmd()) mainCmd.AddCommand(node.Cmd()) mainCmd.AddCommand(chaincode.Cmd(nil)) mainCmd.AddCommand(clilogging.Cmd(nil)) mainCmd.AddCommand(channel.Cmd(nil)) //添加的另外一個test命令,並在前面匯入包"github.com/hyperledger/fabric/peer/test" mainCmd.AddCommand(test.Cmd())
3.在源碼目錄下開啟終端進行編譯 make peer
,在/home/gopath/src/hyperledger/fabric/build/bin下將會產生可執行檔peer.將該檔案拷貝到/home/gopath/bin下測試新添加的test 命令.(類比在peer docker的容器下peer命令的執行).
4.開啟終端,執行peer test
遇到的問題解決方案
1.終端執行make 命令時,出現沒有那個檔案或目錄,
方法:需要在終端下添加環境變數,執行
export GOPATH= /home/gopath
2.當因為網速終端卡住時,需要將Makefile檔案中的curl部分刪除.手動下載相應的檔案chaintool目錄/build/bin下面.
3.當出現檔案找不到或者命令找不到,
方法:終端執行下面兩條命令,將命令複製進去
cp $GOPATH/bin/protoc-gen-go $GOPATH/src/github.com/hyperledger/fabric/build/docker/gotools/bin/
cp $GOPATH/bin/gocov $GOPATH/src/github.com/hyperledger/fabric/build/docker/gotools/bin/
4.當終端make peer出現錯誤時候.
方法:根據錯誤提示
core/chaincode/ccproviderimpl.go:20:2:
不能找到context.進入到相應的檔案ccproviderimpl.go修改.
如果在出現提示哪裡不能找到"context"到指定的檔案下按照上述形式修改即可.
編譯成功:
相應的 build/bin/檔案夾下有peer可執行檔.