C++Linux系统编程——makefile

Makefile

Makefile简介

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。

Makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

make主要解决两个问题:

*1) 大量代码的关系维护*

大项目中源代码比较多,手工维护、编译时间长而且编译命令复杂,难以记忆及维护

把代码维护命令及编译命令写在makefile文件中,然后再用make工具解析此文件自动执行相应命令,可实现代码的合理编译

*2) 减少重复编译时间*

n 在改动其中一个文件的时候,能判断哪些文件被修改过,可以只对该文件进行重新编译,然后重新链接所有的目标文件,节省编译时间

Makefile文件命名规则

makefile和Makefile都可以,推荐使用Makefile。

make工具的安装

sudo apt install make

Makefile语法规则

规则

目标:依赖文件列表

命令列表

Makefile基本规则三要素:

1)目标:

  • 通常是要产生的文件名称,目标可以是可执行文件或其它obj文件,也可是一个动作的名称

2)依赖文件:

  • 用来输入从而产生目标的文件

  • 一个目标通常有几个依赖文件(可以没有)

3)命令:

  • make执行的动作,一个规则可以含几个命令(可以没有)

  • 有多个命令时,每个命令占一行

举例说明:

测试代码:

test:
    echo "hello world"
   
test:test1 test2
    echo "test"
test1:
    echo "test1"
test2:
    echo "test2"

Make命令格式

make是一个命令工具,它解释Makefile 中的指令(应该说是规则)。

make命令格式:

make -f file [ targets ]

1.[ -f file ]:

  • make默认在工作目录中寻找名为GNUmakefile、makefile、Makefile的文件作为makefile输入文件

  • -f 可以指定以上名字以外的文件作为makefile输入文件

l

2.[ options ]

  • -v: 显示make工具的版本信息

  • -w: 在处理makefile之前和之后显示工作路径

  • -C dir:读取makefile之前改变工作路径至dir目录

  • -n:只打印要执行的命令但不执行

  • -s:执行但不显示执行的命令

3.[ targets ]:

  • 若使用make命令时没有指定目标,则make工具默认会实现makefile文件内的第一个目标,然后退出

  • 指定了make工具要实现的目标,目标可以是一个或多个(多个目标间用空格隔开)。

Makefile工作原理

1)若想生成目标, 检查规则中的依赖条件是否存在,如不存在,则寻找是否有规则用来 生成该依赖文件

2) 检查规则中的目标是否需要更新,必须先检查它的所有依赖,依赖中有任一个被更新,则目标必须更新

总结:

  • 分析各个目标和依赖之间的关系

  • 根据依赖关系自底向上执行命令

  • 根据修改时间比目标新,确定更新

  • 如果目标不依赖任何条件,则执行对应命令,以示更新

Makefile示例

测试程序: test.c add.c sub.c mul.c div.c

最简单的Makefile

test:test.c add.c sub.c mul.c div.c
    gcc test.c add.c sub.c mul.c div.c -o test

缺点:效率低,修改一个文件,所有文件会被全部编译

Makefile中变量

在Makefile中使用变量有点类似于C语言中的宏定义,使用该变量相当于内容替换,使用变量可以使Makefile易于维护,修改内容变得简单变量定义及使用。

自定义变量

1)定义变量方法:

变量名=变量值

2)引用变量:

$(变量名)或${变量名}

3)makefile的变量名:

  • makefile变量名可以以数字开头

  • 变量是大小写敏感的

  • 变量一般都在makefile的头部定义

  • 变量几乎可在makefile的任何地方使用

示例:

#变量
OBJS=add.o sub.o mul.o div.o test.o
TARGET=test
​
$(TARGET):$(OBJS)
    gcc $(OBJS) -o $(TARGET) 
​
add.o:add.c
    gcc -c add.c -o add.o
​
sub.o:sub.c
    gcc -c sub.c -o sub.o
​
mul.o:mul.c
    gcc -c mul.c -o mul.o
​
div.o:div.c
    gcc -c div.c -o div.o
​
test.o:test.c
    gcc -c test.c -o test.o
​
clean:
    rm -rf $(OBJS) $(TARGET)

除了使用用户自定义变量,makefile中也提供了一些变量(变量名大写)供用户直接使用,我们可以直接对其进行赋值。

CC = gcc #arm-linux-gcc

CPPFLAGS : C预处理的选项 如:-I

CFLAGS: C编译器的选项 -Wall -g -c

LDFLAGS : 链接器选项 -L -l

自动变量

  • $@: 表示规则中的目标

  • $<: 表示规则中的第一个条件

  • $^: 表示规则中的所有条件, 组成一个列表, 以空格隔开,如果这个列表中有重复的项则消除重复项。

注意:自动变量只能在规则的命令中中使用

#变量
OBJS=add.o sub.o mul.o div.o test.o add.o
TARGET=test
CC=gcc
​
#$@: 表示目标
#$<: 表示第一个依赖
#$^: 表示所有的依赖
​
$(TARGET):$(OBJS)
    #$(CC) $(OBJS) -o $(TARGET) 
    $(CC) $^ -o $@
    echo $@
    echo $<
    echo $^
​
add.o:add.c
    $(CC) -c $< -o $@ 
​
sub.o:sub.c
    $(CC) -c $< -o $@ 
​
mul.o:mul.c
    $(CC) -c $< -o $@ 
​
div.o:div.c
    $(CC) -c $< -o $@ 
​
test.o:test.c
    $(CC) -c $< -o $@
​
clean:
    rm -rf $(OBJS) $(TARGET)

模式规则

模式规则示例:

%.o:%.c

$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

Makefile第三个版本:

OBJS=test.o add.o sub.o mul.o div.o
TARGET=test
$(TARGET):$(OBJS)
    gcc $(OBJS) -o $(TARGET) 
​
%.o:%.c
    gcc -c $< -o $@

Makefile中函数

  1. wildcard – 查找指定目录下的指定类型的文件

src = $(wildcard *.c) //找到当前目录下所有后缀为.c的文件,赋值给src

  1. patsubst – 匹配替换

obj = $(patsubst %.c,%.o, $(src)) //把src变量里所有后缀为.c的文件替换成.o

第四个版本

SRC=$(wildcard *.c)
OBJS=$(patsubst %.c, %.o, $(SRC))
TARGET=test
$(TARGET):$(OBJS)
    gcc $(OBJS) -o $(TARGET) 
​
%.o:%.c
    gcc -c $< -o $@

Makefile中伪目标

clean用途: 清除编译生成的中间.o文件和最终目标文件

make clean 如果当前目录下有同名clean文件,则不执行clean对应的命令,解决方案:

伪目标声明: .PHONY:clean

clean命令中的特殊符号:

  • “-”此条命令出错,make也会继续执行后续的命令。如:“-rm main.o”

  • “@”不显示命令本身,只执行命令。如:“@echo clean done”

SRC=$(wildcard *.c)
OBJS=$(patsubst %.c, %.o, $(SRC))
TARGET=test
$(TARGET):$(OBJS)
    gcc $(OBJS) -o $(TARGET) 
​
%.o:%.c
    gcc -c $< -o $@
.PHONY:clean
clean:
    rm -rf $(OBJS) $(TARGET)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/615745.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Django实现的校园疫情监控平台

基于Django实现的校园疫情监控平台 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系统功能实现 登录注册功能 用户在没有登录自己的用户名之前只能浏览本网站的首页&#xff0c;想要使用其他功能都会…

sqli-labs靶场第十四关

目录 1&#xff1a;分析 找闭合符&#xff1a; 2&#xff1a;开始注入 报错注入&#xff1a; 注入数据库名&#xff1a; 注入表名&#xff1a; 注入列名&#xff1a; 注入具体值&#xff1a; 1&#xff1a;分析 经过我们的实验发现当我们输入的密码后面存在双引号时会报…

构建内网yum仓库

1、环境介绍 系统&#xff1a;龙蜥os 7.9 2、安装epel源 yum install epel-release -y3、安装nginx服务器并启动 yum install nginx httpd -y配置 server {listen 80;server_name repo.wtown.com;root /usr/share/nginx/html/repo;index index.html index.htm;location / {…

阿里云ECS服务器实例挂载数据盘步骤(磁盘自动挂载.、访问挂载点)

阿里云ECS服务器实例挂载数据盘步骤 相关指令 df -h 查看磁盘空间 du -sh * 查看使用内存大小1.磁盘自动挂载 首先登录阿里云ECS服务器&#xff0c;通过 df -h 命令查看当前磁盘挂载情况 通过 fdisk -l 命令查看磁盘情况&#xff0c;可以发现有两个盘&#xff1a; 系统盘 …

Ubuntu 和 Windows之间无法复制粘贴问题解决方法

需要安装open-vm-tools&#xff0c;官方安装open-vm-tools的网址&#xff1a;安装 Open VM Tools (vmware.com)

安全测试工具Nessus安装和使用

安装 下载地址&#xff1a;https://pan.baidu.com/s/1OaYMDdQqYI4BbZ_uUErrTw 提取码: yg2g 安装Nessus-8.14.0-x64.msi&#xff0c;按照提示next至安装完成&#xff0c;显示如下页面&#xff0c;点击Connect via SSL 点击“高级”、“继续访问” 选择 【Managed Scanner】选…

Visual Studio,第1个hello world,入门C++,分别编译一个可以在Windows和Linux下运行的程序

本人的VxTerm&#xff0c;是在Visual Studio 2022下编写的。 其它的语言工具是不是也可以那么方便的使用&#xff0c;本人并不得而知&#xff0c;至少本人能知道&#xff1a;对于我来说&#xff0c;Visual Studio可以让我觉得C/C语言非常简单&#xff01; 一、安装Visual Stu…

stm32——OLED篇

技术笔记&#xff01; 一、OLED显示屏介绍&#xff08;了解&#xff09; 1. OLED显示屏简介 二、OLED驱动原理&#xff08;熟悉&#xff09; 1. 驱动OLED驱动芯片的步骤 2. SSD1306工作时序 三、OLED驱动芯片简介&#xff08;掌握&#xff09; 1. 常用SSD1306指令 2. …

apache atlas 如何自定义hook

atals 是开源的数据元数据和数据资产管理平台&#xff0c;平台设计支持强大的图数数据库&#xff0c;nosql&#xff0c;和搜索引擎3个组件构建。都是基于开源构建。 目前市场上开源的元数据管理工具有Atlas&#xff0c; Datahub&#xff0c; Openmetadata等&#xff0c;你要说二…

进程间通信:连接不同程序世界的桥梁

目录 一、进程间通信的重要性 二、常见的进程间通信方式 三、进程间通信的目的 四、进程间通信的本质 在计算机编程的领域中&#xff0c;进程间通信&#xff08;Inter-Process Communication&#xff0c;IPC&#xff09;是一个至关重要的概念。当我们在操作系统中运行多个程…

Vue中进行粘贴板粘贴数据(图片、文字等)

在页面中如果需要进行粘贴数据&#xff0c;那么就要读取系统粘贴板clipboard&#xff0c;通过此Api来进行粘贴板数据的操作。 目录: 一.封装相关函数1.示例代码&#xff1a;2.代码解释&#xff1a; 二.页面中进行粘贴1.代码示例&#xff1a;2.代码解释&#xff1a; 三.运行结果…

linux day 3

touch 创建文件命令 cat命令&#xff0c;查看文件内容 more命令&#xff0c;查看文件内容。 cat是直接全部显示出来&#xff0c;more是支持翻页&#xff0c;即文件内容过多可以一页一页显示&#xff08;按空格翻页&#xff0c;按Q进行退出&#xff09; cp命令&#xff0c;复制…

数据结构深入理解--栈

目录 一、栈的定义 二、栈的实现 2.1 栈的结构 2.2 栈的初始化 2.3 栈的销毁 2.3 栈元素的插入 2.4 栈元素的删除 2.5 栈顶元素获取 2.6 栈元素有效个数获取 2.7 栈是否为空判断 三、代码总览 Stack.h Stack.c 测试代码:test.c 四、例题 例一&#xff1a; 例二&#xff…

llm.c的Makefile

源码 CC ? clang CFLAGS -Ofast -Wno-unused-result -Wno-ignored-pragmas -Wno-unknown-attributes LDFLAGS LDLIBS -lm INCLUDES CFLAGS_COND -marchnative# Find nvcc SHELL_UNAME $(shell uname) REMOVE_FILES rm -f OUTPUT_FILE -o $ CUDA_OUTPUT_FILE -o $# N…

5.神经网络-激活函数

目录 1. 激活函数不是阶跃函数 1.1 激活函数和阶跃函数都是非线性函数 1.2 激活函数不是阶跃函数 2. sigmoid 函数 2.1 sigmoid 函数表达式 2.2 sigmoid 函数 Python 实现 2.4 sigmoid 函数图 3. ReLU 函数 3.1 ReLU 函数表达式 3.2 ReLU 函数 Python 实现 3.4 ReLU…

Chatgpt的应用场景

文案创作类&#xff1a; 作为一名大型语言模型&#xff0c;ChatGPT可以为使用者提供多种文本处理和文字创作方面的服务&#xff0c;例如&#xff1a; 文本生成和创作 ChatGPT可以基于您提供的主题、关键词或文本段落&#xff0c;生成符合使用者要求的新文本。这些文本可以是文…

Golang | Leetcode Golang题解之第83题删除排序链表中的重复元素

题目&#xff1a; 题解&#xff1a; func deleteDuplicates(head *ListNode) *ListNode {if head nil {return nil}cur : headfor cur.Next ! nil {if cur.Val cur.Next.Val {cur.Next cur.Next.Next} else {cur cur.Next}}return head }

C++的数据结构(二)

一、链表的基本概念 链表&#xff08;Linked List&#xff09;是一种物理存储单元上非连续的、非顺序的线性数据结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列节点&#xff08;链表中每一个元素称为节点&#xff09;组成&#xff0c;节点…

(二刷)代码随想录第4天|24. 两两交换链表中的节点 ● 19.删除链表的倒数第N个节点

24. 两两交换链表中的节点 24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 帮你把链表细节学清楚&#xff01; | LeetCode&#xff1a;24. 两两交换链表中的节点_哔哩哔哩_bilibili 给你一个链表&#xff0c;两两交换其…

【计算机网络】物理层传输介质 习题3

双绞线是用两根绝缘导线绞合而成的&#xff0c;绞合的目的是( )。 A.减少干扰 B.提高传输速度 C.增大传输距离 D.增大抗拉强度 在电缆中采用屏蔽技术带来的好处主要是( ) A.减少信号衰减 B. 减少电磁干扰辐射 C.减少物理损坏 D. 减少电缆的阻抗 利用一根同轴电缆互连主机构成…