Linux之Makefile学习

本文详细介绍了Linux系统下Makefile的使用,包括Makefile的基础概念、基本函数、条件编译、变量定义、目标与依赖的解析以及伪目标的应用。通过对Makefile的学习,可以更好地管理和构建大型工程,提高代码编译效率。文中还提供了代码实例,如条件编译、变量赋值、文件查找等,以及如何处理目标文件和依赖文件的关系。此外,还展示了如何通过Makefile与其他文件夹协同工作。
摘要由CSDN通过智能技术生成

1.Makefile简介

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

简单来说Makefile就像一个Shell脚本一样,可以自动地按我们定下的规则运行规定程序
在代码量不大的工程中可能体现不是很明显,但是对于大型甚至超大型的工程,Makefile可以帮助我们高效的管理和运行代码

三元素:依赖,目标,命令
使用变量方法:$(变量)
$@ 表示目标文件
$^ 表示所有的依赖文件
$< 表示第一个依赖文件
$? 表示比目标还要新的依赖文件列表

2.基本函数

1、wildcard : 扩展通配符

find_files = $(wildcard $(dir) /*)

从目标文件夹(dir)目录下找出所有符合需要的文件模式
如find_files = $(wildcard $(dir) *.c)
从dir文件夹目录下找出所有.c文件
注:一般和foreach共同使用

2、notdir : 去除路径

$(notdir src/foo.c)

将目标文件名从路径中挑出来,返回

3、patsubst :替换通配符

$(patsubst %.c,%.o,$(wildcard *.c))

patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o

4、foreach:遍历通配符

files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))

遍历找出所有由wildcard函数找到的所需文件模式

3.解释代码中的含义

1.条件编译

ARCH ?= x86

?= :表示只有ARCH为空第一次赋值有效,之后不可改变

ARCH ?= x86
ifeq ($(ARCH),x86)
        CC=gcc
else
        CC=arm-linux-gnueabihf-gcc
endif

在我之前的学习中条件编译没怎么接触过,只有前段时间学习STM32时才开始接触,基本逻辑和我们使用if else是一样的,我使用最多的的头文件的条件编译,是为了避免头文件的重复定义
基本格式为:

#ifndef  _HEAD_H
#define	 _HEAD_H


#endif

_HEAD_H就是head.h,写法就是这样
译为如果没有包含_HEAD_H,那就包含_HEAD_H
。最后一定要加上#endif

2.变量定义

TARGET=mp3
BUILD_DIR=build
SRC_DIR=module1 module2
INC_DIR=include
CFLAGS=$(patsubst %,-I%,$(INC_DIR))

VPATH=$(SRC_DIR)
SOURCE=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCE)))

为方便移植,将需要使用的文件夹和中间变量定义出来
TARGET:目标名字
BUILD_DIR:存放中间文件(*.o等)和最终的目标文件
SRC_DIR:存放源文件,即我们编辑的文件
SOURCE:将所有源文件赋给此变量
INC_DIR:存放头文件
CFLAGS:指定头文件路径
VPATH:指定源文件路径
OBJS:存放所有依赖文件

3.解决目标文件和依赖

$(BUILD_DIR)/$(TARGET):$(OBJS)
        $(CC) $^ -o $@

$(BUILD_DIR)/%.o:%.c |create_build
        $(CC) -c $< -o $@ $(CFLAGS)

基本格式:
目标文件:依赖文件
操作项目

4.伪目标

.PHONY:clean create_build

clean:
        rm -r $(BUILD_DIR)

create_build:
        mkdir -p  $(BUILD_DIR) 

如果我们需要书写这样的一个规则:规则所定义的命令不是去创建目标文件,而是通过make命令行明确指定它来执行一些特点的命令,我们输入“make clean”能按照初衷执行,但是一旦文件夹中出现clean文件,我们再次输入“make clean”,由于这个规则没有任何依赖文件,所以目标被认为是最新的而不去执行规则所定义的命令。所以rm命令不会被执行。为了解决问题,我们将目标clean定义成伪目标

4.代码测试

我们的代码测试除了Makefile还有其他文件夹include、module1、module2
include:是放头文件的
module1:可以放一种功能或者main函数
module2:可以放一种功能或者main函数

1.Makefile

ARCH ?= x86

ifeq ($(ARCH),x86)
        CC=gcc

else
        CC=arm-linux-gnueabihf-gcc

endif

TARGET=mp3
BUILD_DIR=build
SRC_DIR=module1 module2
INC_DIR=include
CFLAGS=$(patsubst %,-I%,$(INC_DIR))

VPATH=$(SRC_DIR)
SOURCE=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCE)))

$(BUILD_DIR)/$(TARGET):$(OBJS)
        $(CC) $^ -o $@


$(BUILD_DIR)/%.o:%.c |create_build
        $(CC) -c $< -o $@ $(CFLAGS)


.PHONY:clean create_build

clean:
        rm -r $(BUILD_DIR)

create_build:
        mkdir -p  $(BUILD_DIR) 

2.module1

main.c
main函数:

#include "learn.h"
int main()
{
	linux();
	stm32();

	return 0;
}

3.module2

enbeded.c
功能函数

#include <stdio.h>
#include "music.h"
void linux()
{
	printf("learn linux <<%s>>\n",learn);
}

void stm32()
{
	printf("learn stm32 <<%s>>\n",learn);
}

4.include

learn.h
头文件

#ifndef _LEARN_H
#define _LEARN_H

void linux();
void stm32();

#define learn 	"hello Makefile"

#endif

5.build

build文件夹会自动生成,去存放中间文件和目标文件

在这里插入图片描述
现在慢慢去接触一些Linux底层的一些知识以及一些基本工具的使用,这些东西逻辑性很强,所以会难,所以我将总结尽量写的细一些,基础一些,容易懂一些,当然我目前能力也有限,懂得也不是很多

学识浅薄,希望能帮到您

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值