Mac 从Makefile 编译 Rocksdb 源码的一些注意事项
文章目錄
- 前言
- Makefile 編譯流程
- 1. 平臺(tái)變量/環(huán)境變量的初始化。
- 2. 編譯需要的源碼文件變量初始化。
- 3. include 目錄的設(shè)置。
- 4. 編譯的執(zhí)行邏輯。
- 問(wèn)題記錄1:可能的打包命令`ar` 失效問(wèn)題
- 5. 執(zhí)行具體的編譯指令
- 問(wèn)題記錄2: jar 包編譯
前言
最近在Mac 本地編譯Rocksdb 過(guò)程中踩過(guò)不少坑,特此做一個(gè)記錄,希望能幫助到大家。
Rocksdb 源碼的本地編譯需求來(lái)自于 Rocksdb 使用者對(duì)本地開(kāi)發(fā)/測(cè)試環(huán)境的依賴,尤其是Java 開(kāi)發(fā)的同學(xué)依賴更強(qiáng),因?yàn)榛镜拈_(kāi)發(fā)和調(diào)試在本地的 IDEA 會(huì)方便無(wú)數(shù)倍。而且,RocksJava 的功能也會(huì)隨著社區(qū)版本迭代,所以使用過(guò)程中需要編譯不同版本的的 Rocksdb 的jar包。
本地編譯原生主要是兩種,一種是Makefile,另一種是CMakeList.txt,還有一種是bazel方式,官方也提供了TARGET文件。當(dāng)然,用bazel從源碼編譯可能會(huì)更方便一些,符號(hào)信息也會(huì)更全一些,這里就看大家自己的選擇了。
此外, 本篇可能記錄的是我遇到的一些坑,但不代表大家就一定能遇到,或者說(shuō)大家遇到的我不一定能夠遇到。所以整體提供的解決方法以及案例可能更偏向于方法論,就是告訴大家實(shí)際的編譯流程,以及這個(gè)過(guò)程中的source文件,include文件,依賴庫(kù) 都是在哪里進(jìn)行初始化的,以及可以在哪里進(jìn)行補(bǔ)充,這樣大家有了整個(gè)編譯流程之后就能夠根據(jù)自己的環(huán)境快速解決對(duì)應(yīng)的問(wèn)題。
描述之前,可以先做一些方便大家閱讀makefile的準(zhǔn)備工作,我這里使用的是ctags + vim。
好處是rocksdb 直接提供ctags的生成目錄,在Makefile 所在目錄執(zhí)行命令make ctags -j就好了。可能需要大家安裝cscope命令brew install cscope
有了ctags的輔助,我們就可以在Makefile中自由跳轉(zhuǎn)了。
Makefile 編譯流程
1. 平臺(tái)變量/環(huán)境變量的初始化。
Makefile中會(huì)有一些類似 $(PLATFORM) 這樣的外部變量,Makefile中的邏輯大多是根據(jù)這一些外部變量來(lái)判斷自己的編譯行為。比如不同的操作系統(tǒng) 選擇不同的編譯庫(kù)/編譯邏輯,對(duì)系統(tǒng)依賴庫(kù)的初始化設(shè)置。
所有這一些系統(tǒng)變量/環(huán)境變量的初始化都在這個(gè)文件中:
build_tools/build_detect_platform
像基本的系統(tǒng)庫(kù),是否使用fallocate, snappy, zstd等 都是這里面設(shè)置的,還有我們編譯打包的基礎(chǔ)命令$(CC), $(CXX), $(AR) 的初始化也都是在這個(gè)文件中。
也就是說(shuō)make static_lib 這條命令會(huì)先通過(guò) 上面這個(gè)文件進(jìn)行變量的初始化,而如果我們想要外部改變變量,則指定的ROCKSDB_DISABLE_GFLAGS=1 make static_lib -j也都是通過(guò)這個(gè)文件來(lái)生效的。
2. 編譯需要的源碼文件變量初始化。
我們?cè)贛akefile 有一些帶有SOURCE 的關(guān)鍵字,他們一些保存源碼路徑的變量,用來(lái)編譯一些庫(kù)文件。
這個(gè)時(shí)候我們通過(guò)前面說(shuō)的ctags 來(lái)跳轉(zhuǎn)到聲明ctrl + ] ,返回上一個(gè)位置ctrl + o。就能看到這一些初始化的變量是在
src.mk之中。
也就是大家如果想要補(bǔ)充一些自己修改的源碼文件,即可到src.mk之中添加。
而在Makefile中 src.mk 變量被引入的方式是:
include src.mkAM_DEFAULT_VERBOSITY = 0
如果有對(duì)rocksjni 的代碼進(jìn)行修改,則同樣需要將對(duì)應(yīng)的代碼文件補(bǔ)充到src.mk中的JNI_NATIVE_SOURCES變量。
3. include 目錄的設(shè)置。
我們想要設(shè)置一些編譯依賴的頭文件所在目錄,可以在如下集中的一個(gè)地方進(jìn)行設(shè)置:
CFLAGS += $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)
CXXFLAGS += $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) -Woverloaded-virtual -Wnon-virtual-dtor -Wno-missing-field-initializers
也就是說(shuō)如果大家遇到一些依賴庫(kù)的問(wèn)題,即通過(guò)-lxxx這樣的方式解決不了的,則可以直自己從源碼編譯依賴庫(kù),在這里指定include 和 .dylib 所在位置就可以。
4. 編譯的執(zhí)行邏輯。
這個(gè)其實(shí)很簡(jiǎn)單,有了我們的ctags,我們很容易梳理出一個(gè)大體的執(zhí)行流。從make static_lib來(lái)看,最終的成果物是一個(gè)librocksdb.a文件。
如上執(zhí)行目標(biāo)是static_lib,則$(LIBRARY)是實(shí)際的${LIBNAME}.a,也就是我們想要生成librocksdb.a,那就看$(LIBRARY)作為執(zhí)行目標(biāo)的位置。
這里我們就看到了真正生成librocksdb.a執(zhí)行目標(biāo)的位置了,下面的$(AM_V_at) 以及 $(AR)則是提前初始化好的打包命令,而$(LIBOBJECTS)則是要求從源碼文件.cc編譯成.o的文件集LIBOBJECTS = $(LIB_SOURCES:.cc=.o)。
如果再想仔細(xì)追溯每一個(gè)變量的源頭,按照tags 跳轉(zhuǎn)就好了。
問(wèn)題記錄1:可能的打包命令ar 失效問(wèn)題
提一下,在6.6.0版本以前,on Mac的打包命令可能會(huì)失效,因?yàn)?on linux 和 on mac 的初始化AR變量有差異。
所以大家可以在build_tools/build_detect_platform中增加針對(duì)$(AR)的顯式設(shè)置,這樣不論什么時(shí)候$(AR) 變量都是一個(gè)有效的子命令。
if test -z "$AR"; thenif [ -x "$(command -v gcc-ar)" ]; thenAR=gcc-arelif [ -x "$(command -v llvm-ar)" ]; thenAR=llvm-arelseAR=arfifi
5. 執(zhí)行具體的編譯指令
編譯的時(shí)候我們一般會(huì)編譯一些library或者一些測(cè)試工具, 這里簡(jiǎn)單說(shuō)明一下編譯命令。
- 編譯動(dòng)態(tài)庫(kù)/靜態(tài)庫(kù)
make static_lib -j6或者make shared_lib -j6,默認(rèn)不帶任何符號(hào)信息。
如果想要把符號(hào)信息也添加進(jìn)去來(lái)方便調(diào)試,則需要設(shè)置DEBUG_LEVEL=1 make static_lib,會(huì)以 -O2 的方式進(jìn)行編譯,并將一些測(cè)試代碼和符號(hào)信息也編譯到庫(kù)中。 - 編譯rokcsdb 的測(cè)試工具:
DEBUG_LEVEL=0 make db_bench
因?yàn)楣ぞ叩倪\(yùn)行需要一些依賴庫(kù),這里可能需要大家安裝對(duì)應(yīng)的依賴庫(kù)。
gflags,snappy,zstd,zlib,lz4等,安裝可以直接通過(guò)brew install xxx就可以,而像一些fallocate或者jemalloc的依賴問(wèn)題,如果不想安裝,可以通過(guò)ROCKSDB_DISABLE_FALLOCATE=1或者ROCKSDB_DISABLE_JEMALLOC=1來(lái)禁用即可。
編譯完成之后,可以通過(guò)otool -L db_bench這樣的命令來(lái)進(jìn)行測(cè)試。
問(wèn)題記錄2: jar 包編譯
編譯jar包,建議通過(guò) rocksdbjavastatic 來(lái)進(jìn)行編譯,否則一些jni的代碼編譯不進(jìn)去,出來(lái)的jar 包無(wú)法獨(dú)立使用,缺少一些jni的符號(hào)。
編譯java的時(shí)候如果本地shell 環(huán)境沒(méi)有設(shè)置JAVA_HOME,則需要單獨(dú)指定。
- 通過(guò)執(zhí)行
/usr/libexec/java_home來(lái)得到JAVA_HOME的路徑
如果執(zhí)行失敗,則表示沒(méi)有安裝$ /usr/libexec/java_home /Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Homejdk,需要brew search jdk并brew install jdk@xxx安裝指定版本的jdk - 通過(guò) rocksdbjavastatic 編譯的時(shí)候需要 從網(wǎng)絡(luò)上下載 以及 編譯一些壓縮算法,這里建議 單獨(dú)下載好到
Makefile所在目錄。lz4-*.tar.gz . snappy-*.tar.gz . zlib-*.tar.gz . zstd-*.tar.gz . bzip2-*.tar.gz . - 編譯命令則建議通過(guò)
ROCKSDB_DISABLE_JEMALLOC=0 DEBUG_LEVEL=0 JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Home make rocksdbjavastatic -j6進(jìn)行安裝。
編譯完成之后會(huì)在java/target/目錄下生成 jar 包 和 librocksdbjni 的library。ls java/target apidocs rocksdbjni-6.4.6-javadoc.jar classes rocksdbjni-6.4.6-osx.jar librocksdbjni-osx.jnilib rocksdbjni-6.4.6-sources.jar librocksdbjni-osx.jnilib.dSYM test-classes
jar 包的測(cè)試,可以通過(guò)java/samples/src/main/java/RocksDBSample.java 代碼進(jìn)行測(cè)試:
cd java/src
# 1. 編譯測(cè)試代碼
/Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Home/bin/javac -d . -cp \
../target/rocksdbjni-6.4.6-osx.jar:. ../samples/src/main/java/RocksDBSample.java \
-Xlint:deprecation# 2. 運(yùn)行測(cè)試代碼 并指定db-dir
/Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Home/bin/java -cp \
../target/rocksdbjni-6.4.6-osx.jar:. RocksDBSample db-dir
沒(méi)有core 且生成db-dir 目錄,則表示當(dāng)前jar包無(wú)異常。
當(dāng)然,也可以跑一下java的unitest,如果都過(guò)了,那也沒(méi)什么問(wèn)題。
總結(jié)
以上是生活随笔為你收集整理的Mac 从Makefile 编译 Rocksdb 源码的一些注意事项的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 求一个用名字取qq网名。
- 下一篇: 存储引擎 K/V 分离下的index回写