首页 > 其他分享 >makefile如何编写?

makefile如何编写?

时间:2024-10-30 11:47:17浏览次数:6  
标签:文件 %. 变量 make makefile 如何 clean 编写

什么是makefile?


        makefile文件中定义了一系列的规则来指定, 哪些文件需要先编译, 哪些文件需要后编译, 哪些文件需要重新编译, 甚至于进行更复杂的功能操作, 因为makefile就像一个Shell脚本一样, 其中也可以执行操作系统的命令.  makefile带来的好处就是——“自动化编译”, 一旦写好, 只需要一个make命令, 整个工程完全自动编译, 极大的提高了软件开发的效率.
        make是一个命令工具, 是一个解释makefile中指令的命令工具, 一般来说, 大多数的IDE都有这个命令, 比如:Visual C++的nmake, Linux下GNU的make. 可见, makefile都成为了一种在工程方面的编译方法.
        makefile文件中会使用gcc编译器对源代码进行编译, 最终生成可执行文件或者是库文件.

如何写makefile?

        写makefile要遵守他的规则,makefile由一组规则组成,规则如下:

目标: 依赖
(tab)命令

makefile基本规则三要素:

  • 目标: 要生成的目标文件
  • 依赖: 目标文件由哪些文件生成
  • 命令: 通过执行该命令由依赖文件生成目标

makefile中的变量

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

        makefile常见有两种类型的变量:普通变量、自带变量

普通变量:
变量定义直接用 =
使用变量值用 $(变量名)

//举例:变量的定义和使用
test= aaa			// 定义变量test并赋值为aaa
test1 = $(test)		// 使用变量, $(变量名)
//其中test1的值是test变量值的引用

除了使用用户自定义变量, makefile中也提供了一些变量(变量名大写)供用户直接使用, 我们可以直接对其进行赋值
CC = gcc     #arm-linux-gcc
CPPFLAGS : C预处理的选项 -I
CFLAGS :   C编译器的选项 -Wall -g -c
LDFLAGS :  链接器选项 -L  -l
自带变量:
$@: 表示规则中的目标
$<: 表示规则中的第一个条件
$^: 表示规则中的所有条件, 组成一个列表, 以空格隔开, 如果这个列表中有重复的项则消除重复项。
特别注意:自动变量只能在规则的命令中使用.

模式规则:至少在规则的目标定义中要包含’%’, ‘%’表示一个或多个, 在依赖条件中同样可以使用’%’, 依赖条件中的’%’的取值取决于其目标。(后边会举例子)

makefile函数

        makefile中的函数有很多, 在这里介绍两个最常用的:

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

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

makefile的清理操作

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

make clean 如果当前目录下有同名clean文件,则不执行clean对应的命令, 解决方案:
	伪目标声明: 
.PHONY:clean
	声明目标为伪目标之后, makefile将不会检查该目标是否存在或者该目标是否需要更新
	clean命令中的特殊符号:
	“-”此条命令出错,make也会继续执行后续的命令。如:“-rm main.o”
    rm -f: 强制执行, 比如若要删除的文件不存在使用-f不会报错
	“@”不显示命令本身, 只显示结果。如:“@echo clean done”
	其它
– make 默认执行第一个出现的目标, 可通过make dest指定要执行的目标
– make -f : -f执行一个makefile文件名称, 使用make执行指定的makefile: make -f mainmak

        举例:在linux下创建如下几个文件,并放到同一目录下,进行make和make clean操作。

//fun1.c代码如下:
#include <stdio.h>
void fun1()
{
    printf("this is fun1\n");	

}
//fun2.c代码如下:
#include <stdio.h>
void fun2()
{
    printf("this is fun2\n");	
}
//sum.c代码如下:
#include <stdio.h>

int sum(int len)
{
	int i = 0;
	int sum = 0;
	for(i=0; i<len; i++)
	{
		sum += i;
	}

	return sum;
}
//head.h
void fun1();
void fun2();
int sum(int len);
//main.c代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "head.h"

int main(int argc, char *argv[])
{
    printf("this is main!\n");
	int i = 0;
	for(i=0; i<argc; i++)
	{
		printf("[%d]:[%s]\n", i, argv[i]);
	}

    fun1();
    fun2();

	printf("sum(10)==[%d]\n", sum(10));

    return 0;
}

makefile里边的内容:

src=$(wildcard ./*.c)
object=$(patsubst %.c, %.o, $(src))
target=main
CC=gcc
CPPFLAGS=-I./

$(target):$(object)
	$(CC) -o $@ $^

%.o:%.c
	$(CC) -o $@ -c $< $(CPPFLAGS) 

.PHONY:clean
clean:
	-rm -f $(target) $(object)

结果如下:

编写makefile要掌握其套路,常用的方法和操作在上边已有呈现,下边是本次makefile文件编写的注释,帮助我们理解。
 

# 查找当前目录下所有的 .c 源文件
src=$(wildcard ./*.c)

# 将 src 变量中所有后缀为 .c 的文件替换为对应的 .o 文件
object=$(patsubst %.c, %.o, $(src))

# 定义目标文件名为 main,target 为普通变量
target=main

# 指定编译器为 gcc
CC=gcc

# 编译时使用的预处理器选项,包含当前目录
CPPFLAGS=-I./

# 定义 main 目标及其依赖对象
$(target): $(object)
		$(CC) -o $@ $^  # 使用 gcc 链接生成最终可执行文件

# 定义规则,将 .c 文件编译成 .o 文件
%.o: %.c
		$(CC) -o $@ -c $< $(CPPFLAGS)  # 编译源文件,生成目标文件

# 声明 clean 为伪目标,以便不受文件名影响而被执行
.PHONY: clean

# 定义清理操作,删除生成的目标和对象文件
clean:
		-rm -f $(target) $(object)  # 移除生成的可执行文件和对象文件,-f 表示强制删除,不提示错误信息

标签:文件,%.,变量,make,makefile,如何,clean,编写
From: https://blog.csdn.net/qq_57259389/article/details/143354642

相关文章

  • Gamma 使用教程:新手如何创建专业的 PPT
    介绍Gamma是一个强大的在线演示文稿工具,旨在帮助用户轻松创建专业的PPT。它提供了丰富的模板和功能,使得即使是没有设计经验的人也能制作出高质量的演示文稿。本文将详细介绍如何使用Gamma创建PPT,从账户注册、模板选择到内容编辑和最终导出。注册和登录1.访问Gamma网......
  • 程序员必看!AI如何助你工作开挂!
    现如今,国内的AI工具是越来越多了,它们正以惊人的速度发展壮大,它们不仅改变了我们的工作方式和生活方式,还为我们带来了更加便捷、高效、智能的未来生活体验。程序员作为科技的筑梦师,正站在时代的风口浪尖上,如果AI能有效地更快地解决大问题,那它将在未来有无限可能。那AI怎么来......
  • Java Z 垃圾收集器如何彻底改变内存管理
    大家好,我是V哥,今天的内容来聊一聊ZGC,JavaZGarbageCollector(ZGC)是一个低延迟垃圾收集器,旨在优化内存管理,主要用于大内存应用场景。它通过以下几个关键创新,彻底改变了传统Java的内存管理方式:V哥总结的以下5点,欢迎一起讨论。1.极低的暂停时间ZGC的暂停时间一般保持在10毫......
  • 如何在PVE环境中安装Docker:选择LXC容器还是虚拟机方案
    原文参考:https://www.oryoy.com/news/rong-qi-hua 在当今的云计算和虚拟化技术中,ProxmoxVE(PVE)作为一种强大的开源虚拟化平台,受到了许多系统管理员和开发者的青睐。而在PVE环境中安装Docker,成为了许多用户的需求。本文将详细探讨在PVE环境中安装Docker的两种主要方案:使用LXC容......
  • 如何快速解决RS-485组网通讯异常?
    RS-485总线的好处大家都知道,用隔离模块能让通信更稳定。但实际用的时候,可能会遇到通信不了、出错或者收发器坏掉的问题。本文将深度剖析RS-485组网问题。应用问题当出现通信错误或者不能通信时首先判断应用是否符合表1中的应用情况。表1RS-485总线应用情况表1中三种......
  • 乐维网管平台(三)如何高效管理无线网络
    一、无线网络管理概述1.什么是无线网络管理无线网络管理是指利用专门的软件平台(如网管平台)对无线网络设备(如无线接入点、无线控制器等)及其相关资源进行集中监控、配置、优化和维护的一系列操作。其主要目的是确保无线网络的高效稳定运行,提升用户体验,保障网络安全。2.无线网络管......
  • DevExpress WinForms中文教程:Data Grid - 如何创建未绑定列
    本教程将介绍:在设计时创建未绑定列在设计时为未绑定列指定表达式在运行时编辑表达式向代码中的未绑定列提供数据编辑未绑定列中的单元格值并保存更改P.S:DevExpressWinForms拥有180+组件和UI库,能为WindowsForms平台创建具有影响力的业务解决方案。DevExpressWinForms能......
  • 如何限制用户修改long_query_time
    如何限制用户修改long_query_time需求来源数据库的long_query_time设置了写入慢查询日志的SQL语句执行时长的阈值,当应用系统修改为很小的值或0时,会在数据库的慢查询日志中记录大量SQL语句,导致数据库性能降低和占用磁盘空间的快速增长。GreatSQL对于影响整个数据库会话级变量......
  • 如何使用MD5校验系统文件完整性?
    1、首先,我们先了解一下什么是MD5?很多朋友并不是很了解MD5是什么,针对这个问题,我们来做一下简单的介绍。MD5为计算机安全领域广泛使用的一种散列函数,用以提供文件的完整性保护。简单来说就是用来校验文件在下载过程中是否损坏。2、为什么要对系统文件进行MD5校验呢?经常碰到......
  • 如何构建双轮驱动的产品战略?
    营销和创新是企业永恒不变的话题,尤其是产品竞争激烈的今天,企业构建双轮驱动的产品战略迫在眉睫,产品和技术的创新相互支撑,如何构建双轮驱动的产品战略呢?共创力咨询首席技术战略专家George认为,构建双轮驱动的产品战略,必须进行产品路标和技术路标的开发,而且,产品路标与技术路标需要相......