前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个例子简单学习gcc、makefile、程序执行过程

一个例子简单学习gcc、makefile、程序执行过程

作者头像
用户10551528
发布2023-10-18 14:13:45
1940
发布2023-10-18 14:13:45
举报

test.h

代码语言:javascript
复制
#pragma once

#include<stdio.h>

//函数的声明
extern void show();

test.c

代码语言:javascript
复制
#include "test.h"

void show()
{
  printf("hello");
}

main.c

代码语言:javascript
复制
#include "test.h"

int main()
{
	show();
  
	return 0;
}

形成main.c的可执行程序hello:

代码语言:javascript
复制
gcc -o hello main.c test.c

注意:

  1. -o选项后面紧跟着的名称为可执行程序的名称,-o + ”可执行程序名称“可以出现在依赖对象的前面,也可以在后面。比如gcc main.c test.c -o hello也是可以的
  2. gcc指令用于编译形成.c文件的可执行程序。g++指令用于编译形成.cpp或者.c文件的可执行程序。g++向下兼容,但是gcc只能编译.c文件。g++的大部分指令与gcc一致

这里可能会产生疑问:test.h里包含了show方法的声明,为什么不依赖这个头文件呢

因为头文件在预处理阶段已经在main.c 和test.c 里面展开了

makefile写法:

代码语言:javascript
复制
#makefile
hello:main.c test.c 
	gcc main.c test.c -o hello #此处开头一定是缩进
	
.PHONY:clean
clean:
	rm -f hello
  1. makefile文件是自顶向下执行的,只执行第一个行程目标文件的依赖方法
  2. 在makefile中,hello是目标文件,第一行的main.c 和test.c 为目标文件的依赖文件(依赖对象),hello:main.c test.c 为二者的依赖关系,gcc main.c test.c -o hello为依赖方法
  3. 倒数第二行中,clean:也为一个依赖关系,依赖关系是可以没有依赖对象的,这个就没有。.PHONY为makefile里的一个关键字,作用是使后面的方法“总是被执行”
    1. 每个文件都有三个时间:ACM时间
      1. A(ACCESS):访问时间(读取时间)。在文件的操作中,读取是最频繁的(文件夹也属于文件),在Linux内核2.6、2.7之前,文件的每次访问都会刷新ACCESS时间,因此每次会消耗大量资源来复写文件ACCESS时间,效率极低。在更新之后,文件访问次数每次累计到一定值才会更新ACCESS时间为最后一次访问时间。
      2. C(CHANGE):改动时间。文件内容被修改的最后一次时间。
      3. M(MODIFY):更改时间。文件属性被修改的最后一次时间。文件大小、名称、权限等等都属于文件属性,所以文件内容的修改有时候也会影响文件属性,比如文件内容增多文件大小变大。
      4. 三个时间在系统下的显示顺序是A、M、C,指令stat 文件查看文件信息:
      截屏2023-09-07 12.20.28
      截屏2023-09-07 12.20.28
    2. 一定是源文件先存在,然后通过编译,形成可执行程序,因此源文件M时间一定早于可执行程序M时间。如果源文件M时间早于可执行程序M时间,此时再进行编译,是不会产生新的可执行程序覆盖原可执行程序的,因为认为源文件没有改动,没必要重新生成可执行程序。当源文件更改之后,M时间会更新,肯定比原可执行程序新,此时再次进行编译,系统比对两者M时间之后发现源文件更新,因此会生成新的可执行程序覆盖原可执行程序。
    3. “总是被执行”的意义就在于,无论依赖对象的M时间是否早于目标文件,都会执行依赖方法。因此.PHONY:clean作用就是无论可执行程序hello的新旧、是否存在,总是会执行rm -f hello来删除掉hello
  4. 指令make来执行makefile里的生成可执行程序的依赖方法。指令make clean来执行makefile里面删除hello的方法

c、cpp程序执行过程:

截屏2023-09-07 12.35.10
截屏2023-09-07 12.35.10

.c .h 预处理(头文件展开等) 形成.i

gcc指令为gcc -E test.h test.c,可以加-o选项指定生成的名称,默认名称跟.c文件的名称一样,下同

编译形成 .s汇编文件

gcc指令为gcc -S test.i

汇编形成 .o二进制文件(目标文件)

gcc指令为gcc -c test.s 此处“目标文件”含义和上面makefile中的“目标文件”含义不同,makefile中的含义是目标要形成的文件,而此处的名字就叫做”目标文件“

(与库文件)链接形成 -out可执行程序

gcc指令为gcc test.s,默认生成文件名称为a.out,可以加-o选项指定名称,名称可不加.out后缀

文件后缀的记忆方法:iso gcc指令的记忆方法:ESc,c是小写

注意,gcc指令是的含义是”进行到这一步为止“,因此每步的gcc指令并不依赖上一步的生成的文件

比如可以直接令.c文件进行到汇编结束,生成.o文件gcc -c test.c

或者直接.c文件生成可执行程序gcc test.c

在一般的编译器下,会保留生成.o目标文件,然后将目标文件统一链接形成可执行文件

几个.c源文件就会生成几个.o目标文件

如果想要在makefile中,先形成.o目标文件,然后再链接形成可执行文件,写法为:

代码语言:javascript
复制
hello:test.o main.o
	gcc test.o main.o -o hello
test.o:test.c
	gcc -c test.c
main.o:main.c
	gcc -c main.c
	
.PHONY:clean
clean:
	rm -f *.o hello
  1. makefile自顶向下执行,在执行第一条的时候,找不到依赖的.o文件,会向下执行和寻找
  2. clean此处使用了通配符*,删除当前目录下所有.o结尾的文件

更多内容查看“Makefile初学指南”

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档