当前位置:首页 > C语言
工程管理器 Makefile 的使用
来源:靑龍一笑的博客  作者:靑龍一笑  发布时间:2022-10-02 09:52:41  点击量:140  评论:0

    假设一个 C 语言项目中存在几个文件:main.c、func1.h、func2.h、func1.c、func2.c。
    文件 main.c 内容如下:

#include <stdio.h>
#include <stdlib.h>

#include "func1.h"
#include "func2.h"

int main() {
        func1();
        func2();

        exit(0);
}

    文件 func1.h 内容如下:

#ifndef FUNC1_H__
#define FUNC1_H__

void func1(void);

#endif

    文件 func2.h 内容如下:

#ifndef FUNC2_H__
#define FUNC2_H__

void func2(void);

#endif

    文件 func1.c 内容如下:

#include <stdio.h>
#include "func1.h"

void func1(void){
        printf("func1() run.\n");
}

    文件 func2.c 内容如下:

#include <stdio.h>
#include "func2.h"

void func2(void){
        printf("func2() run.\n");
}

    根据平时的做法,可能会使用如下命令进行编译:

root@RicenOS:~# gcc *.c

    这样,得到的将是一个名为 a.out 的可执行文件,运行效果如下:

root@RicenOS:~# ./a.out 
func1() run.
func2() run.

    比较好的做法是写一个 Makefile 文件,使用 make 命令进行编译。虽然绝大多数软件包发行时,使用的是首字母大写的 Makefile 文件,但是 make 命令在执行时,优先使用的是文件名全部小写的 makefile 文件。之所以采用首字母大写的 Makefile 文件,是为了让用户能够自定义自己的 makefile 文件,当同时存在 Makefile 和 makefile 文件时,以 makefile 文件为主进行编译。
    这里编写一个 Makefile 文件,内容如下:

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

main.o:main.c
    gcc main.c -c -Wall -g -o main.o

func1.o:func1.c
    gcc func1.c -c -Wall -g -o func1.o

func2.o:func2.c
    gcc func2.c -c -Wall -g -o func2.o

clean:
    rm *.o myfunc -rf

    其中,第一行 myfunc 表示要生成的文件名,冒号后面跟的 main.o、func1.o、func2.o 表示要生成 myfunc,需要依赖的几个文件名。
    第二行表示要执行的命令。
    由于 main.o、func1.o、func2.o 不存在,需要生成 main.o、func1.o、func2.o。同理,依照前两行进行相关命令的编写。其中,-c 参数表示只编译不链接,即只生成 .o 文件,但不生成可执行文件。-g 参数是加入调试信息。-Wall 参数是生成所有警告信息。
    最后两行表示在执行 make clean 命令时,删除所有的 .o 文件以及 myfunc 可执行文件。
    以下是执行过程及效果:

root@RicenOS:~# make
gcc main.c -c -Wall -g -o main.o
gcc func1.c -c -Wall -g -o func1.o
gcc func2.c -c -Wall -g -o func2.o
gcc main.o func1.o func2.o -o myfunc
root@RicenOS:~# ./myfunc 
func1() run.
func2() run.
root@RicenOS:~# make clean
rm *.o myfunc -rf

    接下来,使用变量的方式对 Makefile 文件里的重复内容进行替换,修改后的 Makefile 文件内容如下:

OBJS=main.o func1.o func2.o
CC=gcc
CFLAGS+=-c -Wall -g

myfunc:$(OBJS)
    $(CC) $(OBJS) -o myfunc

main.o:main.c
    $(CC) main.c $(CFLAGS) -o main.o

func1.o:func1.c
    $(CC) func1.c $(CFLAGS) -o func1.o

func2.o:func2.c
    $(CC) func2.c $(CFLAGS) -o func2.o

clean:
    $(RM) *.o myfunc -r

    前三行定义了三个变量,后面使用$()来引用前三行定义的变量,而最后一行的变量 RM 相当于 rm -f。
    以下是执行过程及效果:

root@RicenOS:~# make
gcc main.c -c -Wall -g -o main.o
gcc func1.c -c -Wall -g -o func1.o
gcc func2.c -c -Wall -g -o func2.o
gcc main.o func1.o func2.o -o myfunc
root@RicenOS:~# ./myfunc 
func1() run.
func2() run.
root@RicenOS:~# make clean
rm -f *.o myfunc -r

    继续简化 Makefile 文件,内容如下:

OBJS=main.o func1.o func2.o
CC=gcc
CFLAGS+=-c -Wall -g

myfunc:$(OBJS)
    $(CC) $^ -o $@

%.o:%.c
    $(CC) $^ $(CFLAGS) -o $@

clean:
    $(RM) *.o myfunc -r

    其中,$^ 表示上一级依赖关系中被依赖的所有文件,$@ 表示上一级的目标文件,% 相当于一个通配符,在同一句话中,表示同一个名字。
    以下是执行过程及效果:

root@RicenOS:~# make
gcc main.c -c -Wall -g -o main.o
gcc func1.c -c -Wall -g -o func1.o
gcc func2.c -c -Wall -g -o func2.o
gcc main.o func1.o func2.o -o myfunc
root@RicenOS:~# ./myfunc 
func1() run.
func2() run.
root@RicenOS:~# make clean
rm -f *.o myfunc -r
版权所有 © 2005-2023 靑龍一笑的博客  Powered by C.S.Ricen
Copyright © 2005-2023 by www.ricensoftwares.com.cn  All Rights Reserved.

欢迎光临本站,这里是靑龍一笑的博客。

因资金匮乏,本站已迁到国外的免费空间,可能导致本站的访问速度较慢,由此给您带来的不便,敬请谅解。

您可以通过下方的“支持本站建设”链接,给本站提供资金支持。

Free Web Hosting