当前位置:   article > 正文

【Linux】 GCC/G++与Makefile使用

【Linux】 GCC/G++与Makefile使用

Linux GCC/G++使用

GCC如何完成

格式:gcc [选项] 要编译的文件 [选项] [目标文件]

常用选项:

  • -E:让gcc在预处理结束后停止编译过程,输出.i的C语言原始文件。
  • -S:该选项只是进行编译而不是进行汇编,最终生成汇编代码的.s文件。
  • -o <filename>:指定输出目标文件名。
  • -c:仅编译,不链接,输出.o二进制目标文件。

程序从源代码到可执行文件,经过预处理、编译、汇编与链接四个步骤:

  1. 预处理:展开头文件、宏替换、条件编译处理,生成经过预处理的.i文件。

示例:

gcc -E hello.c -o hello.i
  • 1
  1. 编译:语法检查与生成汇编代码,检查无误生成汇编语言的.s文件。

示例:

gcc -S hello.i -o hello.s
  • 1
  1. 汇编:将编译阶段生成的.s汇编代码转换为机器码,生成.o目标文件。

示例:

gcc -c hello.s -o hello.o
  • 1
  1. 链接:合并目标文件和库,生成可执行文件(如.out)。

示例:

gcc hello.o -o hello
  • 1

程序流程图:

	graph LR;
   		![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/2281bed57cab457e98467f0bf078fbcb.jpeg#pic_center)
A[源代码文件 .c] --> B[预处理 .i]
    	B --> C[编译 .s]
    	C --> D[汇编 .o]
    	D --> E[链接 可执行文件]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

动态链接与静态链接

动态链接

在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时
链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为.so

静态链接

静态链接时,程序包含所有依赖库的代码,生成的可执行文件较大,但无需外部库即可独立运行。其后缀名一般为.a

可以使用file命令查看文件是动态链接还是静态链接:

$ file /path/to/your/program
/path/to/your/program: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=0x4a00b217499069528e862542e52e31418370a71b, not stripped
  • 1
  • 2

上述输出中的“statically linked”表明该文件是静态链接的。对于动态链接的文件,输出中则会显示“dynamically linked”。

此外可以使用ldd命令查看所使用的库函数:

$ ldd /path/to/your/program
linux-vdso.so.1 =>  (0x00007fffe3ff9000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f93b7d67000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f93b79ab000)
...
  • 1
  • 2
  • 3
  • 4
  • 5

libc.so中去掉lib前缀和.so后缀,可以看出它是调用了C语言的标准库。

Makefile 的深入理解与应用

在 Linux 或 Unix 系统中,Makefile 是一种用于自动化构建过程的脚本文件,它告诉 make 程序如何编译和链接源代码来创建可执行文件。Makefile 文件可以命名为 makefileMakefile 或者任何其他名字,但是使用大写的 Makefile 是一个常见的约定。

示例 Makefile

在 Makefile 中,规则是构建过程的核心,它们告诉 make 如何以及何时更新目标文件。规则的基本语法如下:

target: dependencies
    commands
  • 1
  • 2
  • target:规则的目标,通常是需要构建的文件。
  • dependencies:目标的依赖项,即创建目标所需的文件。
  • commands:一系列 shell 命令,用于构建目标。

以下是一个简单的 Makefile 示例,用于编译 change.c 并生成可执行文件 mycode

mycode: change.c
    gcc -o mycode change.c
  • 1
  • 2
规则解析

在这个示例中,mycode 是一个目标,change.c 是它的依赖项。当 make 运行时,如果 change.cmycode 新或者 mycode 不存在,那么 make 将执行规则中定义的命令来编译 change.c

伪目标 .PHONY

伪目标用于执行非文件相关的任务,如清理或初始化等。由于伪目标并不对应于文件系统中的文件,因此不会受到时间戳的影响,每次都会执行其命令。使用 .PHONY 关键字可以显式地将目标标记为伪目标:

.PHONY: clean
clean:
	rm -f *.o mycode
  • 1
  • 2
  • 3

这里 clean 目标用于删除所有 .o 文件和 mycode 文件,即使这些文件不存在,make 也会尝试执行这个目标。

Makefile 中的 Tab 字符

在 Makefile 中,命令必须使用 Tab 字符来缩进,而不是空格。这是因为 make 解释器期望 Tab 来标识命令行。

更新文件时间戳

make 会检查目标和依赖项的修改时间戳。如果任何一个依赖项的修改时间比目标晚,或者目标不存在,那么 make 将执行相应的命令来更新目标。

为了触发重新编译,可以使用 touch 命令更新文件的时间戳。例如,如果修改了 change.c 文件的内容,但是时间戳没有改变,可以运行:

touch change.c
  • 1

这将更新 change.c 的时间戳,使 make 认为文件已经被修改,并触发重新编译。

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/827287
推荐阅读
相关标签
  

闽ICP备14008679号