轉(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 的源碼里的 boost 和 libs 文件夾下的東西,所以我建議你下載我的備份。因?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鏈接貼在這里:
- cmake-templates/boost at master · district10/cmake-templates
- district10/bcp-example-1: An exmaple to show how to use bcp.
哦對(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í)就是先 cmake 再 make)和一些其他說(shuō)明。
用 bcp 來(lái)生成一個(gè)單獨(dú)的(standalone)bcp 源碼,生成 bcp。是不是和編譯器 “自舉” 的概念不謀而合?~
refs and see also
- Boost 簡(jiǎn)介 - wangkangluo1 - 博客園{.featured}
- Posix Time - 1.53.0
- BCP - 1.61.0
- district10/bcp at standalone{.featured}
- 使用 bcp 給 boost 瘦身 - langresser 的專欄 - 博客頻道 - CSDN.NET
-
打包里包含一個(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)。 ? -
我建議你寫一個(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)制,也可以)。 ?