返回

Simple makefile:Linux C

发布时间:2022-11-19 02:20:49 289
# 脚本

概述

编写Linux C程序,Makefile文件是无法绕过去的。简单记录一下Makefile的知识,留作备忘。

原理

Linux C程序,是经过编辑、预处理、编译、链接等阶段会生成最终的可执行程序。

简单开发Linux C程序,可以使用gcc命令直接编译程序文件生成可执行文件或静态/动态链接库。

但复杂项目有较多的源文件,每次手动敲gcc编译命令容易出错,也较为浪费时间,故此时需要使用makefile文件,来帮助我们编译程序。

makefile文件定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。

makefile文件编写完成

  • 可在同级目录下执行 make 命令,直接执行makefile中的脚本(若直接使用make命令,则同级目录下makefile文件必须名为makefile或Makefile);
  • 也可以使用-f 来执行makefile文件,如 make -f /home/src/makefile(借助-f 参数时,makefile文件可任意命名);

测试代码

  • head.h
void func1();
void func2();
void sum( int a, int b );
  • func1.c
#include 
void func1()
{
printf( "this is funcion-1...\n" );
}
  • func2.c
#include 
void func2()
{
printf( "this is funcion-2...\n" );
}
  • sum.c
#include 
void sum(int a, int b)
{
printf( "Sum( %d, %d ) = %d\n", a, b, a+b );
}
  • main.c
#include 
#include "head.h"

int main()
{
printf( "start main function...\n" );
func1();
func2();
sum( 1, 2 );
printf( "end main function...\n" );

return 0;
}

makefile 版本1

makefile规则:makefile由一组规则组成,如下所示:

目标: 依赖

(tab)命令

解释:

makefile规则三要素:

  • 目标:要生成的目标文件(可执行文件、库文件、中间文件等)
  • 依赖:目标文件由哪些文件生成
  • 命令:通过执行该命令由依赖文件生成目标文件

例如:

main: main.c func1.c func2.c sum.c
gcc -o main main.c func1.c func2.c sum.c

makefile 版本2

改进:目标文件可一次生成,也可先将中间文件生成,然后再生成目标文件,减少出错率。

例如:

main: main.o func1.o func2.o sum.o
gcc -o main main.o func1.o func2.o sum.o

main.o: main.c
gcc -c main.c -I./

func1.o: func1.c
gcc -c func1.c

func2.o: func2.c
gcc -c func2.c

sum.o: sum.c
gcc -c sum.c

makefile 版本3

改进:项目中可能存在多个源文件,且makefile文件中同样的文件名称出现多次,不利于高效率编写makefile文件,故可使用makefile提供的变量来优化makefile的编写过程。

makefile变量类似于C语言中的宏定义,可以使用变量进行内容替换,提升makefile编写效率,且使之更容易维护。

makefile变量分为三种:

  • 普通变量
  • 自带变量
  • 自动变量

普通变量:

  • 变量定义使用 =
  • 使用变量值 $(变量名)

自带变量:

  • CC: gcc
  • CPPFLAGS: C预处理的选项 -I
  • CFLAGS: C编译器的选项 -Wall -g -c
  • LDFLAGS: 链接器选项 -L -I

自动变量:

  • $@: 表示规则中的目标
  • $<: 表示规则中的第一个条件
  • $^: 表示规则中的所有条件,组成一个列表,以空格隔开,若这个列表中有重复的项,则消除重复项

例如:

target = main
objects = main.o func1.o func2.o sum.o
CC = gcc
CPPFLAGS = -I./

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

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

makefile 版本4

改进:项目中有众多的源文件,虽然上一版本中自定义的普通变量objects列出了所有的目标文件所需的中间文件,但依然容易出错,此时可使用makefile提供的函数,以一定的规则查找所有源文件和进行查找结果的字符替换。

  • ​src =$(wildcard *.c):使用wildcard函数,可查找某路径下所有*.c文件;
  • ​objects = $(patsubst %.c, %.o, $(src)):使用patsubst函数可以将src变量值中所有的后缀为.c的字符串替换为后缀为.o的字符串;

例如:

target = main

src = $(wildcard /home/src/*.c)
objects = $(patsubst %.c, %.o, $(src))

CC = gcc
CPPFLAGS = -I./

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

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

此时,便得到了一个仅需要修改target变量和src中源文件路径的makefile文件,具有普适性。

makefile 最终版本

改进:上一版本随具有普适性,但每次执行完makefile生成的文件(目标文件、中间文件等),还需手动删除,此时可使用makefile提供的伪目标,来达到一键删除makefile生成的文件的目的。

  • .PHONY: 伪目标名称: 可在makefile文件中声明伪目标,执行"make 伪目标名称"命令(如下示例中:make clean),即可跳过前面版本中要生成目标文件的命令,只执行伪目标;

如下所示:

target = main

src = $(wildcard ./*.c)
objects = $(patsubst %.c, %.o, $(src))

CC = gcc
CPPFLAGS = -I./

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

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


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


特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
c语言初识 2022-11-19 01:52:25