服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++学习进阶之Makefile基础用法详解

C++学习进阶之Makefile基础用法详解

2021-11-24 15:31Warrior-K C/C++

Makefile 通常指的是一个含有一系列命令(directive)的,通过 Make自动化编译工具,帮助 C/C++ 程序实现自动编译目标文件的文件,这篇文章主要给大家介绍了关于C++学习进阶之Makefile基础用法的相关资料,需要的朋友可以参考下

1. Makefile基本语法与执行

为什么要使用 Makefile?

Makefile 文件描述了整个工程的编译、链接的规则。

为工程编写 Makefile 的好处是能够使用一行命令来完成“自动化编译”。只需提供一个(通常对于一个工程来说会是多个)正确的 Makefile,接下来每次的编译都只需要在终端输入“make”命令,整个工程便会完全自动编译,极大提高了效率。尤其是在编译一个仅有一小部分文件被改动过的大项目的情况下。

绝大多数的 IDE 开发环境都会为用户自动编写 Makefile。

Make 是怎么工作的?

Make 工作的原则就是:

一个目标文件当且仅当在其依赖文件(dependencies)的更改时间戳比该目标文件的创建时间戳新时,这个目标文件才需要被重新编译。

Make 工具会遍历所有的依赖文件,并且把它们对应的目标文件进行更新。编译的命令和这些目标文件及它们对应的依赖文件的关系则全部储存在 Makefile 中。

Makefile 中也指定了应该如何创建,创建出怎么样的目标文件和可执行文件等信息。

除此之外,你甚至还可以在 Makefile 中储存一些你想调用的系统终端的命令,像一个 Shell 脚本一样使用它。

作用:

Makefile 文件告诉 Make 怎样编译和连接成一个程序

可用命令 dnf install make 安装make功能

格式:

按如下格式编写 Makefile

目标(target): 依赖(prerequiries)...
  命令(command)

注意:每个命令行前面必须是一个Tab字符,即命令行第一个字符是Tab

实验:

vim Makefile 编辑文件:

?
1
2
3
4
5
6
simpletest:simple.o simpletest.o
        g++ simple.o simpletest.o -o simpletest
simple.o:simple.cpp
        g++ -c simple.cpp -o simple.o
simpletest.o:simpletest.cpp
        g++ -c simpletest.cpp -o simpletest.o

结果为:

[root@foundation1 shishi]# make
g++ -c simple.cpp -o simple.o
g++ -c simpletest.cpp -o simpletest.o
g++ simple.o simpletest.o -o simpletest

命令上下是有顺序的,上一行对下一行具有依赖关系

如果文件夹中已经有.o文件,make后会提示已经生成,需要删除.o文件后再make

clean的作用: 被指定时会删除对应.o文件,避免上述情况

?
1
2
3
4
5
6
7
8
simpletest:simple.o simpletest.o
        g++ simple.o simpletest.o -o simpletest
simple.o:simple.cpp
        g++ -c simple.cpp -o simple.o
simpletest.o:simpletest.cpp
        g++ -c simpletest.cpp -o simpletest.o
clean:
        rm simpletest simple.o simpletest.o

结果为:

[root@foundation1 shishi]# make clean
rm simpletest simple.o simpletest.o
[root@foundation1 shishi]# make
g++ -c simple.cpp -o simple.o
g++ -c simpletest.cpp -o simpletest.o
g++ simple.o simpletest.o -o simpletest

2. Makefile简化过程

使用变量: 如果调用某个文件用的次数较多,可以使用变量代替,变量可以直接替换

变量定义: 变量 = 字符串
变量使用: $(变量名)

makefile 文件可改为:

?
1
2
3
4
5
6
7
8
9
10
11
TARGET = simpletest
OBJS = simple.o simpletest.o
 
$(TARGET):$(OBJS)
        g++ $(OBJS) -o $(TARGET)
simple.o:simple.cpp
        g++ -c simple.cpp -o simple.o
simpletest.o:simpletest.cpp
        g++ -c simpletest.cpp -o simpletest.o
clean:
        rm $(TARGET) $(OBJS)

命令自动推导: 我们可以发现,由于 .cpp 文件都是生成对应的 .o 文件,所以 makefile 文件是可以自动识别的

makefile 文件可改为:

?
1
2
3
4
5
6
7
8
9
TARGET = simpletest
OBJS = simple.o simpletest.o
 
$(TARGET):$(OBJS)
        g++ $(OBJS) -o $(TARGET)
simple.o:simple.cpp
simpletest.o:simpletest.cpp
clean:
        rm $(TARGET) $(OBJS)

预定义变量: 系统中自己也定义了一些变量

变量 程序 默认值
CC C语言编译程序 cc
CXX C++编译程序 g++
AR C++打包程序 ar
CPP 带有标准输出的C语言预处理程序 $(CC) -E
RM 删除命令 rm

makefile 文件可改为:

?
1
2
3
4
5
6
7
8
9
TARGET = simpletest
OBJS = simple.o simpletest.o
 
$(TARGET):$(OBJS)
        $(CXX) $(OBJS) -o $(TARGET)
simple.o:simple.cpp
simpletest.o:simpletest.cpp
clean:
        $(RM) $(TARGET) $(OBJS)

假想目标: 如果文件夹中有clean文件,那么make clean就不能使用,需要使用假想目标,可以在执行命令时不查看文件夹里面的文件,直接生效

makefile 文件可改为:

?
1
2
3
4
5
6
7
8
9
10
11
TARGET = simpletest
OBJS = simple.o simpletest.o
 
.PHONY: clean
 
$(TARGET):$(OBJS)
        $(CXX) $(OBJS) -o $(TARGET)
simple.o:simple.cpp
simpletest.o:simpletest.cpp
clean:
        $(RM) $(TARGET) $(OBJS)

建议不生成目标文件的命令都设为假想目标

3. Makefile生成并使用库

3.1 动态库的建立与使用

vim Makefile 编辑文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TARGET = simpletest
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
 
.PHONY: clean
 
$(TARGET):$(LIB) simpletest.o
        $(CXX) simpletest.o -o $(TARGET) -L. -lsimple
$(LIB):$(OBJS)
        $(CXX) -shared $(OBJS) -o $(LIB)
simple.o:simple.cpp
        $(CXX) $(CXXFLAGS) simple.cpp -o $(OBJS)
simpletest.o:simpletest.cpp
        $(CXX) $(CXXFLAGS) simpletest.cpp -o simpletest.o
clean:
        $(RM) $(TARGET) $(OBJS) $(LIB)

结果为:

[root@foundation1 shishi]# make clean
rm -f simpletest simple.o libsimple.so
[root@foundation1 shishi]# make
g++ -c -fPIC simple.cpp -o simple.o
g++ -shared simple.o -o libsimple.so
g++ -c -fPIC simpletest.cpp -o simpletest.o
g++ simpletest.o -o simpletest -L. -lsimple

预定义变量:

还是需要在前面定义

变量 程序参数
CFLAGS 用于C编译器的额外标志
CXXFLAGS 用于C++编译器的额外标志
ARFLAGS 用于C/C++打包器的额外标志
LDFLAGS 链接库路径-L
LDLIBS 链接库-l

makefile 文件可改为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
TARGET = simpletest
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
LDFLAGS = -L.
LDLIBS = -lsimple
 
.PHONY: clean
 
$(TARGET):$(LIB) simpletest.o
        $(CXX) simpletest.o -o $(TARGET) $(LDFLAGS) $(LDLIBS)
$(LIB):$(OBJS)
        $(CXX) -shared $(OBJS) -o $(LIB)
simple.o:simple.cpp
        $(CXX) $(CXXFLAGS) simple.cpp -o $(OBJS)
simpletest.o:simpletest.cpp
        $(CXX) $(CXXFLAGS) simpletest.cpp -o simpletest.o
clean:
        $(RM) $(TARGET) $(OBJS) $(LIB)

自动变量:

自动变量是在规则每次执行时都基于目标和依赖产生新值的变量

自动变量 含义
$< 表示第一个匹配的依赖
$@ 表示目标
$^ 所有依赖
$? 所有依赖中更新的文件
$+ 所有依赖文件不去重
$(@D) 目标文件路径
$(@F) 目标文件名称

makefile 文件可改为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
TARGET = simpletest
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
LDFLAGS = -L.
LDLIBS = -lsimple
 
.PHONY: clean
 
$(TARGET):simpletest.o $(LIB)
        $(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS)
$(LIB):$(OBJS)
        $(CXX) -shared $^ -o $@
simple.o:simple.cpp
        $(CXX) $(CXXFLAGS) $< -o $@
simpletest.o:simpletest.cpp
        $(CXX) $(CXXFLAGS) $< -o $@
clean:
        $(RM) $(TARGET) $(OBJS) $(LIB)

自动匹配:

通配符主要用于匹配文件名,makefile中使用%作为通配符。从匹配目标格式的目标名中依据通配符抽取部分字符串,再按照抽取字符串分配到每一个依赖格式中产生依赖名。例如,使用%.o:%.cpp

可以让重复的语句合为一句

makefile 文件可改为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
TARGET = simpletest
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
LDFLAGS = -L.
LDLIBS = -lsimple
TESTOBJ = simpletest.o
 
.PHONY: clean
 
$(TARGET):$(TESTOBJ) $(LIB)
        $(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS)
 
$(LIB):$(OBJS)
        $(CXX) -shared $^ -o $@
 
$(TESTOBJ) $(OBJS):%.o:%.cpp
        $(CXX) $(CXXFLAGS) $< -o $@
 
clean:
        $(RM) $(TARGET) $(OBJS) $(LIB) $(TESTOBJ)

C++学习进阶之Makefile基础用法详解

3.2 动态加载库的建立与使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
TARGET = simpletest2
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
LDLIBS = -ldl
TESTOBJ = simpletest2.o
 
.PHONY: clean
 
# 生成可执行文件
$(TARGET):$(TESTOBJ) $(LIB)
        $(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS)
 
# 生成库
$(LIB):$(OBJS)
        $(CXX) -shared $^ -o $@
 
# 生成目标文件
$(TESTOBJ) $(OBJS):%.o:%.cpp
        $(CXX) $(CXXFLAGS) $< -o $@
 
clean:
        $(RM) $(TARGET) $(OBJS) $(LIB) $(TESTOBJ)

结果为:

[root@foundation1 C++7.4]# make clean
rm -f simpletest2 simple.o libsimple.so simpletest2.o
[root@foundation1 C++7.4]# make
g++ -c -fPIC simpletest2.cpp -o simpletest2.o
g++ -c -fPIC simple.cpp -o simple.o
g++ -shared simple.o -o libsimple.so
g++ simpletest2.o -o simpletest2  -ldl
[root@foundation1 C++7.4]# ./simpletest2
Simple()
Test()
~Simple()

总结

到此这篇关于C++学习进阶之Makefile基础用法的文章就介绍到这了,更多相关C++ Makefile基础用法内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_39398433/article/details/118614152

延伸 · 阅读

精彩推荐
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29