【redis6.0.6】redis源码慢慢学,慢慢看 -- 第三天:MakeFile

2020-08-31 10:25:58 浏览数 (1)

文章目录
  • 前言:

  • Redis Makefile
  • Copyright (C) 2009 Salvatore Sanfilippo
  • This file is released under the BSD license, see the COPYING file
    • makefile
    • 回来继续
    • 最后再总结一下

前言:

先附上人家的版权:

Redis Makefile Copyright © 2009 Salvatore Sanfilippo This file is released under the BSD license, see the COPYING file

配套资料: makefile方面有陈皓大神的跟我一起写MakeFile,我就不班门弄斧了。

为什么要先写这一部分呢?明明前面路线图把makefile都放最后了,因为我发现昨天写空间配置器的时候,有些默认配置是写在makefile里面的,而且那份路线图啊,哎,算了,还要改的。

如果非要说个所以然,那就:提纲掣领 吧。


分割线


makefile

写了一遍之后,想了想,还是说人话吧(挑点我看得懂的 && 重要的 来讲)

代码语言:javascript复制
release_hdr := $(shell sh -c './mkreleasehdr.sh')
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')	# uname -s 获取操作系统的类型 Linux
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')	# uname -m 获取操作系统的版本 x86_64
OPTIMIZATION?=-O2	# 优化选项
DEPENDENCY_TARGETS=hiredis linenoise lua	# 依赖目标
NODEPS:=clean distclean
代码语言:javascript复制
# Default settings
STD=-std=c11 -pedantic -DREDIS_STATIC=''	# 使用c11标准编译,-pedantic 保证代码规范满足ISO C和ISO C  标准,所以安装的时候系统要有最新的gcc版本
ifneq (,$(findstring clang,$(CC)))
ifneq (,$(findstring FreeBSD,$(uname_S)))
  STD =-Wno-c11-extensions
endif
endif
WARN=-Wall -W -Wno-missing-field-initializers	# 输出所有编译警告信息 ,Wno-missing-field-initializers 不输出missing-的警告信息
OPT=$(OPTIMIZATION)
代码语言:javascript复制
PREFIX?=/usr/local	#默认目录
INSTALL_BIN=$(PREFIX)/bin	#安装的默认目录
INSTALL=install
PKG_CONFIG?=pkg-config
代码语言:javascript复制
# Default allocator defaults to Jemalloc if it's not an ARM
#内存分配器的指定 默认libc,linux系统而且架构不是armv61和71的时候则是jemalloc,

MALLOC=libc
ifneq ($(uname_M),armv6l)
ifneq ($(uname_M),armv7l)
ifeq ($(uname_S),Linux)
	MALLOC=jemalloc
endif
endif
endif
代码语言:javascript复制
# Backwards compatibility for selecting an allocator
#编译的时候指定内存分配器
ifeq ($(USE_TCMALLOC),yes)
	MALLOC=tcmalloc
endif

ifeq ($(USE_TCMALLOC_MINIMAL),yes)
	MALLOC=tcmalloc_minimal
endif

ifeq ($(USE_JEMALLOC),yes)
	MALLOC=jemalloc
endif

ifeq ($(USE_JEMALLOC),no)
	MALLOC=libc
endif
代码语言:javascript复制
# Override default settings if possible
-include .make-settings
# 最终的编译选项CFLAGS是-c的选项,LDFLAGS是链接的选项
FINAL_CFLAGS=$(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) $(REDIS_CFLAGS)
FINAL_LDFLAGS=$(LDFLAGS) $(REDIS_LDFLAGS) $(DEBUG)
FINAL_LIBS=-lm
DEBUG=-g -ggdb
代码语言:javascript复制
ifeq ($(MALLOC),tcmalloc)
	FINAL_CFLAGS = -DUSE_TCMALLOC
	FINAL_LIBS = -ltcmalloc
endif

ifeq ($(MALLOC),tcmalloc_minimal)
	FINAL_CFLAGS = -DUSE_TCMALLOC
	FINAL_LIBS = -ltcmalloc_minimal
endif

ifeq ($(MALLOC),jemalloc)
	DEPENDENCY_TARGETS = jemalloc
	FINAL_CFLAGS = -DUSE_JEMALLOC -I../deps/jemalloc/include
	FINAL_LIBS := ../deps/jemalloc/lib/libjemalloc.a $(FINAL_LIBS)
endif
代码语言:javascript复制
ifeq ($(BUILD_TLS),yes)
	FINAL_CFLAGS =-DUSE_OPENSSL $(OPENSSL_CFLAGS)
	FINAL_LDFLAGS =$(OPENSSL_LDFLAGS)
	LIBSSL_PKGCONFIG := $(shell $(PKG_CONFIG) --exists libssl && echo $$?)
ifeq ($(LIBSSL_PKGCONFIG),0)
	LIBSSL_LIBS=$(shell $(PKG_CONFIG) --libs libssl)
else
	LIBSSL_LIBS=-lssl
endif
	LIBCRYPTO_PKGCONFIG := $(shell $(PKG_CONFIG) --exists libcrypto && echo $$?)
ifeq ($(LIBCRYPTO_PKGCONFIG),0)
	LIBCRYPTO_LIBS=$(shell $(PKG_CONFIG) --libs libcrypto)
else
	LIBCRYPTO_LIBS=-lcrypto
endif
	FINAL_LIBS  = ../deps/hiredis/libhiredis_ssl.a $(LIBSSL_LIBS) $(LIBCRYPTO_LIBS)
endif
代码语言:javascript复制
REDIS_CC=$(QUIET_CC)$(CC) $(FINAL_CFLAGS)	#redis 的gcc -c 选项
REDIS_LD=$(QUIET_LINK)$(CC) $(FINAL_LDFLAGS)	#redis的gcc 链接选项
REDIS_INSTALL=$(QUIET_INSTALL)$(INSTALL)	#redis的安装选项
代码语言:javascript复制
# 依赖项

REDIS_SERVER_NAME=redis-server
REDIS_SENTINEL_NAME=redis-sentinel
REDIS_SERVER_OBJ=adlist.o quicklist.o ··· setcpuaffinity.o	//此处省略一大堆
REDIS_CLI_NAME=redis-cli
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o ae.o crcspeed.o crc64.o siphash.o crc16.o
REDIS_BENCHMARK_NAME=redis-benchmark
REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o adlist.o dict.o zmalloc.o siphash.o
REDIS_CHECK_RDB_NAME=redis-check-rdb
REDIS_CHECK_AOF_NAME=redis-check-aof
代码语言:javascript复制
# MakeFile真正开始Work的地方
all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME)
代码语言:javascript复制
#Makefil.dep 的生成
Makefile.dep:
	-$(REDIS_CC) -MM *.c > Makefile.dep 2> /dev/null || true

ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include Makefile.dep
endif
代码语言:javascript复制
.PHONY: all
#先清除所有编译的输出然后,  将所有设置持久化
persist-settings: distclean
	echo STD=$(STD) >> .make-settings
	echo WARN=$(WARN) >> .make-settings
	echo OPT=$(OPT) >> .make-settings
	echo MALLOC=$(MALLOC) >> .make-settings
	echo CFLAGS=$(CFLAGS) >> .make-settings
	echo LDFLAGS=$(LDFLAGS) >> .make-settings
	echo REDIS_CFLAGS=$(REDIS_CFLAGS) >> .make-settings
	echo REDIS_LDFLAGS=$(REDIS_LDFLAGS) >> .make-settings
	echo PREV_FINAL_CFLAGS=$(FINAL_CFLAGS) >> .make-settings
	echo PREV_FINAL_LDFLAGS=$(FINAL_LDFLAGS) >> .make-settings
	-(cd ../deps && $(MAKE) $(DEPENDENCY_TARGETS))
代码语言:javascript复制
.PHONY: persist-settings
代码语言:javascript复制
# Prerequisites target
.make-prerequisites:
	@touch $@
代码语言:javascript复制
# Clean everything, persist settings and build dependencies if anything changed
#当设置有变化的时候清除并重新持久化设置
ifneq ($(strip $(PREV_FINAL_CFLAGS)), $(strip $(FINAL_CFLAGS)))
.make-prerequisites: persist-settings
endif

ifneq ($(strip $(PREV_FINAL_LDFLAGS)), $(strip $(FINAL_LDFLAGS)))
.make-prerequisites: persist-settings
endif

歇会儿,歇会儿,来个图笑笑,放松一下心情

来一套图吧

这就是我现在的心情写照了。

回来继续

代码语言:javascript复制
# 下面生成redis-server redis-cli等可执行程序

# redis-server
$(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ)
	$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a $(FINAL_LIBS)

# redis-sentinel
$(REDIS_SENTINEL_NAME): $(REDIS_SERVER_NAME)
	$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME)

# redis-check-rdb
$(REDIS_CHECK_RDB_NAME): $(REDIS_SERVER_NAME)
	$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_CHECK_RDB_NAME)

# redis-check-aof
$(REDIS_CHECK_AOF_NAME): $(REDIS_SERVER_NAME)
	$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_CHECK_AOF_NAME)

# redis-cli
$(REDIS_CLI_NAME): $(REDIS_CLI_OBJ)
	$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(FINAL_LIBS)

# redis-benchmark
$(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ)
	$(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS)

dict-benchmark: dict.c zmalloc.c sds.c siphash.c
	$(REDIS_CC) $(FINAL_CFLAGS) $^ -D DICT_BENCHMARK_MAIN -o $@ $(FINAL_LIBS)

DEP = $(REDIS_SERVER_OBJ:%.o=%.d) $(REDIS_CLI_OBJ:%.o=%.d) $(REDIS_BENCHMARK_OBJ:%.o=%.d)
-include $(DEP)
代码语言:javascript复制
# 将所有点c文件编译成.o文件 自动完成file.c 到file.o的对应
%.o: %.c .make-prerequisites
	$(REDIS_CC) -MMD -o $@ -c $<
代码语言:javascript复制
# 接下来是删除编译产物
clean:
	rm -rf $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) *.o *.gcda *.gcno *.gcov redis.info lcov-html Makefile.dep dict-benchmark
	rm -f $(DEP)

.PHONY: clean
代码语言:javascript复制
distclean: clean
	-(cd ../deps && $(MAKE) distclean)
	-(rm -f .make-*)

.PHONY: distclean
代码语言:javascript复制
# 测试编译产物redis-server redis-cli等
test: $(REDIS_SERVER_NAME) $(REDIS_CHECK_AOF_NAME)
	@(cd ..; ./runtest)

test-sentinel: $(REDIS_SENTINEL_NAME)
	@(cd ..; ./runtest-sentinel)

check: test

lcov:
	$(MAKE) gcov
	@(set -e; cd ..; ./runtest --clients 1)
	@geninfo -o redis.info .
	@genhtml --legend -o lcov-html redis.info

test-sds: sds.c sds.h
	$(REDIS_CC) sds.c zmalloc.c -DSDS_TEST_MAIN $(FINAL_LIBS) -o /tmp/sds_test
	/tmp/sds_test

.PHONY: lcov
代码语言:javascript复制
 # 安装到/usr/local/bin
 @mkdir -p $(INSTALL_BIN)
	$(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(INSTALL_BIN)
	$(REDIS_INSTALL) $(REDIS_BENCHMARK_NAME) $(INSTALL_BIN)
	$(REDIS_INSTALL) $(REDIS_CLI_NAME) $(INSTALL_BIN)
	$(REDIS_INSTALL) $(REDIS_CHECK_RDB_NAME) $(INSTALL_BIN)
	$(REDIS_INSTALL) $(REDIS_CHECK_AOF_NAME) $(INSTALL_BIN)
	@ln -sf $(REDIS_SERVER_NAME) $(INSTALL_BIN)/$(REDIS_SENTINEL_NAME)
代码语言:javascript复制
uninstall:
	rm -f $(INSTALL_BIN)/{$(REDIS_SERVER_NAME),$(REDIS_BENCHMARK_NAME),$(REDIS_CLI_NAME),$(REDIS_CHECK_RDB_NAME),$(REDIS_CHECK_AOF_NAME),$(REDIS_SENTINEL_NAME)}

最后再总结一下

总结一下Redis Makefile的思路: 在默认规则也就是第一条规则之前,通过变量设置好编译的相关选项:LDFLAGS,相应的对应关系REDIS_SERVER_OBJ,将规则的target用变量表示好(方便all规则里面用作前置条件),比如REDIS_SERVER_NAME。 在第一条默认规则 all规则里面指定需要构建的东西 在第一规则后面先完成链接,再完成编译的规则 其他功能性规则如clean和distclean 也就是从上到下的结构是总-分。显示整个项目 ,然后是各个模块如redis-server,redis-cli的链接,然后是从源文件到obj文件的编译。

我的天。。

0 人点赞