文章目录- 前言:
- 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文件的编译。
我的天。。