zoukankan      html  css  js  c++  java
  • makefile及其相关知识介绍

    makefile是用来管理工程的。

    示例1:

    1 exe: a.c b.c
    2         gcc a.c b.c -o exe
    3 
    4 clean:
    5         rm exe

    基本概念:

    目标:顶格写,在:前面

    依赖: 在:后面,用来产生目标的原材料

    命令:前面一定是table,不能是多个空格。命令是生成目标所做的动作

    示例2:

     1 led.bin: start.o 
     2         arm-linux-ld -Ttext 0x0 -o led.elf $^
     3         arm-linux-objcopy -O binary led.elf led.bin
     4         arm-linux-objdump -D led.elf > led_elf.dis 
     5         gcc mkv210_image.c -o mkx210   // 该处生成的mkx210是为了在Linux下执行的,这里的gcc和交叉编译工具链的gcc不相同
     6         ./mkx210 led.bin 210.bin  
     7     
     8 %.o : %.S
     9         arm-linux-gcc -o $@ $< -c
    10 
    11 %.o : %.c
    12         arm-linux-gcc -o $@ $< -c 
    13 
    14 clean:
    15         rm *.o *.elf *.bin *.dis mkx210 -f

    示例分析:

    (1)Makefile有三个非常有用的变量。分别是$@,$^,$<代表的意义分别是: 

    $@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件

    (2)交叉编译工具链工具及作用

    先决条件:linux系统下面有一个环境变量叫PATH,必须把该工具链的地址导入到该环境变量下面,export PATH=工具链地址:$PATH

    最好是该语句加到~/.bash文件中,这样每次启动终端都会执行该语句。

    arm-linux-gcc:

    用来编译源文件

    arm-linux-ld:

    用来链接,其中,-Ttest是用来指定链接地址的,在该处也可以使用链接脚本来去进行链接。在该处生成的elf文件还不能烧录执行。

    objcopy:

    作用以led.elf为源材料为源材料制作镜像的工具。

    解释:led.elf已经是可执行程序,在操作系统下已经可以执行,裸机中需要的是可以烧录的二进制文件(镜像image)。

    以led.elf为源材料为源材料制作镜像

    objdump:

    作用:反汇编,将elf格式的可执行程序反过来得到其汇编源代码。

    mkx210(由mkv210_image.c得到):

    作用:以led.bin为源材料得到210.bin(为BL1添加校验头)

    解释:usb启动时不需要头校验,SD卡启动时需要,让led.bin加上header(校验头)成为210.bin。

    附:mkv210_image.c源程序:

      1 /*
      2  * mkv210_image.c的主要作用就是由usb启动时使用的led.bin制作得到由sd卡启动的镜像210.bin
      3  *
      4  * 本文件来自于友善之臂的裸机教程,据友善之臂的文档中讲述,本文件是一个热心网友提供,在此表示感谢。
      5  */
      6 /* 在BL0阶段,Irom内固化的代码读取nandflash或SD卡前16K的内容,
      7  * 并比对前16字节中的校验和是否正确,正确则继续,错误则停止。
      8  */
      9 #include <stdio.h>
     10 #include <string.h>
     11 #include <stdlib.h>
     12 
     13 #define BUFSIZE                 (16*1024)
     14 #define IMG_SIZE                (16*1024)
     15 #define SPL_HEADER_SIZE         16
     16 //#define SPL_HEADER              "S5PC110 HEADER  "
     17 #define SPL_HEADER              "****************"
     18 
     19 int main (int argc, char *argv[])
     20 {
     21     FILE        *fp;
     22     char        *Buf, *a;
     23     int        BufLen;
     24     int        nbytes, fileLen;
     25     unsigned int    checksum, count;
     26     int        i;
     27     
     28     // 1. 3个参数
     29     if (argc != 3)
     30     {
     31         printf("Usage: %s <source file> <destination file>
    ", argv[0]);
     32         return -1;
     33     }
     34 
     35     // 2. 分配16K的buffer,并且全部填充为0
     36     BufLen = BUFSIZE;
     37     Buf = (char *)malloc(BufLen);
     38     if (!Buf)
     39     {
     40         printf("Alloc buffer failed!
    ");
     41         return -1;
     42     }
     43 
     44     memset(Buf, 0x00, BufLen);
     45 
     46     // 3. 读源bin到buffer
     47     // 3.1 打开源bin
     48     fp = fopen(argv[1], "rb");
     49     if( fp == NULL)
     50     {
     51         printf("source file open error
    ");
     52         free(Buf);
     53         return -1;
     54     }
     55     // 3.2 获取源bin长度
     56     fseek(fp, 0L, SEEK_END);                                // 定位到文件尾
     57     fileLen = ftell(fp);                                    // 得到文件长度
     58     fseek(fp, 0L, SEEK_SET);                                // 再次定位到文件头
     59     // 3.3 源bin长度不得超过16K-16byte
     60     count = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))
     61         ? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);
     62     // 3.4 buffer[0~15]存放"S5PC110 HEADER  "
     63     memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE);
     64     // 3.5 读源bin到buffer[16]
     65     nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp);
     66     if ( nbytes != count )
     67     {
     68         printf("source file read error
    ");
     69         free(Buf);
     70         fclose(fp);
     71         return -1;
     72     }
     73     fclose(fp);
     74 
     75     // 4. 计算校验和
     76      // 4.1 从第16byte开始统计buffer中共有几个1
     77     // 4.1 从第16byte开始计算,把buffer中所有的字节数据加和起来得到的结果
     78     a = Buf + SPL_HEADER_SIZE;
     79     for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)
     80         checksum += (0x000000FF) & *a++;
     81     // 4.2 将校验和保存在buffer[8~15]
     82     a = Buf + 8;                            // Buf是210.bin的起始地址,+8表示向后位移2个字,也就是说写入到第3个字
     83     *( (unsigned int *)a ) = checksum;
     84 
     85     // 5. 拷贝buffer中的内容到目的bin
     86     // 5.1 打开目的bin
     87     fp = fopen(argv[2], "wb");
     88     if (fp == NULL)
     89     {
     90         printf("destination file open error
    ");
     91         free(Buf);
     92         return -1;
     93     }
     94     // 5.2 将16k的buffer拷贝到目的bin中
     95     a = Buf;
     96     nbytes    = fwrite( a, 1, BufLen, fp);
     97     if ( nbytes != BufLen )
     98     {
     99         printf("destination file write error
    ");
    100         free(Buf);
    101         fclose(fp);
    102         return -1;
    103     }
    104 
    105     free(Buf);
    106     fclose(fp);
    107 
    108     return 0;
    109 }
    View Code

    (3)指令解释

    -c: 只编译不链接

    -o: 用来指定名字

    -D: 表示反汇编(反汇编工具有多种用法,-D表示反汇编用法)

    -Ttext: 指定代码段的起始地址(链接地址)

    (4)其它

    第8行到第12行叫做makefile的规则,当看到.S和.c文件会自动转化为.o文件。

    printf移植中用到的makefile

     1 CC         = arm-linux-gcc
     2 LD         = arm-linux-ld
     3 OBJCOPY = arm-linux-objcopy
     4 OBJDUMP = arm-linux-objdump
     5 AR         = arm-linux-ar
     6 
     7 INCDIR := $(shell pwd)
     8 
     9 # c预处理器的flag,flag就是编译器可选的选项
    10 CPPFLAGS    := -nostdlib -nostdinc -I$(INCDIR)/include
    11 # C编译器的flag
    12 CFLAGS        := -Wall -O2 -fno-builtin                
    13 
    14 # 导出这些变量到全局,其实就是给子文件下面的makefile使用
    15 export CC LD OBJCOPY OBJDUMP AR CPPFLAGS CFLAGS
    16 
    17 
    18 objs := start.o led.o clock.o uart.o main.o
    19 objs += lib/libc.a
    20 
    21 uart.bin: $(objs) 
    22     $(LD) -Tlink.lds -o uart.elf $^
    23     $(OBJCOPY) -O binary uart.elf uart.bin
    24     $(OBJDUMP) -D uart.elf > uart_elf.dis
    25     gcc mkv210_image.c -o mkx210
    26     ./mkx210 uart.bin 210.bin
    27     
    28 lib/libc.a:
    29     cd lib; make; cd ..
    30     
    31 
    32     
    33 %.o : %.S
    34     $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c 
    35 
    36 %.o : %.c
    37     $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c 
    38 
    39 clean:
    40     rm *.o *.elf *.bin *.dis mkx210 -f
    41     cd lib; make clean; cd ..

     -nostdlib 不用标准库

    -nostdinc 不用标准的头文件

    -O2   编译器的优化等级

    -Wall  显示所有警告

    -I           用来表示寻找头文件的目录(一般用相对路径表示)

  • 相关阅读:
    进程DLL注入
    静态链接库LIB
    利用MoveFileEx实现程序的隐藏、自启动与自删除
    QueueUserApc实现DLL注入的测试
    简单说说SSDT
    ural 1521. War Games 2 约瑟夫环 SBT实现
    次小生成树 (附:poj1679)
    hoj 1138 LC Display
    hoj 3029 Dictionary 模拟队列
    hoj 2578 Super_Stack 模拟栈
  • 原文地址:https://www.cnblogs.com/zou27/p/5021360.html
Copyright © 2011-2022 走看看