2015年9月16日 星期三

包rpm的骯髒事

最近在自己包rpm包,CentOS與Fedora的openssl rpm包因為某些版權問題把bitcoin所需要的橢圓曲線拿掉了,因此必須自己compile一個openssl給bitcoin使用。

無奈的是要讓其他人自己在configure下參數來找到我們自己編的openssl實在是太麻煩了,只好想辦法讓bitcoin在configure與compile時不下任何參數也能避開系統的openssl,而是用到我們包的版本。

我們的server清一色都是CentOS 7,因此團隊裡的大大們覺得乾脆我們自己包一個好了,然後就是由我來負責Orz。

首先,rpm specfile雖然簡單明瞭,但在很容易不小心把沒列在file section中的file install到BUILD_ROOT,這樣會造成錯誤。install section是在整個包的過程最後一步,openssl build一次又需要5~10分鐘,各種低級的error就浪費了我很多時間。

最後終於包好了,要怎麼讓bitcoin找到我們自己compile的libssl.so與libcrypto.so呢?
(以下方法滿髒的但小弟是新手又有deadline只好出此下策)
  1. /etc/profile中加入export PKG_CONFIG_PATH=/usr/local/openssl/lib ,讓每個使用者登入時都會設好PKG_CONFIG_PATH,這樣在configure時autoconf會找到我們要的SSL_CFLAGS和SSL_LD_FLAGS並產生好Makefile。
  2. 這時去make還是會發現我們仍是抓到系統的.so,真的很奇怪。打開verbose模式 make V=1 才發現需要用到openssl的某幾條gcc指令竟然還有幾個-L/usr/lib之類的linker path參數放在我們的-L/usr/local/openssl/lib之前!
  3. 最後我們只好在/etc/profile中又加上了export CXX="c++ -L/usr/local/openssl/lib" 這樣就保證了我們的路徑比系統的還優先找到XDD
此時,我們已經能抓到正確的openssl來編了。然而一執行bitcoind …
 ./bitcoind: /usr/lib/libcrypto.so: no version information available ...
去google才發現若執行時ld.so發現抓到的.so版本比編譯時的.so還舊,就會報這個error。

此時才想到忘記把.so的path加入ld.so.cache。在/etc/ld.so.conf.d/下創一個檔案並把路徑加入後,再執行
 $ ldconfig
讓路徑load至cache中就完成了!
最後,感謝強者lantw44的指導阿!

2015年8月21日 星期五

Cross Initialization

今天和朋友聊到了會發生在Switch statement與goto statement的Cross Initialization問題。
switch (ch) {
    case 1:
        int jval = 1;
        break;
    case 2:
        jval = 2;
}
compile時會出現

error: crosses initialization of 'int jval'

然而只要改成
switch (ch) {
    case 1:
        int jval;
        break;
    case 2:
        jval = 2;
}
就不會出現error了
或者是使用block來限制變數的scope也可解決這問題。
switch (ch) {
    case 1: {
        int jval;
        break;
    }
    case 2: {
        jval = 2;
    }
}
去google了一下,stackoverflow有許多篇在介紹這個問題,似乎是compiler不允許在同一個scope中jump over initialization.

ISO C++ ‘03 6.7/3 有規範
It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer (8.5)

還需要弄懂的是為什麼只有initialization被禁止(不只有explicit的使用initializer來init,default init和value init也都不行),但是卻可以做definition與assignment。