首页 > 系统相关 >Linux下makefile 编译项目

Linux下makefile 编译项目

时间:2024-09-04 13:23:47浏览次数:12  
标签:文件 nginx app makefile 编译 BUILD Linux ROOT DIR

1、规划makefile编写

a、根目录下放三个文件:

1、makefile:是咱们编译项目的入口脚本,编译项目从这里开始,起总体控制作用。 2、config.mk:配置脚本,被makefile包含,单独分处理,为了应付一些可变的东西。 3、common.mk:最核心的编译脚本,定义makefile编译规则,并且各个子目录中都用到这个来编译.c文件的编译

b、每个子目录下

都有一个叫做makefile的文件,每个makefile文件,都会包含根目录下的common.mk。

现在不支持目录中嵌套子目录

2、makefile文件

2.1、根目录下common.mk

#.PHONY:all clean 

ifeq ($(DEBUG),true)
#-g是生成调试信息。GNU调试器可以利用该信息
CC = g++-std=c++11-g 
VERSION = debug
else
CC = g++-std=c++11
VERSION = release
endif

#CC = gcc

# $(wildcard *.c)表示扫描当前目录下所有.c文件
#SRCS = nginx.c ngx_conf.c
SRCS = $(wildcard *.cxx)

#OBJS = nginx.o ngx_conf.o  这么一个一个增加.o太麻烦,下行换一种写法:把字符串中的.c替换为.o
OBJS = $(SRCS:.cxx=.o)

#把字符串中的.c替换为.d
#DEPS = nginx.d ngx_conf.d
DEPS = $(SRCS:.cxx=.d)

#可以指定BIN文件的位置,addprefix是增加前缀函数
#BIN = /mnt/hgfs/linux/nginx
BIN := $(addprefix $(BUILD_ROOT)/,$(BIN))

#定义存放ojb文件的目录,目录统一到一个位置才方便后续链接,不然整到各个子目录去,不好链接
#注意下边这个字符串,末尾不要有空格等否则会语法错误 
LINK_OBJ_DIR = $(BUILD_ROOT)/app/link_obj
DEP_DIR = $(BUILD_ROOT)/app/dep

#-p是递归创建目录,没有就创建,有就不需要创建了
$(shell mkdir-p $(LINK_OBJ_DIR))
$(shell mkdir-p $(DEP_DIR))

#我们要把目标文件生成到上述目标文件目录去,利用函数addprefix增加个前缀
#处理后形如 /mnt/hgfs/linux/nginx/app/link_obj/ngx_signal2.o /mnt/hgfs/linux/nginx/app/link_obj/ngx_signal.o
# := 在解析阶段直接赋值常量字符串【立即展开】,而 = 在运行阶段,实际使用变量时再进行求值【延迟展开】
# /mnt/hgfs/linux/nginx/app/link_obj/nginx.o   /mnt/hgfs/linux/nginx/app/link_obj/ngx_conf.o 
OBJS := $(addprefix $(LINK_OBJ_DIR)/,$(OBJS))
DEPS := $(addprefix $(DEP_DIR)/,$(DEPS))

#找到目录中的所有.o文件(编译出来的)
LINK_OBJ = $(wildcard $(LINK_OBJ_DIR)/*.o)
#因为构建依赖关系时app目录下这个.o文件还没构建出来,所以LINK_OBJ是缺少这个.o的,我们 要把这个.o文件加进来
LINK_OBJ += $(OBJS)

#-------------------------------------------------------------------------------------------------------
#make找第一个目标开始执行[每个目标[就是我们要生成的东西],其实都是定义一种依赖关系],目标的格式为:
#目标:目标依赖【可以省略】
# 要执行的命令【可以省略】
#如下这行会是开始执行的入口,执行就找到依赖项$(BIN)去执行了,同时,这里也依赖了$(DEPS),这样就会生成很多.d文件了
all:$(DEPS) $(OBJS) $(BIN)

#这里是诸多.d文件被包含进来,每个.d文件里都记录着一个.o文件所依赖哪些.c和.h文件。内容诸如 nginx.o: nginx.c ngx_func.h
#我们做这个的最终目的说白了是,即便.h被修改了,也要让make重新编译我们的工程,否则,你修改了.h,make不会重新编译,那不行的
#有必要先判断这些文件是否存在,不然make可能会报一些.d文件找不到
ifneq ("$(wildcard $(DEPS))","")#如果不为空,$(wildcard)是函数【获取匹配模式文件名】,这里 用于比较是否为""
include $(DEPS)
endif

#----------------------------------------------------------------1begin------------------
#$(BIN):$(OBJS)
$(BIN):$(LINK_OBJ)
@echo"------------------------build $(VERSION) mode--------------------------------!!!"

#一些变量:$@:目标,     $^:所有目标依赖
# gcc -o 是生成可执行文件
    $(CC)-o $@ $^-lpthread

#----------------------------------------------------------------1end-------------------


#----------------------------------------------------------------2begin-----------------
#%.o:%.c
$(LINK_OBJ_DIR)/%.o:%.cxx
# gcc -c是生成.o目标文件   -I可以指定头文件的路径
#如下不排除有其他字符串,所以从其中专门把.c过滤出来 
#$(CC) -o $@ -c $^
    $(CC)-I$(INCLUDE_PATH)-o $@-c $(filter %.cxx,$^)
#----------------------------------------------------------------2end-------------------



#----------------------------------------------------------------3begin-----------------
#我们现在希望当修改一个.h时,也能够让make自动重新编译我们的项目,所以,我们需要指明让.o依赖于.h文件
#那一个.o依赖于哪些.h文件,我们可以用“gcc -MM c程序文件名” 来获得这些依赖信息并重定向保存到.d文件中
#.d文件中的内容可能形如:nginx.o: nginx.c ngx_func.h
#%.d:%.c
$(DEP_DIR)/%.d:%.cxx
#gcc -MM $^ > $@
#.d文件中的内容形如:nginx.o: nginx.c ngx_func.h ../signal/ngx_signal.h,但现在的问题是我们的.o文件已经放到了专门的目录
# 所以我们要正确指明.o文件路径这样,对应的.h,.c修改后,make时才能发现,这里需要用到sed文本处理工具和一些正则表达式语法,不必深究
#gcc -MM $^ | sed 's,\(.*\)\.o[ :]*,$(LINK_OBJ_DIR)/\1.o:,g' > $@
#echo 中 -n表示后续追加不换行
echo-n $(LINK_OBJ_DIR)/>$@
# gcc -MM $^ | sed 's/^/$(LINK_OBJ_DIR)&/g' > $@
#  >>表示追加
# gcc -I$(INCLUDE_PATH) -MM $^ >> $@
    $(CC)-I$(INCLUDE_PATH)-MM $^>>$@

#上行处理后,.d文件中内容应该就如:/mnt/hgfs/linux/nginx/app/link_obj/nginx.o: nginx.c ngx_func.h ../signal/ngx_signal.h

#----------------------------------------------------------------4begin-----------------



#----------------------------------------------------------------nbegin-----------------
#clean:   
#rm 的-f参数是不提示强制删除
#可能gcc会产生.gch这个优化编译速度文件
# rm -f $(BIN) $(OBJS) $(DEPS) *.gch
#----------------------------------------------------------------nend------------------

2.2、config.mk

#定义项目编译的根目录,通过export把某个变量声明为全局的[其他文件中可以用],这里获取当前这个文件所在的路径作为根目录;
#BUILD_ROOT = /mnt/hgfs/linux/nginx
export BUILD_ROOT = $(shell pwd)

#定义头文件的路径变量
export INCLUDE_PATH = $(BUILD_ROOT)/_include

#定义我们要编译的目录
BUILD_DIR = $(BUILD_ROOT)/signal/ \
            $(BUILD_ROOT)/proc/   \
            $(BUILD_ROOT)/net/    \
            $(BUILD_ROOT)/misc/   \
            $(BUILD_ROOT)/logic/   \
            $(BUILD_ROOT)/app/

#编译时是否生成调试信息。GNU调试器可以利用该信息
#很多调试工具,包括Valgrind工具集都会因为这个为true能够输出更多的调试信息;
export DEBUG =true

2.3、根目录makefile

include config.mk
all:
#-C是指定目录
#make -C signal   

#可执行文件应该放最后
#make -C app      

#用shell命令for搞,shell里边的变量用两个$
@fordirin $(BUILD_DIR); \
do \
        make -C $$dir; \
done


clean:
#-rf:删除文件夹,强制删除
rm-rf app/link_obj app/dep nginx
rm-rf signal/*.gch app/*.gch

2.4、其他目录下

#只生成 .d,.o即可 
BIN = nginx   #这个可以保证生成nginx可执行文件
include $(BUILD_ROOT)/common.mk


标签:文件,nginx,app,makefile,编译,BUILD,Linux,ROOT,DIR
From: https://blog.51cto.com/u_14618022/11917510

相关文章

  • Linux C++ 多线程高并发服务器实战项目一
    1、项目介绍1、按照包头+包体的格式收发数据包,解决粘包的问题2、非常完整的多线程高并发服务器3、根据收到数据包执行,不同的业务逻辑函数用到的技术:epoll高并发通讯技术,用的是水平触发【LT】水平触发模式通过线程池技术处理业务逻辑多线程、之间同步技术使用,互斥量、和条件变......
  • linux下graphviz离线安装指南及报错解决方式
    在联网的机器上下载Graphviz的源码包:网址:Graphviz下载地址将下载的安装包copy到linux下,解压后,在解压目录下执行安装tar-xvfgraphviz-12.1.0.tar.gzcdgraphviz-12.1.0./configure--prefix=/your_want_install_path/makemakeinstall注:我在执行make命令时报......
  • 在Linux系统中如何修改只读文件?
    在Linux操作系统中,每个文件都有自己的权限,包括读取、写入和执行权限。只读权限是指用户只能查看文件内容而不能修改或删除文件的权限,那么Linux只读文件如何修改?以下是具体方法。在Linux系统中,默认情况下某些文件和目录是只读的,这意味着您无法直接更改它们的内容。然而,可以......
  • nginx部署前端项目 (Linux版)
    目录一:nginx部署前端项目(Windows版)二:下载相关依赖三:下载安装nginx四:启动nginx五:部署前端项目一:nginx部署前端项目(Windows版)nginx部署前端项目(Windows版本)二:下载相关依赖yuminstall-ygcc-c++pcrepcre-develzlibzlib-developensslopen......
  • Linux 系统压测实战
    今天给伙伴们分享一下Linux系统压测实战,希望看了有所收获。我是公众号「想吃西红柿」「云原生运维实战派」作者,对云原生运维感兴趣,也保持时刻学习,后续会分享工作中用到的运维技术,在运维的路上得到支持和共同进步!如果伙伴们看了文档觉得有用,欢迎大家关注我的公众号,获取相......
  • Linux 用户和组管理(详细)
    今天给伙伴们分享一下Linux用户和组管理,希望看了有所收获。我是公众号「想吃西红柿」「云原生运维实战派」作者,对云原生运维感兴趣,也保持时刻学习,后续会分享工作中用到的运维技术,在运维的路上得到支持和共同进步!如果伙伴们看了文档觉得有用,欢迎大家关注我的公众号,获取相......
  • Linux 磁盘管理-存储设备及类型介绍(超详细)
    今天给伙伴们分享一下Linux磁盘管理-存储设备及类型介绍,希望看了有所收获。我是公众号「想吃西红柿」「云原生运维实战派」作者,对云原生运维感兴趣,也保持时刻学习,后续会分享工作中用到的运维技术,在运维的路上得到支持和共同进步!如果伙伴们看了文档觉得有用,欢迎大家关注......
  • linux 基础操作
    LinuxOperationsoriginurl(https://ubuntu.com/tutorials/command-line-for-beginners#4-creating-folders-and-files)Fileoperatorsopenaterminal_shift+alt+t_showcurrentworkingdirectory_pwd_changedirectorycd*changedirectorytoroot_cd......
  • Linux-devops
    云原生时代:以Devops、SRE框架为指导,Docker/K8S/微服务为基础,用分布式方式加上Python和Go语言,构建一套云技术产品体系,以及进行高级管理工具的二次开发,实现属于公司自己的自动化运维体系以及云技术体系的自动化产品。使用的自动化运维产品,可以用rancherargoCDtecktonClgit......
  • Linux启动后自动登录root进入控制台
    通过修改/etc/inittab文件来实现1.buildroot编译出来的 /etc/inittab文件如下##Copyright(C)2001ErikAndersen<[email protected]>##Note:BusyBoxinitdoesn'tsupportrunlevels.Therunlevelsfieldis#completelyignoredbyBusyBoxinit.Ifyo......