找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2210|回复: 0
收起左侧

makefile相关的知识

[复制链接]
ID:108615 发表于 2016-3-13 17:22 | 显示全部楼层 |阅读模式
makefile的功能太过强大,完全个人总结,知 识有限,欢迎纠正错误!


main.c

#include "main.h"
int main()
{
        printf_hello();
        printf_ok();
        return ;
}

main.h

#ifndef _MAIN_H
#define _MAIN_H
#include "hello.h"
#include "ok.h"
#endif


printf_hello.c

#include "hello.h"
void printf_hello(void)
{
        printf("hello!\n");
        printf_thanks();
}
void printf_thanks(void)
{
        printf("thanks!!!\n");
}

hello.h

#ifndef _HELLO_H
#define _HELLO_H
#include <stdio.h>
void printf_thanks(void);
void printf_hello(void);
#endif

printf_ok.c

#include "ok.h"
void printf_ok(void)
{
        printf("ok!!!\n");
        printf_thanks();
}

ok.h

#ifndef _OK_H_
#define _OK_H_
#include <stdio.h>
void printf_ok(void);
extern void printf_thanks(void);
#endif

在编译六个文件组成的项目时,可以不用写makefile文件因为文件的数量比较的少所以
可以直接在linux系统下直接使用  gcc  main.c  printf_hello.c  printf_ok.c  -o  main
编译成执行文件  main  ,可以直接./main执行此文件即可。(上面的所有的文件必须
在一个文件夹中,才可以编译,否则 将会报错说找不到目标文件)。

当项目比较大的时候,文件可能几千甚至更多的时候,我们可以先创建一个工程文件名
为project的文件夹,之后在其中在创建两个文件夹,一个取名为inc   ,另一个取名为
src 。在inc中我们通常是放.h文件,而在src中我们通常放的是.c文件和makefile文件。

一般的makefile文件如下:

main:main.o printf_hello.o printf_ok.o
        gcc main.o printf_hello.o printf_ok.o -o main
main.o:main.c
        gcc -c -I ../inc/ main.c -o main.o
printf_hello.o:printf_hello.c
        gcc -c -I ../inc/ printf_hello.c -o printf_hello.o
printf_ok.o:printf_ok.c
        gcc -c -I ../inc/ printf_ok.c -o  printf_ok.o
clean:
        -rm -f *.o main    //移除后缀为.o和目标文件

每一个gcc命令的最后加上  -g   就可以使用   gdb  编译!!!

makefile 通常有三种写法  Makefile ,   makefile   ,   GNU makefile
第一种使用较多,因为大写的M的 ASCII 较小系统摆放文件时将其放在了前面。

调用make命令可输入
target是Makefile文件中定义的目标之一,如果省略target,make就将生成
Makefile文件中定义的第一个目标。
例如:在上面的例子中我们可以输入   make  main.o   或  make  printf_hello.o
等等  ,但是如果你输入的是make  main.o 那么他只会执行gcc -c -I ../inc/ main.c
-o main.o   这一个命令!而单独的一个“make”命令等价于make  main命令,
由于依赖的关系所以下面的命令都执行除了clean命令外(clean命令和他们没有
依赖的关系)。

因为main是Makefile文件中定义的第一个目标,make首先将其读入,然后从第一行
开始执行,把第一个目标main作为它的最终目标,所有后面的目标的更新都会影响到
main的更新。

如果直接在linux系统下敲击make命令,则系统执行的命令是makefile,而
不是执行的是Makefile文件的命令。如果文件夹中既有makefile 也有Makefile文
件,我们需要使用make的命令,make  -f    Makefile  就可以执行Makefile的文
件的命令。而以上的makefile文件可以通过更改头文件的路径而更改,.h文件不必
改变。

make的执行过程:
1.如果目标文件的时问戳比依赖文件还早,就按规则中定义的命令更新目标文件。
2.如果该规则中的依赖文件又是其他规则中的目标文件,那么依照规则链不断执行这
个过程,直到Makefile文件的结束,至少可以找到一个不是规则生成的最终依赖文
件,获得此文件的时间戳
3.然后从下到上依照规则链执行目标文件的时间戳比此文件时间戳旧的规则,直到最
顶层的规则

#include "../inc/ok.h"    //将相对路径添加到头文件中
void printf_ok(void)
{
        printf("ok!!!\n");
        printf_thanks();
}

#include "../inc/hello.h"    //将相对路径添加到头文件中
void printf_hello(void)
{
        printf("hello!\n");
        printf_thanks();
}
void printf_thanks(void)
{
        printf("thanks!!!\n");
}

#include "../inc/main.h"   //将相对路径添加到头文件中
int main()
{
        printf_hello();
        printf_ok();
        return ;
}

修改后的makefile文件:
main:main.o printf_hello.o printf_ok.o
        gcc main.o printf_hello.o printf_ok.o -o main
main.o:main.c
        gcc -c  main.c -o main.o
printf_hello.o:printf_hello.c
        gcc -c printf_hello.c -o printf_hello.o
printf_ok.o:printf_ok.c
        gcc -c printf_ok.c -o  printf_ok.o
clean:
        -rm -f *.o main

Makefile的变量
(1)变量名不包括: “   :”  、“   #   ”  、“  =  ”
(2)变量名是大小写敏感的,“  foo ”与“ Foo ”代表不同的变量
(3)预留大写字母作为作为控制隐含规则参数或者用户重载命令选项

Makefile中的变量分为:
            用户自定义变量
            预定义变量、
            自动变量

1.用户自定义的变量
例如将上面的makefile改变:
A=main.o printf_hello.o printf_ok.o
B=gcc

main:$(A)
        $(B)  $(A) -o main
main.o:main.c
        $(B)  -c  main.c -o main.o
printf_hello.o:printf_hello.c
        $(B)  -c printf_hello.c -o printf_hello.o
printf_ok.o:printf_ok.c
        $(B)  -c printf_ok.c -o  printf_ok.o
clean:
        -rm -f *.o main

2.预定义变量
A=main.o printf_hello.o printf_ok.o
B=gcc
$@     目标文件的完整名称
$<      第一个依赖的文件名称

main:$(A)
        $(B)  $(A) -o $@
main.o:main.c
        $(B)  -c   $<  -o  $@
printf_hello.o:printf_hello.c
        $(B)  -c  $<  -o  $@
printf_ok.o:printf_ok.c
        $(B)  -c  $<  -o   $@
clean:
        -rm -f *.o main

也可以写成:
main:$(A)
        $(B)  -o $@   $(A)
main.o:main.c
        $(B)  -c    -o   $@      $<
printf_hello.o:printf_hello.c
        $(B)  -c    -o   $@      $<
printf_ok.o:printf_ok.c
        $(B)  -c    -o   $@      $<
clean:
        -rm -f *.o main

3. 自动变量
实际上,make可以使工作更加自动化,也就是说,make知道一些默认
的动作,它有一些称作隐含规则的内置的规则。
如上例完全可以写成:
A=main.o printf_hello.o printf_ok.o
B=gcc
$@     目标文件的完整名称
$<      第一个依赖的文件名称

main:$(A)
        $(B)  $(A) -o $@
clean:
        -rm -f *.o main

可以省略最后两条,因为Makefile的隐式规则指出都可由“ .c ”文件使用
以下命令生成:
$(B) $(CFLAGS)  $(CPPFLAGS)  -c   –o  file.o file.c

CFLAGS   CPPFLAGS  是系统的默认的变量为空  ,我们可以给他赋值,也
可以不理会!!!

makefile还有一种模式规则可以将makefile变更为:
A=main.o printf_hello.o printf_ok.o
B=gcc

main:$(A)
        $(B)  -o  $@  $(A)
%.o:%.c                                //代表了一系列这样的文件
        $(B)  -c    -o   $@      $<
clean:
        -rm -f *.o main
1.模式规则是用来定义相同处理规则的多个文件的,模式规则可以引入用户自定义
变量,为多个文件建立相同的规则,从而简化Makefile的编写。
2.模式规则中相关文件前必须用“    %    ”



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表