文章目录

  • 前言
  • Makefile 编译流程
    • 1. 平台变量/环境变量的初始化。
    • 2. 编译需要的源码文件变量初始化。
    • 3. include 目录的设置。
    • 4. 编译的执行逻辑。
      • 问题记录1:可能的打包命令`ar` 失效问题
    • 5. 执行具体的编译指令
      • 问题记录2: jar 包编译

前言

最近在Mac 本地编译Rocksdb 过程中踩过不少坑,特此做一个记录,希望能帮助到大家。

Rocksdb 源码的本地编译需求来自于 Rocksdb 使用者对本地开发/测试环境的依赖,尤其是Java 开发的同学依赖更强,因为基本的开发和调试在本地的 IDEA 会方便无数倍。而且,RocksJava 的功能也会随着社区版本迭代,所以使用过程中需要编译不同版本的的 Rocksdb 的jar包。

本地编译原生主要是两种,一种是Makefile,另一种是CMakeList.txt,还有一种是bazel方式,官方也提供了TARGET文件。当然,用bazel从源码编译可能会更方便一些,符号信息也会更全一些,这里就看大家自己的选择了。

此外, 本篇可能记录的是我遇到的一些坑,但不代表大家就一定能遇到,或者说大家遇到的我不一定能够遇到。所以整体提供的解决方法以及案例可能更偏向于方法论,就是告诉大家实际的编译流程,以及这个过程中的source文件,include文件,依赖库 都是在哪里进行初始化的,以及可以在哪里进行补充,这样大家有了整个编译流程之后就能够根据自己的环境快速解决对应的问题。

描述之前,可以先做一些方便大家阅读makefile的准备工作,我这里使用的是ctags + vim。
好处是rocksdb 直接提供ctags的生成目录,在Makefile 所在目录执行命令make ctags -j就好了。可能需要大家安装cscope命令brew install cscope

有了ctags的辅助,我们就可以在Makefile中自由跳转了。

Makefile 编译流程

1. 平台变量/环境变量的初始化。

Makefile中会有一些类似 $(PLATFORM) 这样的外部变量,Makefile中的逻辑大多是根据这一些外部变量来判断自己的编译行为。比如不同的操作系统 选择不同的编译库/编译逻辑,对系统依赖库的初始化设置。
所有这一些系统变量/环境变量的初始化都在这个文件中:
build_tools/build_detect_platform

像基本的系统库,是否使用fallocate, snappy, zstd等 都是这里面设置的,还有我们编译打包的基础命令$(CC), $(CXX), $(AR) 的初始化也都是在这个文件中。

也就是说make static_lib 这条命令会先通过 上面这个文件进行变量的初始化,而如果我们想要外部改变变量,则指定的ROCKSDB_DISABLE_GFLAGS=1 make static_lib -j也都是通过这个文件来生效的。

2. 编译需要的源码文件变量初始化。

我们在Makefile 有一些带有SOURCE 的关键字,他们一些保存源码路径的变量,用来编译一些库文件。

这个时候我们通过前面说的ctags 来跳转到声明ctrl + ] ,返回上一个位置ctrl + o。就能看到这一些初始化的变量是在
src.mk之中。

也就是大家如果想要补充一些自己修改的源码文件,即可到src.mk之中添加。
而在Makefile中 src.mk 变量被引入的方式是:

 include src.mkAM_DEFAULT_VERBOSITY = 0

如果有对rocksjni 的代码进行修改,则同样需要将对应的代码文件补充到src.mk中的JNI_NATIVE_SOURCES变量。

3. include 目录的设置。

我们想要设置一些编译依赖的头文件所在目录,可以在如下集中的一个地方进行设置:

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

也就是说如果大家遇到一些依赖库的问题,即通过-lxxx这样的方式解决不了的,则可以直自己从源码编译依赖库,在这里指定include 和 .dylib 所在位置就可以。

4. 编译的执行逻辑。

这个其实很简单,有了我们的ctags,我们很容易梳理出一个大体的执行流。从make static_lib来看,最终的成果物是一个librocksdb.a文件。

如上执行目标是static_lib,则$(LIBRARY)是实际的${LIBNAME}.a,也就是我们想要生成librocksdb.a,那就看$(LIBRARY)作为执行目标的位置。

这里我们就看到了真正生成librocksdb.a执行目标的位置了,下面的$(AM_V_at) 以及 $(AR)则是提前初始化好的打包命令,而$(LIBOBJECTS)则是要求从源码文件.cc编译成.o的文件集LIBOBJECTS = $(LIB_SOURCES:.cc=.o)

如果再想仔细追溯每一个变量的源头,按照tags 跳转就好了。

问题记录1:可能的打包命令ar 失效问题

提一下,在6.6.0版本以前,on Mac的打包命令可能会失效,因为 on linux 和 on mac 的初始化AR变量有差异。
所以大家可以在build_tools/build_detect_platform中增加针对$(AR)的显式设置,这样不论什么时候$(AR) 变量都是一个有效的子命令。

 if test -z "$AR"; thenif [ -x "$(command -v gcc-ar)" ]; thenAR=gcc-arelif [ -x "$(command -v llvm-ar)" ]; thenAR=llvm-arelseAR=arfifi

5. 执行具体的编译指令

编译的时候我们一般会编译一些library或者一些测试工具, 这里简单说明一下编译命令。

  • 编译动态库/静态库 make static_lib -j6 或者 make shared_lib -j6,默认不带任何符号信息。
    如果想要把符号信息也添加进去来方便调试,则需要设置DEBUG_LEVEL=1 make static_lib,会以 -O2 的方式进行编译,并将一些测试代码和符号信息也编译到库中。
  • 编译rokcsdb 的测试工具:DEBUG_LEVEL=0 make db_bench
    因为工具的运行需要一些依赖库,这里可能需要大家安装对应的依赖库。
    gflags, snappy,zstd,zlib,lz4等,安装可以直接通过brew install xxx就可以,而像一些fallocate或者jemalloc 的依赖问题,如果不想安装,可以通过ROCKSDB_DISABLE_FALLOCATE=1 或者 ROCKSDB_DISABLE_JEMALLOC=1来禁用即可。
    编译完成之后,可以通过otool -L db_bench 这样的命令来进行测试。

问题记录2: jar 包编译

编译jar包,建议通过 rocksdbjavastatic 来进行编译,否则一些jni的代码编译不进去,出来的jar 包无法独立使用,缺少一些jni的符号。
编译java的时候如果本地shell 环境没有设置JAVA_HOME,则需要单独指定。

  1. 通过执行/usr/libexec/java_home 来得到JAVA_HOME的路径

     $ /usr/libexec/java_home
    /Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Home
    

    如果执行失败,则表示没有安装jdk,需要brew search jdkbrew install jdk@xxx 安装指定版本的jdk

  2. 通过 rocksdbjavastatic 编译的时候需要 从网络上下载 以及 编译一些压缩算法,这里建议 单独下载好到Makefile所在目录。
    lz4-*.tar.gz .
    snappy-*.tar.gz .
    zlib-*.tar.gz .
    zstd-*.tar.gz .
    bzip2-*.tar.gz .
    
  3. 编译命令则建议通过ROCKSDB_DISABLE_JEMALLOC=0 DEBUG_LEVEL=0 JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Home make rocksdbjavastatic -j6 进行安装。
    编译完成之后会在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 包的测试,可以通过java/samples/src/main/java/RocksDBSample.java 代码进行测试:

cd java/src
# 1. 编译测试代码
/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. 运行测试代码 并指定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

没有core 且生成db-dir 目录,则表示当前jar包无异常。

当然,也可以跑一下java的unitest,如果都过了,那也没什么问题。

Mac 从Makefile 编译 Rocksdb 源码的一些注意事项相关推荐

  1. mac c语言 gui,MAC GUI编程编译wxWidgets源码教程

    想要对您Mac电脑上的文件进行GUI编程或者编译吗?可是又不知道如何去启动编辑?那就来看看这里的MAC GUI编程编译wxWidgets源码教程吧.只要通过了MAC GUI编程编译wxWidgets源 ...

  2. 编译rocksdb源码导致的部署失败

    这几天经历了一次心酸的历程,使用了rocksdb第三方库,编译器是7.2,rocksdb是20190701从github上取下来的,由于rocksdb自己的CMakeList.txt中使用了-marc ...

  3. mac下编译安卓源码

    资源 Mac OS10.12 编译Android源码8.1 aosp编译-需翻墙 Mac下编译安卓源码 手把手教你在Mac OS下载.编译及导入Android源码 步骤 准备 磁盘空间大于180G 安 ...

  4. 中标麒麟编译qgis源码+PyQt环境

    中标麒麟编译qgis源码 根据公司工作安排需要在中标麒麟下编译qgis3.4.7,把编译的过程随手记录一下. QGIS项目主页:http://www.qgis.org/en/site/ QGIS源码下 ...

  5. windows 平台使用 VS2017 编译 libevent 源码

    一 依赖库编译 先要将其依赖的库编译好,其中openssl需要编译到libevent中,编译成libevent_openssl.lib库,zlib在新版本中只有示例用到. 1)windows 平台使用 ...

  6. Linux如何编译安装源码包软件

    一.什么是源码包软件: 顾名思义,源码包就是源代码的可见的软件包,基于Linux和BSD系统的软件最常见:在国内源可见的软件几乎绝迹:大多开源软件都是国外出品:在国内较为出名的开源软件有fcitx;l ...

  7. 获取并编译linux源码,android获取源代码、编译、命令

    ---my--- 正确的编译android sdk: cd myandroid . ./build/envsetup.sh lunch sdk-eng make sdk //或者: make PROD ...

  8. 编译Hadoop源码

    背景: 在阅读hadoop源代码过程中会发现部分类或者函数无法找到,这是由于Hadoop2.0使用了Protocol Buffers定义了RPC协议, 而这些Protocol Buffers文件在Ma ...

  9. 【Windows 逆向】CheatEngine 工具 ( CheatEngine 简介 | 使用 Lazarus 编译 CE 源码 | CheatEngine 相关文档资料 )

    文章目录 一.CheatEngine 简介 二.使用 Lazarus 编译 CE 源码 三.CheatEngine 相关文档资料 一.CheatEngine 简介 CheatEngine 简称 CE ...

最新文章

  1. java类的两个基本成分_Java类文件的基本结构
  2. UOJ #584. 天天去哪吃
  3. 获取当前系统时间c语言,使用C语言获取当前系统的时间
  4. java虚拟机内存监控_java虚拟机内存监控工具jps,jinfo,Jstack,jstat,jmap,jhat使用...
  5. 编码基本功:以文件大小进行性能测试是错误的
  6. C++11线程中的几种锁
  7. 重要的GMaps对象与接口
  8. “第二课堂”开课啦~
  9. 「运维有小邓」搜索日志数据以作为网络安全情报
  10. 论文略读1《Direct training for spiking neural networks:faster,larger,better》
  11. 2022年中国现制咖啡行业市场规模及重点企业经营现状分析:市场规模达89.7亿元[图]
  12. RISC-V的ARTY工程实现
  13. Java实现简单的日历小程序之Java图形界面开发小日历
  14. pytorch自动下载的权重保存位置
  15. 手机游戏:崇尚简单至上和零碎娱乐的永恒价值
  16. 北京朝阳一互联网公司被警方一锅端了!23人被带走…这种岗位千万别干!
  17. Matplotlib 常用画图命令总结:使用 Python 在论文中画出一手漂亮的数据图
  18. android 获取外部存储卡路径,Android获得内/外置存储卡路径的方法
  19. 计算机专业培养要求,计算机科学与技术专业人才培养目标及毕业要求(2015修订版)...
  20. 那些适合仓库管理员使用的办公软件

热门文章

  1. 经常使用ARM汇编指令
  2. 2014-01-04 SQL练习
  3. 关于WPF的ComboBox中Items太多而导致加载过慢的问题
  4. am5718_AM5718如何扩大内存 - Sitara™ Cortex-A8 和 ARM9 微处理器 - Sitara™ Cortex-A8 和 ARM9 微处理器 - E2E™ 中文支持论坛...
  5. 新的mysql如何使用_如何使用新的MySQL更新日志
  6. 线性回归、逻辑回归及SVM
  7. linux 压缩排除某个文件夹,linux tar压缩排除 某类型文件 某个文件夹
  8. 手写java_手写JAVA虚拟机(二)——实现java命令行
  9. 高德地图markevents_GitHub - mingxuWang/Map: 高德地图API二次封装
  10. jedis操作set_在Java中使用jedis操作Set类型