首页 > 系统相关 >linux开发之Make

linux开发之Make

时间:2023-04-13 17:22:30浏览次数:28  
标签:src objs %. target Make 开发 linux cpp main

简述

代码变成可执行文件,叫做编译(compile);先编译这个,还是先编译那个(即编译的安排),叫做构建(build)。
Make是最常用的构建工具,他根据makefile来行动。
makefile是一个名字叫Makefile(或makefile)的文件,它一堆规则的定义,它定义了具体该怎么编译,链接等操作。
当源代码有几十上百时,手动输入命令行编译就很麻烦。想象一下,当只有一个源文件改变,我们只需要编译这一个,然后重新链接即可。只需要输入make就能够自动等待完成。

详细一点的简述

makefile的一般规则如下(注意命令前有tab):

目标:依赖
  命令1
  命令2

如果不指定,makefile的第一个目标就是默认目标。当目标文件不存在,或者目标文件的时间在依赖之前,这就说明需要更新了,就执行命令。

最简单的例子

假设我们有main.cpp,a.cpp,b.cpp。head.h中为fun1,fun2函数的声明。

// main.cpp
#include <iostream>
#include "head.h"
int main() {
    puts("main fun");
    fun1();
    fun2();
    return 0;
}
// a.cpp
#include <iostream>
void fun1() {
    puts("This is fun1");
}
// b.cpp
#include <iostream>
void fun2() {
    puts("Here is fun2");
}

最简单的makefile:

app: main.cpp a.cpp b.cpp
	g++ main.cpp a.cpp b.cpp -o app

效果如下图,当我们需要编译时候只需要一个make语句就行。
makefile1使用

进阶一点的例子

在上面的例子中,其实一点都没有体现出来优势。我们来模拟下,工程中有好多文件时候,有时候只需要重新编译一个文件,其余的保持不变,最后链接一下。

我们把makefile改写一下:

app: main.o a.o b.o
	g++ main.cpp a.cpp b.cpp -o app
a.o: a.cpp
	g++ -c a.cpp -o a.o
b.o: b.cpp
	g++ -c b.cpp -o b.o
main.o: main.cpp
	g++ -c main.cpp -o main.o

初次构建成功:
初次构建

当我们对a.cpp进行修改后,再次构建如下图。可以看到,它只编译了a.cpp,并且进行了链接,其余没有发生改变的源文件就没有进行编译,节省了资源。
具体流程是:

  1. 检查app目标的依赖,如果遇到目标则递归检测依赖
  2. 检测到app目标的a.o目标的a.cpp文件依赖时间在a.o之后
  3. 运行a.o目标命令
  4. 运行app目标命令
    再次构建

变量

工程中那么多文件,一个个手写名字还是很麻烦的,于是可以使用变量嘿嘿

自定义变量(注意等号左右没有空格): 变量名=变量值。例如:val=hello

预定义变量 含义
AR 归档维护程序的名称,默认为ar
CC c编译器的名称,默认为cc
CXX c++编译器的名称,默认为g++
$@ 目标的完整名称
$< 第一个依赖文件
$^ 所有依赖文件
% 目标和依赖字符串通配

使用变量格式为$(变量名)

接下来我们对之前的makefile进行修改:

src=a.o b.o main.o
target=app
$(target): $(src)
	g++ $(src) -o $(target)
%.o: $.c
	$(CXX) -c $< -o $@

成功构建
用了变量

函数

虽然用了变量简单了很多,但每个目标文件的名字还是需要自己写,还是麻烦,而使用函数就可以轻松获取名字。

常用函数 作用 示例 结果
$(wildcard 参数) 获取参数位置的指定文件 wildcar .cpp ./src/cpp main.cpp a.cpp b.cpp
$(patsubst <pattern>,<replacement>,<text>) 查找text中的单词是否符合,如果符合则替换为 patsubst %.c,%.o,x.c bar.c x.o bar.o

把a.cpp,b.cpp放到src文件夹下,然后对我们的makefile再做一点改动:

src=$(wildcard *.cpp ./src/*.cpp)
objs=$(patsubst %.cpp, %.o, $(src))
target=app
$(target): $(objs)
	g++ $(objs) -o $(target)
%.o: $.c
	$(CXX) -c $< -o $@

构建过程:
加了函数的构建

清理以及伪目标

当你想把源码发给别人时候,只想有纯净的代码,不想有目标文件,可执行文件等,那么就可以通过make设定一个clean目标来进行清理。

src=$(wildcard *.cpp ./src/*.cpp)
objs=$(patsubst %.cpp, %.o, $(src))
target=app
$(target): $(objs)
	g++ $(objs) -o $(target)
%.o: $.c
	$(CXX) -c $< -o $@
clean:
	rm -f $(objs) $(target)

如图,可以看到成功清理了其他东西。
清理1

但是,如果当前文件夹下有一个名字叫clean的文件会发生什么?
clean目标没有依赖,当检测时候发现没有任何依赖比clean文件的时间更新,所以clean文件就是最新的。
无法clean

解决方法为将clean目标声明为伪目标,指不是真的要生成文件

src=$(wildcard *.cpp ./src/*.cpp)
objs=$(patsubst %.cpp, %.o, $(src))
target=app
$(target): $(objs)
	g++ $(objs) -o $(target)
%.o: $.c
	$(CXX) -c $< -o $@
.PHONY:clean  # 伪目标
clean:
	- rm -f $(objs) $(target)  # 命令前加 - 表示如果执行遇到问题了继续不用管
	-@echo "cleaned!"

clean成功

标签:src,objs,%.,target,Make,开发,linux,cpp,main
From: https://www.cnblogs.com/1v7w/p/17315235.html

相关文章

  • windows上编写shell拷到linux执行报错
    1.最近随手在windows写了个自动安装docker的shell脚本,然后传到linux服务器执行竟然报以下错  2.进入vim查看突然看到下截图红色框地方 最后查阅资料发现,这个标志的产生原因是因为在windows下,文件的换行符是\r\n,而在linux下换行符是\n,所以,使用cat-Ainstall_docker.sh......
  • 【web 开发基础】PHP 中的特殊流程控制(continue) -PHP 快速入门 (21)
    continue语句continue语句只能用于循环语句内部,功能是跳过本次循环继续执行下一次循环结构,而不终止整个循环的执行。在while和do...while语句中,continue语句跳转到循环条件处开始继续执行,对于for循环随后的动作是变量更新。流程图如下:continue的语法如下:continue[label];可选的......
  • linux入门2
       1.创建链接文件xiang指向hunan[root@blueendingnovalianxi]#mkdirhunan[root@blueendingnovalianxi]#ln-shunanxiang[root@blueendingnovalianxi]#llxianglrwxrwxrwx1rootroot54月1315:43xiang->hunaln   创建链接文件  link 可以给文......
  • [Linux]veth是什么?
    vethpair是什么?vethpair(VirtualEthernetPair)是一种Linux内核技术,可用于将两个虚拟网络接口连接在一起,从而可以在两个不同的命名空间之间进行通信。它常常被用于容器的实现,比如Docker中的容器网络,以提供网络隔离和互联。vethpair包括两个虚拟网络接口,这两个网络接口......
  • linux操作系统和linux内核
    linux内核并非操作系统,是操作系统的基本,负责对计算机硬件进行管理,并且提供了使用这些硬件资源的通用接口。主要管理如下几个方面:1. 内存管理:追踪记录有多少内存存储了什么以及存储在哪里2. 进程管理:其实就是对cpu的管理,即确定哪些进程可以使用中央处理器......
  • [Linux]有哪些常见的System Call?
    Linux中有许多Systemcall,以下是其中的一些常见的Systemcall:open:打开一个文件close:关闭一个文件read:从文件中读取数据write:将数据写入文件lseek:控制文件位置指针fcntl:操作文件描述符标识socket:创建一个套接字connect:建立一个连接bind:将一个套接字绑定到一个地址lis......
  • tinymix使用 嵌入式linux tinyplay控制音频
    tinymix控制声音大小使用方法使用字符方式保险  tinymix"LINEOUTvolume""2"有的是输入int但是此处输入输入int时,不行,使用字符串输入可以正常修改 输入tinymix查看选项和使用方法 root@/test_utils/alsa#tinymixMixername:'audiocodec'Numberofcontrols:......
  • linux的一些命令(入门)
       1.查看linux内核的版本[root@blueendingnova~]#cat/etc/centos-releaseCentOSLinuxrelease7.9.2009(Core)   2.查看linux系统的版本[root@blueendingnova~]#uname-r3.10.0-1160.el7.x86_64   3.查询passwd命令存放的路径[root@blueendingnov......
  • 实现数字化转型升级,快速开发平台流辰信息来助力!
    在如今迅猛发展的年代里,科技的力量是伟大的,可以让老百姓的生活变得丰富多彩,也可以让各行各业的企业实现办公自动化,朝着数字化转型升级,快速提升办公协作效率。快速开发平台流辰信息作为一家低代码平台服务商,深知肩上所扛的责任与义务,将秉承初心,持续奋斗,创新研发,为行业的进步和用户......
  • 餐饮小程序系统开发有哪些作用?五个作用非常突出
     众所周知,餐饮行业的商家非常适合开发一个餐饮小程序系统,可以给商家带来很大的帮助。那么餐饮小程序系统开发有哪些作用?今天名锐讯动为大家介绍五个作用非常突出。 1.定位服务。如果用户想要到店就餐却不知道商家门店的具体位置该怎么办呢?一旦没有解决这个问题,那么商家门店在......