leveldb的makefile剖析
来源:互联网 发布:域名查询 美橙互联 编辑:程序博客网 时间:2024/05/21 15:14
首先出现在眼前的是这个:
OPT ?= -O2 -DNDEBUG
-O0
-O1
-O2
-O3
编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
至于-DNDEBUG我不知道什么意思,麻烦知道的同学告诉我。
-DNDEBUG是定义宏的意思。准确的来说-D是定义宏的意思,定义了NDEBUG这个宏,而在以下的代码当中能够使用#ifndef来判断:
在db/version_set.cc,db/db_bench.cc,doc/bench/db_bench_tree_db.cc,doc/bench/db_bench_sqlite3.cc,table/format.cc 当中都有#ifndef NDEBUG这一行。如果没有定义NDEBUG则不执行下面的代码。
使用这种方式可以通过控制编译参数-D来控制编译的代码量。
然后是这个:
$(shell CC="$(CC)" CXX="$(CXX)" TARGET_OS="$(TARGET_OS)" \./build_detect_platform build_config.mk ./) include build_config.mk
$(shell)是一个makefile的函数,但是它不像其他的函数,它的参数应该就是操作系统Shell的命令。它
和反引号“`”是相同的功能。这就是说,shell函数把执行操作系统命令后的输出作为函数返回。
这个函数做的工作很简单,就是执行了./build_detect_platform这个shell脚本文件。然后生成了./build_config.mk
./build_detect_platform这个shell脚本文件的作用就是检测系统的类型,是IOS还是Linux等等。然后生成的文件./build_config.mk就是符合这个系统的参数。
在build_detect_platform文件当中,有如下的语句:
if test -z "$CC"; then CC=cc fi if test -z "$CXX"; then CXX=g++ fi# Detect OS if test -z "$TARGET_OS"; then TARGET_OS=`uname -s` fi
如果CC,CXX,TARGET_OS为0的话则给它们赋值为cc,g++,操作系统的类型.
随后还有TARGET_OS的操作,
case "$TARGET_OS" in
使用case语句判断操作系统的类型, 随后将编译的参数PLATFORM(平台),COMMON_FLAGS(通用参数),PLATFORM_LIBS(编译时候需要使用的库),PLATFORM_LDFLAGS(链接时候的参数)等等给设定好
我们看include build_config.mk
打开build_config,mk可以发现在这个文件里面包含了make的很多变量,正如其名称一样是build需要的参数
在Makefile使用include关键字可以把别的Makefile包含进来,这很像C语言的#include
在这个include则是把build_config.mk原模原样的放在当前文件的包含位置。
随后在Makefile当中:
CFLAGS += -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)CXXFLAGS += -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT)LDFLAGS += $(PLATFORM_LDFLAGS) 链接的参数LIBS += $(PLATFORM_LIBS) 需要使用的库
接下来的
LIBOBJECTS = $(SOURCES:.cc=.o)
就是把build_config.mk里面的SOURCES里面的c++文件名换成.o文件,并赋值给LIBOBJECTS
MEMENVOBJECTS = $(MEMENV_SOURCES:.cc=.o)
也是同理
TESTUTIL = ./util/testutil.oTESTHARNESS = ./util/testharness.o $(TESTUTIL)
就是简单的赋值
如果用的是苹果系统,那么ar命令和其他系统的命令不同,需要做修改
ifeq ($(PLATFORM), IOS)AR=xcrun arendif
接下来先跳过一大串的代码,直接到
all: $(SHARED) $(LIBRARY)
这里就是makefile默认开始编译的地方,
这条命令说明这个makefile编译生成两个文件:
LIBRARY是静态库文件libleveldb.a
SHARED是动态库文件:
在makefile中有一条语句:
ifneq ($(PLATFORM_SHARED_EXT),)
这条语句说如果PLATFORM_SHARED_EXT不为空的话,则执行下面的语句:
查找build_config.mk得到PLATFORM_SHARED_EXT是so
接下去还要判断PLATFORM_SHARED_VERSIONED是否等于true
这个PLATFORM_SHARED_VERSIONED在build_detect_platform当中都是true,除了当检测到TARGET_OS是IOS的情况(此时PLATFORM_SHARED_VERSIONED是空的),就是说当你的系统是IOS时候,
SHARED,SHARED1,SHARED2,SHARED3都是libleveldb.so,而当你的系统是其他系统的时候,SHARED包含了SHARED1 SHARED2 SHARED3
SHARED1是libleveldb.so,SHARED2是libleveldb.so.1,SHARED3是libleveldb.so.1.18
SHARED1(libleveldb.so)和SHARED2(libleveldb.so.1)都是SHARED3(libleveldb.so.1.18)的软链接
而生成SHARED3:
$(CXX) $(LDFLAGS) $(PLATFORM_SHARED_LDFLAGS)$(SHARED2) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SOURCES) -o $(SHARED3) $(LIBS)
这里只要知道
PLATFORM_SHARED_CFLAGS 就是”-fPIC”这个参数
我们一般用来生成动态库的命令都是g++ -fPIC -shared,在这里两个参数都全了。剩下的重要参数就是SOURCES,就是指要编译进入libleveldb.a的文件
完整命令如下:
g++ -pthread -shared -Wl,-soname -Wl,libleveldb.so.1 -I. -I./include -std=c++0x -fno-builtin-memcmp -pthread -DOS_LINUX -DLEVELDB_PLATFORM_POSIX -DLEVELDB_ATOMIC_PRESENT -O2 -DNDEBUG -fPIC db/builder.cc db/c.cc db/dbformat.cc db/db_impl.cc db/db_iter.cc db/dumpfile.cc db/filename.cc db/log_reader.cc db/log_writer.cc db/memtable.cc db/repair.cc db/table_cache.cc db/version_edit.cc db/version_set.cc db/write_batch.cc table/block_builder.cc table/block.cc table/filter_block.cc table/format.cc table/iterator.cc table/merger.cc table/table_builder.cc table/table.cc table/two_level_iterator.cc util/arena.cc util/bloom.cc util/cache.cc util/coding.cc util/comparator.cc util/crc32c.cc util/env.cc util/env_posix.cc util/filter_policy.cc util/hash.cc util/histogram.cc util/logging.cc util/options.cc util/status.cc port/port_posix.cc -o libleveldb.so.1.18
而静态库很简单:
$(LIBRARY): $(LIBOBJECTS)rm -f $@ #首先先把原来的静态库删除掉$(AR) -rs $@ $(LIBOBJECTS) #重新使用AR生成静态库
接下来makefile需要生成的就是静态库的以来文件
.cc.o:$(CXX) $(CXXFLAGS) -c $< -o $@.c.o:$(CC) $(CFLAGS) -c $< -o $@
将C++代码和C代码文件编译生成.o文件。
其中,如果系统是IOS的话,那么需要使用IOS下面的编译器:xcrun
ifeq ($(PLATFORM), IOS)# For iOS, create universal object files to be used on both the simulator and# a device.PLATFORMSROOT=/Applications/Xcode.app/Contents/Developer/PlatformsSIMULATORROOT=$(PLATFORMSROOT)/iPhoneSimulator.platform/DeveloperDEVICEROOT=$(PLATFORMSROOT)/iPhoneOS.platform/DeveloperIOSVERSION=$(shell defaults read $(PLATFORMSROOT)/iPhoneOS.platform/version CFBundleShortVersionString)IOSARCH=-arch armv6 -arch armv7 -arch armv7s -arch arm64.cc.o:mkdir -p ios-x86/$(dir $@)xcrun -sdk iphonesimulator $(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@mkdir -p ios-arm/$(dir $@)xcrun -sdk iphoneos $(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@xcrun lipo ios-x86/$@ ios-arm/$@ -create -output $@.c.o:mkdir -p ios-x86/$(dir $@)xcrun -sdk iphonesimulator $(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@mkdir -p ios-arm/$(dir $@)xcrun -sdk iphoneos $(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@xcrun lipo ios-x86/$@ ios-arm/$@ -create -output $@
这一大行代码的作用就是把SOURCES里面的文件编译一下,只不过用到了xcrun
好了,如果你仅仅执行make,那么makefile做的就是生成动态库和静态库,中间会生成.o文件。但是makefile里面还有一个参数check。check是all的超集。如果运行make check那么不仅会生成动态库,静态库,.o文件,还会生成db_bench和leveldbutil可执行文件以及链接生成测试用的可执行文件。
接下来的
TESTS = \arena_test \autocompact_test \bloom_test \c_test \cache_test \coding_test \corruption_test \crc32c_test \db_test \dbformat_test \env_test \fault_injection_test \filename_test \filter_block_test \hash_test \issue178_test \issue200_test \log_test \memenv_test \skiplist_test \table_test \version_edit_test \version_set_test \write_batch_test
这一大串都是测试用的可执行文件的名字。
check: all $(PROGRAMS) $(TESTS)for t in $(TESTS); do echo "***** Running $$t"; ./$$t || exit 1; done
这个循环会把TESTS集合里面的文件一个个拿出来执行一下,就是通过运行./$$t,看看有没有什么问题。如果有问题的话那么退出码为1
makefile首先会生成
就是通过下面:
db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL)...................write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS)
这一大串的代码
最后有个小的剩余,就是MEMENVLIBRARY = libmemenv.a这个文件
这个文件之所以单独从TESTS这个集合当中拿出来,单独为它生成一个静态库,自然是因为它有一定的重要性,helper/memenv/ 实现了一个简单的完全内存的文件系统.
接下来的clean就不多说了,删除可执行文件,.o文件,动态库和静态库文件还有./build_detect_platform脚本生成的./build_config.mk文件。如果是IOS系统,那么最开始生成.o文件的时候会创建目录ios-x86,ios-arm,也一并删除了:
clean:-rm -f $(PROGRAMS) $(BENCHMARKS) $(LIBRARY) $(SHARED) $(MEMENVLIBRARY) */*.o */*/*.o ios-x86/*/*.o ios-arm/*/*.o build_config.mk-rm -rf ios-x86/* ios-arm/*
- leveldb的makefile剖析
- LevelDb原理剖析
- leveldb源码剖析--编码
- leveldb源码剖析-sstable
- leveldb源码剖析--MemTable
- LevelDB源码剖析之SSTable_1(Block的创建与读取)
- LevelDB源码剖析之SSTable_sstable文件的创建
- LevelDB源码剖析之SSTable_sstable文件的读取
- LevelDB源码剖析之SkipList
- LevelDB源码剖析之SkipList
- LevelDB源码剖析之Log_1
- LevelDB源码剖析之Log_2
- LevelDB源码剖析之TableCache
- leveldb源码剖析---filter block
- leveldb源码剖析---日志系统
- leveldb源码剖析---缓存系统
- leveldb源码剖析---迭代器设计
- leveldb源码剖析--key-value形式的Block块中的数据存储格式
- python中使用libsvm
- servlet后台如何接收对象参数
- HDU1969 Pie(二分搜索)
- presentviewcontroller 动画
- arm启动脚本里面经常出现1b
- leveldb的makefile剖析
- POJ 1852 Ants
- Mysql limit 分页机制和优化实例
- 5.2-1
- C++面试宝典(整理版)2
- linux gdb调试笔记
- HDU ACM 1084 What Is Your Grade?
- 安卓应用商店遭遇的创新窘境
- java中多态的小例子