最近闲着没事,找了一个socket异步io的库写了一个服务端程序。好久没有写过C/C++程序,Makefile也不会写了。先在网上找了一个Makefile模板,修修改改也基本能用。
基本能用不行啊,我需要一些高级点的操作。
首先,我希望目标文件不要和源代码放在一起,所以创建了一个目标目录,编译生成到目标目录中
dest_dir = build
src_dir = src
obj_dir = $(dest_dir)/objects
bin_dir = $(dest_dir)/bin
$(bin_dir)/%:
@echo ">>> Linking" $@ "<<<"
@if [ ! -d $(bin_dir) ]; then mkdir -p $(bin_dir); fi;
$(CC) -o $@ $^ $(LLIB)
ln -sf $@ $(notdir $@)
$(obj_dir)/%.o: $(src_dir)/%.cpp
@echo ">>> Compiling" $< "<<<"
@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
$(CC) $(CFLAGS) $(IINC) -c $< -o $@
其次,需要添加多目标,clean,debug之类的不能少。debug依赖clean和all,另外,debug的编译选项也不同
CFLAGS = -Wall -O3 -std=c++14
debug: CFLAGS = -c -g -Ddebug -std=c++14
debug: clean all
第三步,由于用到protobuf,使用protobuf生成的C++文件的后缀是cc,添加cc的编译设置,并且由于生成文件我希望是在另外自动创建的generate目录,所以增加cc编译选项,并修改原来的编译选项,使用VPATH变量指定源代码搜寻目录
VPATH = $(src_dir):$(src_dir)/generated
$(obj_dir)/%.o: %.cpp
@echo ">>> Compiling" $< "<<<"
@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
$(C++) $(CCFLAGS) $(IINC) -c $< -o $@
$(obj_dir)/%.o: %.cc
@echo ">>> Compiling" $< "<<<"
@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
$(C++) $(CCFLAGS) $(IINC) -c $< -o $@
另外,protobuf相关的代码是纯C,同样的方式增加C编译选项
最后,不想在Makefile中罗列源代码列表了,直接罗列obj文件,至于源码是什么后缀,由make自己去搜寻。由于obj文件我们希望还是生成在目标目录,通过addprefix命令,在目标文件列表中统一添加目标目录前缀
# C++FILES = main.cpp
# CCFILES = base.pb.cc calc.pb.cc login.pb.cc
# CFILES = protorpc.c
#ofiles = $(C++FILES:%.cpp=$(obj_dir)/%.o) $(CCFILES:%.cc=$(obj_dir)/%.o) $(CFILES:%.c=$(obj_dir)/%.o)
ofiles = $(addprefix $(obj_dir)/, main.o base.pb.o calc.pb.o login.pb.o protorpc.o)
至此,一个功能相对完备的Makefile文件完成,能够适应我这个相对复杂的需求。
# $@: 目标文件, $^: 所有依赖文件, $<: 第一个依赖文件
# 语法规则:
# targets: prerequisites
# command
dest_dir = build
src_dir = src
obj_dir = $(dest_dir)/objects
bin_dir = $(dest_dir)/bin
inc_dir = /usr/local/include
lib_dir = /usr/local/lib
CC = gcc
C++ = g++
RESULT = boyiserver
CFLAGS = -Wall -O3
# C++FILES = main.cpp
# CCFILES = base.pb.cc calc.pb.cc login.pb.cc
# CFILES = protorpc.c
IINC = -I$(inc_dir)
LLIB = -L $(lib_dir) -lhv -lhiredis -lprotobuf
VPATH = $(src_dir):$(src_dir)/generated
#vpath %.cc $(src_dir)/generated
#ofiles = $(C++FILES:%.cpp=$(obj_dir)/%.o) $(CCFILES:%.cc=$(obj_dir)/%.o) $(CFILES:%.c=$(obj_dir)/%.o)
ofiles = $(addprefix $(obj_dir)/, main.o base.pb.o calc.pb.o login.pb.o protorpc.o)
program = $(bin_dir)/$(RESULT)
all: $(program)
debug: CFLAGS = -c -g -Ddebug
debug: clean all
CCFLAGS = $(CFLAGS) -std=c++14
$(program): $(ofiles)
$(bin_dir)/%:
@echo ">>> Linking" $@ "<<<"
@if [ ! -d $(bin_dir) ]; then mkdir -p $(bin_dir); fi;
$(C++) -o $@ $^ $(LLIB)
ln -sf $@ $(notdir $@)
$(obj_dir)/%.o: %.cpp
@echo ">>> Compiling" $< "<<<"
@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
$(C++) $(CCFLAGS) $(IINC) -c $< -o $@
$(obj_dir)/%.o: %.cc
@echo ">>> Compiling" $< "<<<"
@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
$(C++) $(CCFLAGS) $(IINC) -c $< -o $@
$(obj_dir)/%.o: %.c
@echo ">>> Compiling" $< "<<<"
@if [ ! -d $(obj_dir) ]; then mkdir -p $(obj_dir); fi;
$(CC) $(CFLAGS) $(IINC) -c $< -o $@
.PHONY: clean
clean:
rm -rf $(dest_dir)
rm -f $(RESULT)