【redis6.0.6】redis源码慢慢学,慢慢看 -- 第三天:MakeFile
时间:2022-07-24
本文章向大家介绍【redis6.0.6】redis源码慢慢学,慢慢看 -- 第三天:MakeFile,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
文章目录- 前言:
- 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
写了一遍之后,想了想,还是说人话吧(挑点我看得懂的 && 重要的 来讲)
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
# 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)
PREFIX?=/usr/local #默认目录
INSTALL_BIN=$(PREFIX)/bin #安装的默认目录
INSTALL=install
PKG_CONFIG?=pkg-config
# 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
# 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
# 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
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
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
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的安装选项
# 依赖项
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
# MakeFile真正开始Work的地方
all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME)
#Makefil.dep 的生成
Makefile.dep:
-$(REDIS_CC) -MM *.c > Makefile.dep 2> /dev/null || true
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include Makefile.dep
endif
.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))
.PHONY: persist-settings
# Prerequisites target
.make-prerequisites:
@touch $@
# 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
歇会儿,歇会儿,来个图笑笑,放松一下心情
来一套图吧
这就是我现在的心情写照了。
回来继续
# 下面生成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)
# 将所有点c文件编译成.o文件 自动完成file.c 到file.o的对应
%.o: %.c .make-prerequisites
$(REDIS_CC) -MMD -o $@ -c $<
# 接下来是删除编译产物
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
distclean: clean
-(cd ../deps && $(MAKE) distclean)
-(rm -f .make-*)
.PHONY: distclean
# 测试编译产物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
# 安装到/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)
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文件的编译。
我的天。。
- weex里Vuex state使用storage持久化
- 网络字体@font-face 如何处理网页中的特殊字体
- python实现多变量线性回归(Linear Regression with Multiple Variables)
- 【美团技术团队博客】序列化和反序列化
- Java 静态代理与动态代理
- ELK日志套件安装与使用
- HTML知识复习
- MarkDown 常用语法教程
- CSS3盒阴影 box-shadow
- HTML5-类库系列 补讲AJAX
- HTML5-类库系列 事件与获取完成版样式
- 为什么不要在 JavaScript 中使用位操作符?
- 高级语言的编译:链接及装载过程介绍
- 美团技术团队博客:Kafka文件存储机制那些事
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Codeforces Beta Round #8 A. Train and Peter
- Codeforces Round #559 (Div. 2)B. Expansion coefficient of the array
- Codeforces Beta Round #72 (Div. 1 Only)B. Doctor
- pygame游戏常用方法
- node-blog:用 node 搭建的个人开源博客
- 2018-2019 ICPC, NEERC, Southern Subregional Contest D. Garbage Disposal
- 「查缺补漏」JavaScript执行上下文-执行栈
- 树状数组 _ 求逆序数
- PAT (Basic Level) Practice (中文)1012 数字分类 (20 分)
- PAT (Basic Level) Practice (中文)1018 锤子剪刀布 (20 分)
- 还在用传统的方式驱动一个通信模组?不如一起来学习下TOS的AT模组框架吧!
- 编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(一)词法分析
- Codeforces Round #199 (Div. 2)C. Cupboard and Balloons
- PAT (Basic Level) Practice (中文)1004 成绩排名 (20 分)
- PAT (Basic Level) Practice (中文)1020 月饼 (25 分)