关于Linux系统下Makefile学习的简单总结
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底层的一些知识以及一些基本工具的使用,这些东西逻辑性很强,所以会难,所以我将总结尽量写的细一些,基础一些,容易懂一些,当然我目前能力也有限,懂得也不是很多
学识浅薄,希望能帮到您