Makefile快速上手

news2024/12/1 9:04:41

Makefile学习

https://maxwell-lx.vip/basic-usage-make/

https://zhuanlan.zhihu.com/p/92010728

https://zhuanlan.zhihu.com/p/350297509

一、是什么

可以理解为一个自动化的编译脚本,避免繁琐的手动编译过程。有点类似shell脚本。

1.1 从小例子入手

(1)新建项目文件夹hello,及文件main.cppfactorial.cppprinthello.cppfunctions.h

hello目录的结构如下:

hello/
├──main.cpp
├──factorial.cpp
├──printhello.cpp
└──functions.h

main.cpp

#define _FUNCTIONS_H_

#include <iostream>
#include "functions.h"
using namespace std;

int main()
{
	printhello();
	
	cout << "This is main:" << endl;
	cout << "The factorial of 5 is:" << factorial(5) << endl;
	return 0;
}

printhello.cpp

#include <iostream>
#include "functions.h"
using namespace std;

void printhello()
{
	int i;
	cout << "Hello World!" << endl;
}

factorial.cpp

#include "functions.h"

int factorial(int n)
{
	if (n==1)
		return 1;
	else
		return n * factorial(n-1);
}

function.h

#ifdef _FUNCTIONS_H_
#define _FUNCTIONS_H_
void printhello();
int factorial(int n);
#endif

(2)那么我们一般手动执行的命令为:

g++ main.cpp factorial.cpp printhello.cpp -o main
./main

这种方法适用于小型项目。对于大型项目来说,此法编译效率低,

(3)新建Makefile

hello: main.cpp printhello.cpp factorial.cpp
	g++ -o hello main.cpp printhello.cpp factorial.cpp

在命令行上直接运行make命令就能出现hello可执行文件

二、Makefile解析

2.1 大致了解一个Makefile

对于一个初学者,大概浏览一个makefile:

1、区分前处理/变量处理(根据规则定义或处理参数) 。

2、找到target: 包含了冒号(colon :)。arget都是顶格抒写的, " : <***> " , target下面的带[tab]缩进的行,就是它包含的命令,找到所有的target。

3、执行target: 一般是实现第一个target,(也可以用make 指定,如make clean,就只执行"clean" 这个target)。

2.2 Makefile的语法

简单的分为三个部分:目标、依赖、命令

[目标]: [依赖]
(tab制表符)[命令]
  • 目标:规则的目标,可以是 Object File(一般称它为中间文件),也可以是可执行文件,还可以是一个标签;
  • 依赖:可以是生成 targets 需要的文件或者是目标。可以是多个,也可以是没有;
  • 命令:make 需要执行的命令(任意的 shell 命令)。可以有多条命令,每一条命令占一行。

2.3 工作原理

从第一个target开始,检查它的依赖是否都存在,如果存在的话就执行当前target下的命令。

否则就往下查找,寻找新规则生成依赖。

三、实战

3.1 version1

hello: main.cpp printhello.cpp factorial.cpp
	g++ -o hello main.cpp printhello.cpp factorial.cpp

版本1就相当于普通的编译命令。

3.2 version2

CXX = g++
TARGET = hello 
OBJ = main.o printhello.o factorial.o

$(TARGET): $(OBJ)
	$(CXX) -o $(TARGET) $(OBJ)

main.o: main.cpp
	$(CXX) -c main.cpp

printhello.o: printhello.cpp
	$(CXX) -c printhello.cpp

factorial.o: factorial.cpp
	$(CXX) -c factorial.cpp

版本2分离编译器、目标、对象,但是还是不够智能。增加一个cpp文件需要改动的地方很多。

3.3 version3

CXX = g++
CXXFLAGS = -c -Wall
TARGET = hello 
OBJ = main.o printhello.o factorial.o

$(TARGET): $(OBJ)
	$(CXX) -o $@ $^

%.o: %.cpp
	$(CXX) $(CXXFLAGS) $< -o $@

.PHONY: clean
clean:
	rm -f *.o $(TARGET)

版本3引入了自动变量、通配符、.PONY

(1)自动变量小撇:

目标: 依赖
  • $@ 目标名
  • $^ 所有依赖的文件名
  • $< 第一个依赖的文件名

(2)通配符%,匹配0个或多个任意字符。

(3).PHONY的作用比较特殊,跟在它后面的目标都被称为伪目标

如果 make 伪目标,不管该目录下是否有伪目标同名的文件(即使有也不会产生冲突),都会执行执行伪目标的依赖的命令。

3.4 version4

CXX = g++
TARGET = hello 
SRC = $(wildcard *.cpp)
OBJ = $(patsubst %.cpp, %.o, $(SRC))

CXXFLAGS = -c -Wall

$(TARGET): $(OBJ)
	$(CXX) -o $@ $^

%.o: %.cpp
	$(CXX) $(CXXFLAGS) $< -o $@

.PHONY: clean
clean:
	rm -f *.o $(TARGET)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

B058-SpringBoot

目录 springboot概念与作用入门案例springboot运行方式热部署配置文件Profile多环境支持整合测试-springboot-testSpringboot-web1.返回json数据2.返回页面&#xff08;模板技术&#xff09;thymeleaf1.导入thymeleaf依赖2.模板文件3.controller4.启动类 SSM整合1.导包2.项目目…

【Excel】快速提取某个符号前面的数据内容

【问题描述】 在使用excel整理数据过程中&#xff0c;经常与需要调整数据后&#xff0c;进行使用。 例如凭证导出后&#xff0c;科目列是包含科目编码和科目名称的。 但由于要将数据复制到其他的导入模板上使用&#xff0c;对应的模板只需要科目编码&#xff0c;不需要科目名称…

【管理运筹学】第 5 章 | 整数规划(4,指派问题)

系列文章 【管理运筹学】第 5 章 | 整数规划 &#xff08;1&#xff0c;问题提出与分支定界法&#xff09; 【管理运筹学】第 5 章 | 整数规划 &#xff08;2&#xff0c;割平面法及 0-1 变量的特性&#xff09; 【管理运筹学】第 5 章 | 整数规划 &#xff08;3&#xff0c;隐…

Win10怎样取消自动固定到快速访问?

双击桌面上此电脑在菜单栏点击查看在弹出的选项里边选择选项在打开文件资源管理器那里把快速访问改成此电脑在下面隐私部分选择快速访问中显示最近使用文件在快速访问中显示常用文件夹并且清除文件资源管理器记录就行。

调度器/调度程序

一、调度对象 1.让谁运行-调度算法 闲逛进程&#xff1a;无其他就绪进程时&#xff0c;运行闲逛进程&#xff1b;优先级最低&#xff0c;能耗低。 2.运行多长时间-时间片大小 二、调度产生时机 1.创建新进程与进程退出 2.运行进程阻塞 3.I/O中断发生&#xff0c;可能唤醒…

lv5 嵌入式开发-8 信号机制(上)

目录 1 信号机制 2 信号的产生 3 常用信号 4 相关命令 4.1 信号相关命令 kill / killall 4.2 信号发送 – kill / raise 4.3 定时器函数相关函数 – alarm /ualarm/ pause 4.4 信号捕捉&#xff1a;设置信号响应方式 – signal /sigaction&#xff0c;闹钟实现 4.5 子…

CCF CSP认证 历年题目自练Day14

CCF CSP认证 历年题目自练Day14 题目一 小明今天生日&#xff0c;他有n块蛋糕要分给朋友们吃&#xff0c;这n块蛋糕&#xff08;编号为1到n&#xff09;的重量分别为a1, a2, …, an。小明想分给每个朋友至少重量为k的蛋糕。小明的朋友们已经排好队准备领蛋糕&#xff0c;对于…

【进阶C语言】动态内存分配

本章大致内容介绍&#xff1a; 1.malloc函数和free函数 2.calloc函数 3.realloc函数 4.常见错误案例 5.笔试题详解 6.柔性数组 一、malloc和free 1.malloc函数 &#xff08;1&#xff09;函数原型 函数参数&#xff1a;根据用户的需求需要开辟多大的字节空间&#xff…

nodejs+vue 网上招聘系统elementui

第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;技术背景 5 3.2.2经济可行性 6 3.2.3操作可行性&#xff1a; 6 3.3 项目设计目标与原则 6 3.4系统流程分析 7 3.4.1操作流程 7 3.4.2添加信息流程 8 3.4.3删除信息流程 9 第4章 系统设计 11 …

【PyTorch实战演练】使用Cifar10数据集训练LeNet5网络并实现图像分类(附代码)

文章目录 0. 前言1. Cifar10数据集1.1 Cifar10数据集下载1.2 Cifar10数据集解析 2. LeNet5网络2.1 LeNet5的网络结构2.2 基于PyTorch的LeNet5网络编码 3. LeNet5网络训练及输出验证3.1 LeNet5网络训练3.2 LeNet5网络验证 4. 完整代码4.1 训练代码4.1 验证代码 0. 前言 按照国际…

Spring Boot 常用注解详解:全面指南

Spring Boot 中有许多常用的注解&#xff0c;这些注解用于配置、管理和定义 Spring Boot 应用程序的各个方面。以下是这些注解按大类和小类的方式分类&#xff0c;并附有解释和示例。 一、Spring Boot 核心注解 SpringBootApplication 解释&#xff1a;这是一个组合注解&a…

反射学习笔记

反射学习笔记 一、反射入门案例 在反射中&#xff0c;万物皆对象&#xff0c;方法也是对象。反射可以在不修改源码的情况下&#xff0c;只需修改配置文件&#xff0c;就能实现功能的改变。 实体类 /*** 动物猫类*/ public class Cat {private String name;public void hi()…

openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化:x86

文章目录 openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化&#xff1a;x8684.1 BIOS84.2 操作系统环境设置84.3 网络 openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化&#xff1a;x86 …

大学各个专业介绍

计算机类 五米高考-计算机类 注&#xff1a;此处平均薪酬为毕业五年平均薪酬&#xff0c;薪酬数据仅供参考 来源&#xff1a; 掌上高考 电气类 五米高考-电气类 机械类 五米高考-机械类 电子信息类 五米高考-电子信息类 土木类 五米高考-土木类

Cloudflare进阶技巧:缓存利用最大化

1. 引言 cloudflare我想你应该知道是什么&#xff0c;一家真正意义上免费无限量的CDN&#xff0c;至今未曾有哥们喷它的。当然&#xff0c;在国内的速度确实比较一般&#xff0c;不过这也不能怪它。 CDN最大的特色&#xff0c;我想就是它的缓存功能&#xff0c;达到防攻击&am…

【数据结构】归并排序、基数排序算法的学习知识点总结

目录 1、归并排序 1.1 算法思想 1.2 代码实现 1.3 例题分析 2、基数排序 2.1 算法思想 2.2 代码实现 2.3 例题分析 1、归并排序 1.1 算法思想 归并排序是一种采用分治思想的经典排序算法&#xff0c;通过将待排序数组分成若干个子序列&#xff0c;将每个子序列排序&#xff…

安卓玩机-----给app加注册码 app加弹窗 云注入弹窗

在对接很多工作室业务中有些客户需要在他们自带的有些app中加注册码或者验证码的需求。其实操作起来也很简单。很多反编译软件有自带的注入功能。例如注入弹窗。这个是需要对应的注册码来启动应用。而且是随机id。重新安装app后需要重新注册才可以继续使用&#xff0c;原则上可…

Ubuntu 20.04部署Promethues

sudo lsb_release -r可以看到操作系统版本是20.04&#xff0c;sudo uname -r可以看到内核版本是5.5.19。 sudo wget -c https://github.com/prometheus/prometheus/releases/download/v2.37.1/prometheus-2.37.1.linux-amd64.tar.gz下载必要的组件。 tar -zxf prometheus-2.…

python对RabbitMQ的简单使用

原文链接&#xff1a;https://blog.csdn.net/weixin_43810267/article/details/123914324 RabbitMq 是实现了高级消息队列协议&#xff08;AMQP&#xff09;的开源消息代理中间件。消息队列是一种应用程序对应用程序的通行方式&#xff0c;应用程序通过写消息&#xff0c;将消…

日常学习之:如何基于 OpenAI 构建自己的向量数据库

文章目录 原理前期准备依赖安装Pinecone 数据库注册Index 创建&#xff08;相当于传统数据库中的创建 table&#xff09; 基于 pinecone 数据库的代码实现尝试用 OpenAI 的 API 构建 embedding将示例的数据 embedding 后写入你的 pinecode &#xff08;构建向量数据库&#xff…