基于redis 7.2.3的makefile源码解读学习

 更新时间:2023年12月01日 08:35:19   作者:werbenhu  
这篇文章主要为大家介绍了基于redis 7.2.3的makefile源码解读学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

基于redis 7.2.3的makefile源码

先从makefile 入手,我这里是基于redis 7.2.3的源码。

# Top level makefile, the real shit is at src/Makefile
default: all
.DEFAULT:
    cd src && $(MAKE) $@
install:
    cd src && $(MAKE) $@
.PHONY: install

makefile两个伪指令

  • .PHONY:
    目标“.PHONY”的所有的依赖被作为伪目标。伪目标时这样一个目标:当使用make命令行指定此目标时,这个目标所在规则定义的命令、无论目标文件是否存在都会被无条件执行。
  • .DEFAULT
    Makefile 中,目标“.DEFAULT”所在规则定义的命令,被用在重建那些没有具体规则的目标(明确规则和隐含规则)。就是说一个文件作为某个规则的依赖,但却不是另外一个规则的目标时。Make 程序无法找到重建此文件的规则,此种情况时就执行“.DEFAULT”所指定的命令。

我们直接make,运行的是这个.DEFAULT目标,也就是 这一行cd src && $(MAKE) $@,也就是到src目录下然后执行$(MAKE) $@.

这个$(MAKE)是什么?

在Makefile中,$(MAKE) 是一个特殊的变量,用于递归调用 make 工具。在Makefile中,为了避免硬编码make命令的名称,通常使用$(MAKE)来代替。

这是因为在某些情况下,用户可能将 make 工具的可执行文件命名为不同的名称,例如 GNU make 在不同系统上可能被安装为make、gmake 或其他名称。通过使用$(MAKE),Makefile可以使用调用者所使用的 make 工具的名称,使其更具可移植性。

这个$@又是什么?

在Makefile中,有一些特殊的自动变量:

我们以这一段makefile为例:

target: dependency1 dependency2
    command
  • $@
    代表规则中的目标文件(target)。它表示当前规则中的目标的文件名。例如:
    在这个规则中,command中的$@ 会被替换为 "target"。
  • $^
    代表规则中的所有依赖项(dependencies)。它表示所有出现在规则中的依赖项的列表,以空格分隔。例如:
    在这个规则中,command中的$^ 会被替换为 "dependency1 dependency2"。
  • $<
    代表规则中的第一个依赖项。例如
    在这个规则中,command中的$< 会被替换为 "dependency1"。
  • $*
    代表规则中目标的文件名(不包含文件扩展名)的部分。例如:
%.o: %.c
  command $*

在这个规则中,如果目标是 "example.o",$* 会被替换为 "example"。

回到上面的makefile中:cd src && $(MAKE) $@ 这一行相当于在src中执行make了。

去到src下的Makefile。这个makefile足足有500行,这里就不贴出来了。

前面大部分都在定义一些变量,真正的make的目标从这里开始:

all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) $(TLS_MODULE)
    @echo ""
    @echo "Hint: It's a good idea to run 'make test' ;)"
    @echo ""

这里相当于如果执行make,将会编译redis-server, redis-sentinel, redis-cli所有的这些目标。

我们现在只关心redis-server这一个。我们找到$(REDIS_SERVER_NAME) 这表明这个REDIS_SERVER_NAME也是一个变量,我们找到它的定义,它又使用了PROG_SUFFIX这个变量,但是PROG_SUFFIX默认是没有定义的,所以其实相当于生成的目标文件就是redis-server

REDIS_SERVER_NAME=redis-server$(PROG_SUFFIX)

找到定义$(REDIS_SERVER_NAME)这个目标的地方

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

-o $@ 表示生成的可执行文件就叫redis-server. $^代表规则中的所有依赖项(dependencies),也就是上面的$(REDIS_SERVER_OBJ),这些OBJ就是我们需要编译的源码了,就是下面这些文件了。

REDIS_SERVER_OBJ=threads_mngr.o adlist.o quicklist.o ae.o anet.o dict.o server.o 
sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o 
networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o 
t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o 
intset.o syncio.o cluster.o cluster_legacy.o crc16.o endianconv.o slowlog.o 
eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crc64.o bitops.o 
sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o 
redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o 
geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o 
listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o tracking.o socket.o 
tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o 
call_reply.o script_lua.o script.o functions.o function_lua.o commands.o strl.o 
connection.o unix.o logreqres.o

$(REDIS_LD)变量

ifndef V
QUIET_CC = @printf '    %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR) 1>&2;
QUIET_GEN = @printf '    %b %b\n' $(CCCOLOR)GEN$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR) 1>&2;
QUIET_LINK = @printf '    %b %b\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;
QUIET_INSTALL = @printf '    %b %b\n' $(LINKCOLOR)INSTALL$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;
endif
...

REDIS_LD=$(QUIET_LINK)$(CC) $(FINAL_LDFLAGS)

这里的QUIET_LINK只是打印信息当前是编译还是链接等,在Shell中,printf 是一个用于格式化输出的命令。它的使用方式与C语言中的 printf 函数相似,但在Shell中,它用于在终端上格式化输出文本。

$(CC) 是一个在Makefile中经常使用的变量,用于表示C编译器的名称。这个变量的默认值通常是 "cc",即C语言的默认编译器。其实你在终端里面输入cc命令默认就是gcc。

在Makefile中,你可以使用 $(CC) 来引用C编译器,从而使Makefile更具可移植性。这样,如果用户在其系统上使用不同的C编译器,只需更改 CC 变量的定义,而不必修改整个Makefile。

FINAL_LDFLAGS 是gcc的一些编译参数。 比如-O3,表示GCC优化级别是3。

再回到这个target,其实就是将上面这些obj和这些.a链接成最终的redis-server可执行文件。FINAL_LIBS是一些系统的so链接库列表。

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

现在有一个问题,这些.o文件又是怎么生成的呢?下面这个目标会将当前目录下所有的.c文件编译成.o。

%.o: %.c .make-prerequisites
    $(REDIS_CC) -MMD -o $@ -c $&lt;

以上就是redis源码学习之makefile的详细内容,更多关于redis makefile的资料请关注脚本之家其它相关文章!

相关文章

  • Redis 实现队列原理的实例详解

    Redis 实现队列原理的实例详解

    这篇文章主要介绍了Redis 实现队列原理的实例详解的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
    2017-09-09
  • 阿里云服务器安装配置redis的方法并且加入到开机启动(推荐)

    阿里云服务器安装配置redis的方法并且加入到开机启动(推荐)

    这篇文章主要介绍了阿里云服务器安装配置redis并且加入到开机启动,需要的朋友可以参考下
    2017-12-12
  • Redis命令处理过程源码解析

    Redis命令处理过程源码解析

    这篇文章主要介绍了Redis命令处理过程源码解析,本文是基于社区版redis4.0.8,通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • Redis如何存储对象

    Redis如何存储对象

    这篇文章主要介绍了Redis如何存储对象,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • 详解redis数据结构之sds

    详解redis数据结构之sds

    sds是Simple Dynamic String的缩写,译为简单动态字符串,redis使用该结构保存字符串,不同于c中的字符串,redis使用该结构来更方便的进行字符串的处理,需要的朋友可以参考下
    2017-05-05
  • 浅谈Redis分布式锁的正确实现方式

    浅谈Redis分布式锁的正确实现方式

    这篇文章主要介绍了浅谈Redis分布式锁的正确实现方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • 解决Redis连接无法正常释放的问题

    解决Redis连接无法正常释放的问题

    这篇文章主要介绍了解决Redis连接无法正常释放的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Redis的字符串是如何实现的

    Redis的字符串是如何实现的

    本文主要介绍了Redis的字符串是如何实现的,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • Redis删除策略的三种方法及逐出算法

    Redis删除策略的三种方法及逐出算法

    这篇文章主要介绍了Redis删除策略的三种方法及逐出算法,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • Redis 集群搭建和简单使用教程

    Redis 集群搭建和简单使用教程

    集群技术是构建高性能网站架构的重要手段,下面这篇文章主要介绍了Redis 集群搭建和简单使用教程,文中通过示例代码和图片介绍的很想,对大家具有一定的参考价值,有需要的朋友们下面来一起看看吧。
    2017-02-02

最新评论