一个维护成本低,容易修改的makefile

最近在自己从头实现一个服务器。 慢慢把它做成符合mmorpg使用。做一个非hello world工程,第一件事就是makefile了。

这里是地址:

https://github.com/enjolras1205/my_server/blob/master/my_server/Makefile

服务器echo功能都还没有,源码就先不放上来了。只有一个makefile。

此makefile的好处如下:

1、维护简单,文件、目录变动无需更改makefile:可作新makefile模板使用。

2、使用了预编译头,能加快编译速度。

我对makefile的理解很简单:目标的依赖关系与目标创建规则

列一下此前在makefile使用上遇到过的槛,希望看到这篇文章的人不再遇到:

1、如何将中间文件输入到一个指定的目录。

2、如何遍历目录获得构建的目标。

3、如何生成依赖关系。

问题1:

通过改变目标文件创建规则,这样目标文件就放到BUILD_DIR目录下了。

# object file create rule
$(BUILD_DIR)/%.o: %.cpp $(PCH)
        $(CXX) -c $(CXXFLAGS) $(INCLUDES) $< -o $@
问题2:
通过调用shell,或者内置的函数。

DIRS=$(shell find ./src -type d)
HEADERS=$(foreach dir_var,$(DIRS),$(wildcard $(dir_var)/*.h))
HEADER_DIRS=$(sort $(dir $(HEADERS)))
SRCS=$(foreach dir_var,$(DIRS),$(wildcard $(dir_var)/*.cpp))
SRC_DIRS=$(sort $(dir $(SRCS)))
OBJS=$(patsubst %.cpp,$(BUILD_DIR)/%.o,$(notdir $(SRCS)))
DEPS=$(patsubst %.o,%.d,$(OBJS))
INCLUDES=$(foreach dir_var,$(DIRS), -I $(dir_var))

第一行:通过find命令获得了src目录下的所有目录。

第二行:通过wildcard与foreach配合使用,遍历获得了所有的头文件。

第三行:dir获得目录,sort去重,得到了头文件目录。

第六行:通过patsubst字符串操作,得到了目标文件集合。

makefile内置函数的使用可以翻阅http://www.gnu.org/software/make/manual/make.pdf最后面的Index of Concepts。

问题3:

# depend file create rule
$(BUILD_DIR)/%.d: %.cpp
        @echo "making $@"
        @set -e;         $(RM) $@.tmp;         $(CXX) -E -MM $(CXXFLAGS) $(INCLUDES) $(filter %.cpp,$^) > $@.tmp;         sed ‘s,\(.*\)\.o[:]*,$(BUILD_DIR)/\1.o $@:,g‘<$@.tmp > $@;         $(RM) $@.tmp

通过g++ -MM生成了依赖的非系统头文件,然后通过sed的字符串处理,生成了类似下面的内容。值得注意的是,依赖文件也对这些文件存在依赖,否则,这些文件改动时,依赖文件不会重新生成。导致依赖关系没有更新,编译出错误的程序。

./build/Acceptor_Func.o build/Acceptor_Func.d: src/utility/acceptor/Acceptor_Func.cpp  src/utility/log/Log.h src/utility/builder/Singleton.h  src/utility/thread/Thr_Mutex.h src/Pre_Header.h  src/utility/thread/Thr_Mutex_Guard.h src/utility/thread/Thr_Mutex.h  src/utility/builder/Repo_Factory.h src/utility/builder/Singleton.h  src/utility/reactor/Reactor.h src/utility/builder/Obj_Pool.h  src/utility/reactor/Svc.h src/utility/reactor/Event.h  src/utility/sock/Sock_IO.h src/utility/sock/Sock.h  src/utility/sock/IPC_SAP.h src/define/Define.h
另一个值得注意的是include前面的减号。

-include $(DEPS)
相较于不加减号,当依赖文件不存在时,makefile会用上面的依赖文件生成规则生成新的依赖文件再include。

最后:如何使用

mkdir src
cd src/
echo "#include <iostream>" > Pre_Header.h
vim main.cpp,内容如下:
#include "Pre_Header.h"

int main()
{
	std::cout<<"hello world"<<std::endl;
	return 0;
}
敲入make即可在build目录下生成名为my_server的hello world程序。

一个维护成本低,容易修改的makefile

上一篇:Linux下DRBD配置


下一篇:Gecko 线程分析二