gcc的编译选项-详细

嵌入式C语言编译器,文章的理论部分

注意: 下文验证的内容,使用的是这里的func.h、test.c
func.h

#include <stdio.h>

void func()
{
#ifdef TEST
    printf("TEST = %s\n", TEST);
#endif

    return;
}

test.c

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

int g_global = 0;
int g_test = 1;

int main(int argc, char *argv[])
{
    func();

    printf("&g_global = %p\n", &g_global);
    printf("&g_test = %p\n", &g_test);
    printf("&func = %p\n", &func);
    printf("&main = %p\n", &main);

    return 0;
}

0x01 预处理指令: gcc -E test.c -o test.i

file

test.i

# 1 "test.c"                 // 1 :表示后文部分是test.c的第一行展开内容
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
# 1 "/usr/include/stdio.h" 1 3 4

// ..... 此处省略800余行 .....

# 2 "test.c" 2      // 第一个2 : 表示后文部分是test.c的第二行展开内容, 第二个2表示:之前包含的语句结束了
# 1 "func.h" 1      // 第一个1 :从这里开始,展开的是func.h第一行展开的内容

void func()
{

                   //打印语句被删掉了

    return;
}
# 3 "test.c" 2  // 3:后面部分来自test.c的第三行之后的部分,2:表示从之前包含的头文件里退出了

int g_global = 0;
int g_test = 1;

int main(int argc, char *argv[])
{
    func();

    printf("&g_global = %p\n", &g_global);
    printf("&g_test = %p\n", &g_test);
    printf("&func = %p\n", &func);
    printf("&main = %p\n", &main);

    return 0;
}

0x02 编译指令 : gcc -S test.i -o test.s

file

Linux下生成的汇编代码
test.s

    .file   "test.c"
    .text
.globl func
    .type   func, @function
func:
    pushl   %ebp
    movl    %esp, %ebp
    popl    %ebp
    ret
    .size   func, .-func
.globl g_global
    .bss
    .align 4
    .type   g_global, @object
    .size   g_global, 4
g_global:
    .zero   4
.globl g_test
    .data
    .align 4
    .type   g_test, @object
    .size   g_test, 4
g_test:
    .long   1
    .section    .rodata
.LC0:
    .string "&g_global = %p\n"
.LC1:
    .string "&g_test = %p\n"
.LC2:
    .string "&func = %p\n"
.LC3:
    .string "&main = %p\n"
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    call    func
    movl    $.LC0, %eax
    movl    $g_global, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    movl    $.LC1, %eax
    movl    $g_test, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    movl    $.LC2, %eax
    movl    $func, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    movl    $.LC3, %eax
    movl    $main, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5.1) 4.4.5"
    .section    .note.GNU-stack,"",@progbits

0x03 汇编指令 : gcc -c test.s -o test.o

file

0x04 生成映射文件: gcc -Wl,-Map=test.map test.c

全局变量的地址和存放的位置可以在映射文件中找到;
全局变量和函数的地址在编译结束后就已经决定了,不需要运行的时候动态决定;

file

0x05 宏定义 gcc -D’TEST="test"’ test.c

file

看一下预处理文件

file

0x06 获取系统头文件路径 : gcc -v file.c

查看自己包含的头文件路径对不对,这个也很关键

file

0x07 获取目标的完整依赖关系:gcc -M test.c

0x08 获取目标的部分依赖关系: gcc -MM test.c

Makefile中会用到
“-MM”就很清晰,.o依赖.c和.h

file

0x09 指定库文件和库文件搜索路径 : gcc test.c -L. -lfunc

“-L”: 指定库文件搜索路径
“-l”: 指定库文件
编译test.c的时候依赖func库,到当前目录下搜索("-L.")

创建一个库文件,来链接,步骤:

  1. 把func.h名字修改为func.c, test.c中不包含func.h
  2. func.c编译成func.o
  3. func.o打包成库文件libfunc.a
  4. 使用这个库文件 “-L.”

file

注意:
静态库文件名的命名规范:以lib为前缀,紧接着跟静态库名,扩展名为.a。
例如:我们将创建的静态库名为hello,则静态库文件名就是libhello.a

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇