Boost 庫(kù)裁剪及其應(yīng)用

轉(zhuǎn)載自我的博客:Boost 庫(kù)裁剪及其應(yīng)用


STL 全稱“標(biāo)準(zhǔn)模板庫(kù)(Standard Template Library)”,其實(shí)它是一套標(biāo)準(zhǔn),可能有不同的實(shí)現(xiàn),它是 C++ 的“標(biāo)準(zhǔn)庫(kù)”。Boost 則是一個(gè) C++ 庫(kù),被稱為“C++ 準(zhǔn)標(biāo)準(zhǔn)庫(kù)”。

Boost 庫(kù)涵蓋的范圍極廣,有字符串和文本處理相關(guān)子庫(kù)比如 format 庫(kù)和 regexp 庫(kù),有容器相關(guān)子庫(kù)比如 variant 庫(kù)(和 Qt 的 QVariant 有得一拼),有迭代器子庫(kù)比如 tokenizer 庫(kù)(可以把字符進(jìn)行 tokenize),還有算法、函數(shù)對(duì)象和高階編程相關(guān)子庫(kù)如
functional 庫(kù)、lambda 庫(kù)和 signal 庫(kù),還有泛型編程、模板編程子庫(kù)如 call traits、mpl,還有并發(fā)編程相關(guān)的 thread 庫(kù),等等等等。

Boost 是如此強(qiáng)大,毫無(wú)疑問(wèn)它也很大。Windows 上安裝 boost 需要占用 2G+ 的空間,編譯配置起來(lái)也十分麻煩。

本文討論的是如何不配置 boost 庫(kù)而使用 boost 庫(kù)。

解決方案用一句話說(shuō)就是:

裁剪 boost 庫(kù),并在項(xiàng)目中內(nèi)嵌 boost 源碼,使項(xiàng)目脫離對(duì) boost 庫(kù)的依賴。

一個(gè)例子說(shuō)明 boost 庫(kù)裁剪的意義

或許你還是不明白 boost 庫(kù)裁剪到底是啥意思,那我們一起來(lái)跑一個(gè)例子。以我的 cmake-templates 里面的一個(gè) boost 代碼為例,源碼只有一個(gè) main.cpp,里面只有如下幾行:

#include <cstdio>
#include <boost/date_time/posix_time/posix_time_types.hpp>

int main( void  )
{
    namespace pt = boost::posix_time;
    pt::ptime now = pt::second_clock::local_time();

    printf( "%s\t->\t%04d-%02d-%02d %02d:%02d:%02d\n"
          , "date '+%Y-%m-%d %H:%M:%S'"
          , (int)now.date().year()
          , (int)now.date().month()
          , (int)now.date().day()
          , (int)now.time_of_day().hours()
          , (int)now.time_of_day().minutes()
          , (int)now.time_of_day().seconds() );

    return 0;
}

程序運(yùn)行輸出大概是:

date '+%Y-%m-%d %H:%M:%S'        ->        2016-07-11 19:33:19

這 20 行不到的代碼,展示了 Linux 系統(tǒng)下一個(gè)常用指令 date 輸出當(dāng)前時(shí)間的效果(相當(dāng)于命令行下輸入 date '+%Y-%m-%d %H:%M:%S')。

如果你的系統(tǒng)配置了 Boost,那就到上面的鏈接下載源碼,進(jìn)入 boost 文件夾,這里一共有三個(gè)文件:一個(gè) main.cpp、一個(gè) CMakeLists.txt,一個(gè) README 說(shuō)明文檔。如果你不知道如何使用 CMake 生成 VS 工程,可以先看我以前寫的教程:HOWTO: Win + CMake + Visual Studio 2010 · Issue #1 · district10/cmake-templates

但要運(yùn)行這個(gè)程序并不容易,尤其是在一切都要手工的 Windows 系統(tǒng)上:你必須自己去下載合適的 boost 版本,設(shè)定一些環(huán)境變量。
在 Linux 下則比較簡(jiǎn)單,只要三步(先下載源碼,并 cd 到源碼目錄):

sudo apt-get install -y libboost-all-dev cmake
mkdir build && cd build
cmake .. && make && ./BOOST

你不禁感慨,為了運(yùn)行一個(gè) 20 行不到的小程序,居然要手工安裝兩三個(gè) G 的 boost 庫(kù)!

這時(shí)候 boost 庫(kù)的裁剪,就顯得尤為重要了。我們不希望拿到代碼的人還要費(fèi)時(shí)間去配置 boost 庫(kù),我們也不希望自己的代碼要十分小心地,才能跑起來(lái)。我們要讓自己的代碼不論什么情況都能迅速地跑起來(lái)!下面我們來(lái)看看剛才那 20 行代碼,加上裁剪過(guò)的 boost 庫(kù)源碼,一起“發(fā)行”的效果:district10/bcp-example-1: An exmaple to show how to use bcp.。

我們裁剪后的 boost 庫(kù),頭文件大概有 3.18 MB,cpp 文件有兩個(gè)約 11 KB??瓷先ネΥ?,但是壓縮完其實(shí)就 213 KB!拿到這份代碼,首先解壓 include.zip 到當(dāng)前文件夾,然后運(yùn)行 cmake 生成 VS 工程(或者 Linux 上的 makefile 工程),然后編譯、運(yùn)行。完全不需要再管那煩心的 boost 庫(kù)的配置了!

我想你一定能把這個(gè)程序跑起來(lái)的。無(wú)論你用什么操作系統(tǒng),用什么編譯器。

運(yùn)行起來(lái)更省心,這就是 boost 庫(kù)裁剪的意義。

我要怎么裁剪出自己需要的部分?

我們來(lái)深究一下怎么拿到上面那 3.18 MB 的頭文件,11 KB 的 cpp 文件。

首先,下載 Boost 庫(kù)源碼,你可以去 官網(wǎng),也可以用我的備份:http://whudoc.qiniudn.com/2016/boost_1_58_0_headers_sources.7z(37.6 MB)。我們只需要官方 release 的源碼里的 boostlibs 文件夾下的東西,所以我建議你下載我的備份。因?yàn)樗娴男『芏?,下載起來(lái)也很快。而且里面還打包了用于提取 boost 源碼的工具 bcp[1]。

然后,解壓下載到的壓縮包,進(jìn)入源碼文件夾,新建一個(gè)文件夾,比如叫 output,然后在當(dāng)前窗口打開命令行,輸入 ./bcp.exe boost/date_time/posix_time/posix_time_types.hpp output,這里 "./bcp.exe" 是我們的裁剪工具,"boost/date_time/posix_time/posix_time_types.hpp" 是我們自己項(xiàng)目中用到的 boost 頭文件,如果有多個(gè)頭文件,用空格隔開,把它們都敲進(jìn)命令行。[2]最后的 "output" 是輸出文件夾。

在 cmake 里,這個(gè)過(guò)程大概是 1)在源碼根目錄新建 include 文件夾,在根目錄的 CMakeLists.txt 加上 include_directories( ${CMAKE_SOURCE_DIR} );2)新建 libs 文件夾,把裁剪出來(lái)的 cpp 文件放到這個(gè)文件下的 MiniBoost 文件加下,然后參考 district10/bcp-example-1/libs 寫好 CMakeLists 文件,再到根目錄的 CMakeLists 文件加上 add_subdirectory( libs);3)將裁剪出來(lái)的 miniboost 鏈接到我們的二進(jìn)制:target_link_libraries( ${PROJECT_NAME} MiniBoost )

你可以仔細(xì)對(duì)比看看鏈接系統(tǒng)安裝的 Boost 庫(kù)和使用自帶的裁剪后的 Boost 庫(kù)(我把它稱為 MiniBoost)兩者的區(qū)別和聯(lián)系,再一次,我們?cè)创a鏈接貼在這里:

哦對(duì),一個(gè)需要注意的地方是,提取出來(lái)的頭文件里,boost/config/auto_link.hpp 里的內(nèi)容最好刪掉,不然在 Windows 平臺(tái)上,boost 會(huì)嘗試自動(dòng)鏈接。所以我通常把這個(gè)文件內(nèi)容清空。

更多的實(shí)踐

上面那只是一個(gè)很小的例子。下面是裁剪 boost 庫(kù)的實(shí)際應(yīng)用,這里我舉兩個(gè)有意思的例子。

第一個(gè)叫 kaguya,是一個(gè) lua 腳本語(yǔ)言的 C++ 綁定。這個(gè)庫(kù)很有意思的是,如果你的編譯器支持 C++11 的幾個(gè)特定特性,它是不依賴于 boost 庫(kù)的(但依賴了 lua 庫(kù));如果你的編譯器對(duì) C++11 特性支持得不夠,它就用 boost 庫(kù)來(lái)做補(bǔ)充。

我 fork 了這個(gè) repo,先給它把 lua 源碼打包了進(jìn)去,這樣你就不用安裝、編譯、配置 lua 也能運(yùn)行 kaguya 了,又把 boost 庫(kù)打包內(nèi)嵌進(jìn)去,這樣,你也不必要自己配置 boost 庫(kù),或者使用一個(gè)支持 C++11 的編譯器了(對(duì)于 windows 系統(tǒng)來(lái)說(shuō),也就是你用 VS2010,VS2013 就可以,不必要安裝 VS2015)。

這是我的 fork 的 standalone 分支:4ker/kaguya at standalone。相信你一定能很快把它跑起來(lái)。

第二個(gè)叫 bcp,就是我們用來(lái)裁剪 boost 的工具。Boost 源碼里有 bcp 這個(gè)工具的源碼,但是編譯起來(lái)真是巨麻煩!官方的源碼在這里 boostorg/bcp: Boost.org bcp module,你試試能跑起來(lái)嗎?

這是我修改后的源碼:district10/cmake-bcp: Build Boost bcp via CMake/CMakeLists.txt,很容易就能運(yùn)行起來(lái)。里面有說(shuō)明文檔(其實(shí)就是先 cmakemake)和一些其他說(shuō)明。

用 bcp 來(lái)生成一個(gè)單獨(dú)的(standalone)bcp 源碼,生成 bcp。是不是和編譯器 “自舉” 的概念不謀而合?~


refs and see also


  1. 打包里包含一個(gè) Windows x64 二進(jìn)制 bcp.exe,一個(gè) Linux x64 二進(jìn)制 bcp_standalone_linux,如果你的系統(tǒng)是 32 位,或者是別的操作系統(tǒng)什么的。你就要自己去編譯 bcp 二進(jìn)制。源碼在 district10/cmake-bcp: Build Boost bcp
    via CMake/CMakeLists.txt
    。編譯很簡(jiǎn)單,你所需要的只是一個(gè) c++ 編譯器和一點(diǎn)點(diǎn)耐心。如果你執(zhí)意要用官方的下載,這里是裁剪工具 bcp 的執(zhí)行文件:1)Windows: http://whudoc.qiniudn.com/2016/bcp_standalone.exe (561 KB);2)Linux: http://whudoc.qiniudn.com/2016/bcp_standalone_linux (917 KB)。 ?

  2. 我建議你寫一個(gè)腳本文件。很快,output 文件夾下出現(xiàn)了 boost 文件夾和 libs 文件夾。前者是提取出來(lái)的頭文件,后者是出來(lái)的 cpp 文件。把這些文件集成到自己的項(xiàng)目中就可以了。集成進(jìn)來(lái)后,我們的源碼應(yīng)當(dāng)能 include 那些提取出來(lái)的頭文件,我們的二進(jìn)制應(yīng)當(dāng)能夠鏈接那些提取出來(lái)的 cpp 文件生成的庫(kù)文件(或者和我們的 cpp 文件一起編譯二進(jìn)制,也可以)。 ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容