基于redis 7.2.3的makefile源碼解讀學(xué)習(xí)
基于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兩個(gè)偽指令
- .PHONY:
目標(biāo)“.PHONY”的所有的依賴被作為偽目標(biāo)。偽目標(biāo)時(shí)這樣一個(gè)目標(biāo):當(dāng)使用make命令行指定此目標(biāo)時(shí),這個(gè)目標(biāo)所在規(guī)則定義的命令、無(wú)論目標(biāo)文件是否存在都會(huì)被無(wú)條件執(zhí)行。 - .DEFAULT
Makefile 中,目標(biāo)“.DEFAULT”所在規(guī)則定義的命令,被用在重建那些沒(méi)有具體規(guī)則的目標(biāo)(明確規(guī)則和隱含規(guī)則)。就是說(shuō)一個(gè)文件作為某個(gè)規(guī)則的依賴,但卻不是另外一個(gè)規(guī)則的目標(biāo)時(shí)。Make 程序無(wú)法找到重建此文件的規(guī)則,此種情況時(shí)就執(zhí)行“.DEFAULT”所指定的命令。
我們直接make,運(yùn)行的是這個(gè).DEFAULT目標(biāo),也就是 這一行cd src && $(MAKE) $@
,也就是到src目錄下然后執(zhí)行$(MAKE) $@
.
這個(gè)$(MAKE)是什么?
在Makefile中,$(MAKE) 是一個(gè)特殊的變量,用于遞歸調(diào)用 make 工具。在Makefile中,為了避免硬編碼make命令的名稱,通常使用$(MAKE)來(lái)代替。
這是因?yàn)樵谀承┣闆r下,用戶可能將 make 工具的可執(zhí)行文件命名為不同的名稱,例如 GNU make 在不同系統(tǒng)上可能被安裝為make、gmake 或其他名稱。通過(guò)使用$(MAKE),Makefile可以使用調(diào)用者所使用的 make 工具的名稱,使其更具可移植性。
這個(gè)$@又是什么?
在Makefile中,有一些特殊的自動(dòng)變量:
我們以這一段makefile為例:
target: dependency1 dependency2 command
- $@
代表規(guī)則中的目標(biāo)文件(target)。它表示當(dāng)前規(guī)則中的目標(biāo)的文件名。例如:
在這個(gè)規(guī)則中,command中的$@
會(huì)被替換為 "target"。 - $^
代表規(guī)則中的所有依賴項(xiàng)(dependencies)。它表示所有出現(xiàn)在規(guī)則中的依賴項(xiàng)的列表,以空格分隔。例如:
在這個(gè)規(guī)則中,command中的$^
會(huì)被替換為 "dependency1 dependency2"。 - $<
代表規(guī)則中的第一個(gè)依賴項(xiàng)。例如
在這個(gè)規(guī)則中,command中的$<
會(huì)被替換為 "dependency1"。 - $*
代表規(guī)則中目標(biāo)的文件名(不包含文件擴(kuò)展名)的部分。例如:
%.o: %.c command $*
在這個(gè)規(guī)則中,如果目標(biāo)是 "example.o",$* 會(huì)被替換為 "example"。
回到上面的makefile中:cd src && $(MAKE) $@
這一行相當(dāng)于在src中執(zhí)行make
了。
去到src下的Makefile。這個(gè)makefile足足有500行,這里就不貼出來(lái)了。
前面大部分都在定義一些變量,真正的make的目標(biāo)從這里開(kāi)始:
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 ""
這里相當(dāng)于如果執(zhí)行make,將會(huì)編譯redis-server, redis-sentinel, redis-cli所有的這些目標(biāo)。
我們現(xiàn)在只關(guān)心redis-server這一個(gè)。我們找到$(REDIS_SERVER_NAME)
這表明這個(gè)REDIS_SERVER_NAME
也是一個(gè)變量,我們找到它的定義,它又使用了PROG_SUFFIX
這個(gè)變量,但是PROG_SUFFIX默認(rèn)是沒(méi)有定義的,所以其實(shí)相當(dāng)于生成的目標(biāo)文件就是redis-server
。
REDIS_SERVER_NAME=redis-server$(PROG_SUFFIX)
找到定義$(REDIS_SERVER_NAME)
這個(gè)目標(biāo)的地方
# 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 $@
表示生成的可執(zhí)行文件就叫redis-server. $^
代表規(guī)則中的所有依賴項(xiàng)(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只是打印信息當(dāng)前是編譯還是鏈接等,在Shell中,printf 是一個(gè)用于格式化輸出的命令。它的使用方式與C語(yǔ)言中的 printf 函數(shù)相似,但在Shell中,它用于在終端上格式化輸出文本。
$(CC) 是一個(gè)在Makefile中經(jīng)常使用的變量,用于表示C編譯器的名稱。這個(gè)變量的默認(rèn)值通常是 "cc",即C語(yǔ)言的默認(rèn)編譯器。其實(shí)你在終端里面輸入cc命令默認(rèn)就是gcc。
在Makefile中,你可以使用 $(CC) 來(lái)引用C編譯器,從而使Makefile更具可移植性。這樣,如果用戶在其系統(tǒng)上使用不同的C編譯器,只需更改 CC 變量的定義,而不必修改整個(gè)Makefile。
FINAL_LDFLAGS
是gcc的一些編譯參數(shù)。 比如-O3,表示GCC優(yōu)化級(jí)別是3。
再回到這個(gè)target,其實(shí)就是將上面這些obj和這些.a鏈接成最終的redis-server可執(zhí)行文件。FINAL_LIBS
是一些系統(tǒng)的so鏈接庫(kù)列表。
# 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)
現(xiàn)在有一個(gè)問(wèn)題,這些.o文件又是怎么生成的呢?下面這個(gè)目標(biāo)會(huì)將當(dāng)前目錄下所有的.c文件編譯成.o。
%.o: %.c .make-prerequisites $(REDIS_CC) -MMD -o $@ -c $<
以上就是redis源碼學(xué)習(xí)之makefile的詳細(xì)內(nèi)容,更多關(guān)于redis makefile的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Redis 數(shù)據(jù)庫(kù)忘記密碼找回或重置的解決方法
對(duì)于 Redis 數(shù)據(jù)庫(kù),如果忘記了密碼,可以通過(guò)密碼重置來(lái)找回密碼,今天通過(guò)本文給大家分享Redis 數(shù)據(jù)庫(kù)忘記密碼找回或重置的解決方法,感興趣的朋友一起看看吧2024-01-01Redis數(shù)據(jù)庫(kù)的數(shù)據(jù)傾斜詳解
Redis,英文全稱是Remote Dictionary Server(遠(yuǎn)程字典服務(wù)),是一個(gè)開(kāi)源的使用ANSI C語(yǔ)言編寫(xiě)、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫(kù),需要的朋友可以參考下2023-07-07淺談Redis存儲(chǔ)數(shù)據(jù)類型及存取值方法
這篇文章主要介紹了淺談Redis存儲(chǔ)數(shù)據(jù)類型及存取值方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05

redis實(shí)現(xiàn)sentinel哨兵架構(gòu)的方法