• 编译过程,gcc/g++,make命令


    gcc 编译程序的四个阶段

    gcc指令的一般格式为:gcc [选项] 要编译的文件 [选项] [目标文件]
    其中,目标文件可缺省,gcc 默认生成可执行的文件名为:编译文件.out

    1)预处理(Pre-processing)
    在该阶段,编译器将C源代码中的包含的头文件如stdio.h编译进来。可以使用gcc的选项”-E”进行查看,该选项使得 gcc 在预处理结束后停止编译过程,从而生成预处理之后的文件。
    选项:-E
    用法:gcc -E main.c -o main.i
    作用:将 main.c 预处理输出 main.i 文件

    2)编译阶段(Compiling)
    第二步进行的是编译阶段,在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。可以使用”-S”选项来进行查看,该选项使得 gcc 在编译结束后停止编译过程,从而生成汇编代码。
    选项: -S
    用法:gcc –S main.i –o main.s
    作用:将预处理输出文件 main.i 汇编成 main.s 文件

    3)汇编阶段(Assembling)
    汇编阶段是把编译阶段生成的”.s”文件转成二进制目标代码。可使用选项”-c”来进行查看,该选项使得 gcc 在汇编结束后停止编译过程从而生成二进制目标代码了。
    选项:-c
    用法:gcc –c main.s –o main.o
    作用:将汇编输出文件 main.s 编译输出 main.o 文件

    4)链接阶段(Link)
    在成功编译之后,就进入了链接阶段,此阶段会生成最终的可执行文件。
    读者可以重新查看这个小程序,在这个程序中并没有定义”printf”的函数实现,且在预编译中包含进的”stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现”printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为libc.so.6的库文件中去了,在没有特别指定时,gcc会到系统默认的搜索路径”/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函 数”printf”了,而这也就是链接的作用。函数库一般分为静态库和动态库两种。静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件 了。其后缀名一般为”.a”。动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以 节省系统的开销。动态库一般后缀名为”.so”,如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。完成了链接之后,gcc就可以生成可执行文件
    无选项链接
    用法:gcc main.o –o main.out
    作用:将编译输出文件 main.o 链接成最终可执行文件main

    gcc/g++ 常用参数

    https://www.cnblogs.com/MyOnlyBook/p/9526889.html

    • -Wall, -W, -w:显示警告信息;显示可能会引起错误的警告信息;屏蔽警告信息
    • -g, -g2, -g0, -g3:生成不同级别的调试信息,其中 -g0 表示不生成调试信息
    • -O, -O1, -O2, -O3, -Os:优化代码
    • -lm,链接数学库;-pthread,链接线程库
    • -E,将源代码变成预处理之后的代码
    • -S,将源代码变成汇编代码
    • -c,将源代码变成机器代码

    多文件调用问题

    • 第一种

    不使用 .h 文件,而是将代码写在 .c 文件中,其他文件要调用该 .c 文件的函数或变量时直接包含 .c 文件。当有多个文件同时包含同一个 .c 文件时,会导致重定义问题,编译不通过。

    • 第二种

    同样也是不使用 .h 文件而是将代码写在 .c 文件中,但不同的是,当其他文件要调用该 .c 文件的函数或变量时,在该调用文件中使用 extern 进行声明(这是因为全局变量和全局函数可以被外部引用),而对于函数则可以不必使用 extern 声明。对于每个调用文件,都需要显示声明所用到的全局变量和全局函数,导致代码的冗余。

    • 第三种

    为每一个模块都编写一个 .c 文件,一个 .h 文件。.c 源文件中放:函数的定义,全局变量的定义,全局结构体变量的定义。.h 头文件中放:函数的声明,全局变量的声明(extern),全局结构体的定义,全局结构体变量的声明。调用文件(main.c)文件中:包含.h头文件即可,不用声明任何东西。

    假设有如下文件:bar.c, bar.h, foo.c, foo.h, common.h, main.c。其中 bar.h 定义 bar.c 的接口,foo.h 定义 foo.c 的接口,然后给main.c 使用,而 common.h 包含所有文件都要用到的通用定义(bar.h 和 foo.h 中包含 common.h),为了生成名为 main 的可执行文件,编译命令可写为,

    gcc -c bar.c -o bar.o
    gcc -c foo.c -o foo.o
    gcc -c main.c -o main.o
    gcc main.o bar.o foo.o -o main
    
    • 1
    • 2
    • 3
    • 4

    make与makefile初探

    https://zhuanlan.zhihu.com/p/29910215

    https://www.cnblogs.com/paul-617/p/15501875.html

    makefile 中写明了程序的依赖关系,make 命令结合该 makefile 文件将源代码经过预处理编译汇编链接从而生成可执行文件。

    同上面同样的文件依赖关系,写成makefile文件,如下所示,

    .PHONY: clean
    CC = gcc
    CFLAGS = -Wall -c
    
    main: foo.o woo.o main.o
    	$(CC) $^ -o $@
    %.o: %.c
    	$(CC) $(CFLAGS) $^ -o $@
    foo.o: foo.c foo.h common.h
    bar.o: bar.c bar.h common.h
    main.o: main.c bar.h foo.h common.h
    clean:
    	rm *.o main
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    当然还可以继续化简,比如gnumake其实是默认定义了一组rule的,上面这个整个都可以不写,就这样就可以了,

    LDLIBS=-lpthead
    CFLAGS+=-MMD -MP
    SRC=$(wildcard *.c)
    OBJ=$(SRC:.c=.o)
    DEP=$(SRC:.c=.d)
    -include $(DEP)
    app.executable: $(OBJ)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里其实没有定义.o到.c的依赖,但gnumake默认如果.c存在,.o就依赖对应的.c,而.o到.c的rule,是通过宏默认定义的。你只要修改CC,LDLIBS这类的宏,就能解决大部分问题了。所以又省掉了一组定义,这就可以写得很短。CFLAGS中增加的参数可以为xxx.c产生xxx.d文件,里面就是那个依赖关系,然后我用-include包含这些依赖关系。这样就不再需要手工来写每个依赖了。为了解决这个问题,你已经看见了,include前面又增加了一个语法。那个减号表示允许被包含的文件不存在。

    cmake

    make 工具通过调用 makefile 文件中的命令便可以对大型程序进行编译,而 makefile 文件中就包含了调用 gcc 去编译多个源文件的命令。但是如果程序是跨平台的,换个平台之后 makefile 又要重新修改,会很麻烦,所以出现了 cmake 工具,通过 cmake 我们可以快速创建出不同平台的 makefile 文件。

  • 相关阅读:
    Oracle数据泵备份恢复(导出导入)详细语句
    数字精度问题
    Java ThreadPoolExecutor的拒绝策略
    http-only原理与防御XSS实践
    7、GC日志详解
    四.pyqt5 登录界面和功能
    云原生中间件RocketMQ-生产者核心解析、主从同步机制解析,生产者同步异步消息发送
    GPT模型结合Python-GEE遥感云大数据分析、管理与可视化技术
    slam学习
    分库分表的几个常见方面
  • 原文地址:https://blog.csdn.net/qq_36605433/article/details/126486427