您好,欢迎来到九壹网。
搜索
您的当前位置:首页Makefile学习(四)提取makefile的公共部分,简化makefile

Makefile学习(四)提取makefile的公共部分,简化makefile

来源:九壹网

在上节我们完成了通过make编译多个项目,但是我们发现,两个项目里其实有非常多的重复部分,并且每个项目的makefile都非常长。

于是想到能不能把公共部分都提取出来,自定义一个makefile配置

于是本章节通过在项目中包含一个公共的makefile来实现makefile的简化

(一)成果预览

首先看看简化后的Test_s_lib的makefile

ifeq ($(STATIC),1)
LIBTYPE=.a
else
LIBTYPE=.so
endif
include ../makefile.mk

这是简化后的Test_d_lib的makefile

LIBTYPE=.so
include ../makefile.mk

是的一共就这么几行!!!比起原来的少了非常多

(二)编写配置用的makefile

(1)提取TARGET

通过ifndef来判断是否已经确定目标

ifndef TARGET
TARGET:=$(notdir $(shell pwd)) #test_include
endif

在上一章节中提到过可以通过$(shell pwd)获取到当前路径

这里再引入一个新的makefile函数 :notdir 

1、notdir函数:

作用是从文件路径中提取文件名部分,去掉路径部分。

当有一个文件路径/home/user/documents/file.txt,

使用notdir函数后,$(notir /home/user/documents/file.txt)  返回的结果是file.txt

(2)提取编译器环境变量

变量的意思已经再第二章节解释过,这就不在解释一遍啦


CXXFLAGS:=$(CXXFLAGS) -I../../include -std=c++17 
LDFLAGS:=$(LDFLAGS) 
LDLIBS:=$(LDLIBS) -lpthread 

-std=c++17是告诉编译器要使用 C++ 17 标准来编译代码。

这里只是引入原项目中的变量,后面还会对变量进一步设置

(3)提取目标依赖项

SRCS:=$(wildcard *.cpp *.cc *.c)
OBJS:=$(patsubst %.cpp,%.o,$(SRCS))
OBJS:=$(patsubst %.cc,%.o,$(OBJS))
OBJS:=$(patsubst %.c,%.o,$(OBJS)) 

1、wildcard 函数:

当Makefile中的文件列表依赖于wildcard函数获取的结果时,添加或删除符合模式的文件后,make命令会自动重新构建相关的目标。这对于管理项目中的文件更新非常方便,

2、patsubst函数:

在 Makefile 中,patsubst是一个文本处理函数,用于模式替换。它的主要作用是将文本中的一种模式替换为另一种模式。
语法格式为:$(patsubst <pattern>,<replacement>,<text>)。
其中<pattern>是要匹配的模式,<replacement>是替换后的内容,<text>是要进行处理的原始文本,可以是变量或者字符串列表。

即我们这里第一个patsubst是把SRCS里的.cpp文件替换成对应的.o文件

后面的也都一样

(4)区分动态静态库

ifeq ($(LIBTYPE),.so)
	TARGET:=lib$(strip $(TARGET)).so  
	LDLIBS:=$(LDLIBS) -shared
	CXXFLAGS:=$(CXXFLAGS) -fPIC
endif
ifeq ($(LIBTYPE),.a)
	TARGET:=lib$(strip $(TARGET)).a  
endif

变量LIBTYPE是在原项目中设定变量,用于确定要编译为什么库

ifeq的功能是对比两个字符是否相等,在上一章节也已经提到过

当传进来的LIBTYPE是.so,说明要编译的是动态库

动态库和静态库用到的变量和参数也都已经在上一章节讲解过,这里说下用到的新函数strip

1、strip函数

它的主要作用是去除字符串开头和结尾的空格(包括空格、制表符等空白字符)。这在处理文件路径、变量值等可能包含多余空白字符的字符串时非常有用。

(5)目标生成

$(TARGET):$(OBJS)
ifeq ($(LIBTYPE),.a)
	$(AR) -cvr $@ $^
else
	$(CXX) $(LDFLAGS) $^ -o $@  $(LDLIBS)
endif

这里也通过LIBTYPE来决定是生成动态库路还是静态库

变量和参数也都在上一章节提到过啦

(6)完整配置makefile

最后的clean和伪目标的设置也已经用过很多次,就不再提了

ifndef TARGET
TARGET:=$(notdir $(shell pwd)) #test_include
endif

CXXFLAGS:=$(CXXFLAGS) -I../../include -std=c++17 
LDFLAGS:=$(LDFLAGS) 
LDLIBS:=$(LDLIBS) -lpthread 


SRCS:=$(wildcard *.cpp *.cc *.c) 
OBJS:=$(patsubst %.cpp,%.o,$(SRCS)) 
OBJS:=$(patsubst %.cc,%.o,$(OBJS))
OBJS:=$(patsubst %.c,%.o,$(OBJS)) 

ifeq ($(LIBTYPE),.so) 
	TARGET:=lib$(strip $(TARGET)).so  
	LDLIBS:=$(LDLIBS) -shared
	CXXFLAGS:=$(CXXFLAGS) -fPIC
endif
ifeq ($(LIBTYPE),.a)
	TARGET:=lib$(strip $(TARGET)).a  
endif


$(TARGET):$(OBJS)
ifeq ($(LIBTYPE),.a) 
	$(AR) -cvr $@ $^
else
	$(CXX) $(LDFLAGS) $^ -o $@  $(LDLIBS)
endif

#rm -r test.o test

clean:
	$(RM) $(OBJS)  $(TARGET) 

.PHONY: clean 

(三)使用配置的makefile

把上一章节Test_s_lib的makefile和Test_d_lib的makefile都换成这章的makefile

ifeq ($(STATIC),1)
LIBTYPE=.a
else
LIBTYPE=.so
endif
include ../makefile.mk
LIBTYPE=.so
include ../makefile.mk

 然后

再执行上章节写好的make就可以直接编译啦

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 91gzw.com 版权所有 湘ICP备2023023988号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务