Linux多文件编译

本文详细解释了C语言在Linux编译过程中的四个阶段(预编译、编译、汇编和链接),并通过Makefile自动化管理,包括单文件和多文件项目的构建,展示了如何使用Makefile简化编译步骤并实现依赖文件的自动识别。
摘要由CSDN通过智能技术生成

        在windows系统中我们平常使用的都是已经集成化的编译软件,但是大家并不知道c语言在实际的编译过程是怎样的,在Linux系统中写了多个文件是如何进行编译的。其实windows系统下的编译软件的原理就是Makefile。

        在初学Linux时,我们通过gcc -Wall hello.c -o hello,来生成一个可执行文件。但是在实际编译的时候,这个过程经历了4个阶段:预编译、编译、汇编、链接。
预编译(Preprocessing)是程序编译过程中的一个阶段,它在编译器对源代码进行实际编译之前进行。预编译过程主要由预处理器(Preprocessor)负责执行,它根据预处理指令对源代码进行处理,并生成一个新的被处理过的代码文件。在gcc后面添加-E选项,生成一个.i文件,接下来进行编译。

gcc -E hello.c -o hello.i

编译可以将C语言代码转换为汇编代码的过程。编译器(Compiler)将源代码进行语法分析和语义检查,并将其转换为汇编语言或直接生成机器码。通过-S选项,根据.i文件生成.s文件。

gcc -S hello.i -o hello.s

汇编语言是一种与机器指令一一对应的书写和理解较容易的语言。汇编器(Assembler)将汇编语言代码转换为机器指令的二进制表示形式。通过-c选项,gcc编译器便会根据.s文件生成一个计算机可识别的.o文件。

gcc -c hello.s -o hello

其实上三步也可以将其合并起来,直接输入gcc -c hello.c -o hello,即可一步生成可执行文件。因为hello.c是一个单独的文件,不需要链接,所以不执行链接这一步。那么在如果当前目录有如下文件:main.c  fun1.c  fun2.c myinclude.h就需要链接了

链接是将多个目标文件和库文件合并为一个可执行文件的过程。在编译时,多个源文件会被分别编译为独立的目标文件。链接器(Linker)负责将这些目标文件中的符号引用和定义进行解析和连接,生成最终的可执行文件。

//main.c
#include"myhead.h"
int main(){
    function1();
    function2();
    return 0;
}
//fun1.c
#include"myhead.h"
void function1(){
    printf("This is funtion one\n");
}
//fun2.c
#include"myhead.h"
void function2(){
    printf("This is funtion two\n");
}
//myhead.h
#ifndef _MYHEAD_H
#include<stdio.h>
void function1();
void function2();
#endif

 这是除了头文件不需要编译,main.c  fun1.c  fun2.c文件都需要gcc -c 生成一个可执行文件,然后再链接gcc main.o fun1.o fun2.o -o test。这样编译就会非常麻烦,每次编译调试,都需要去生成.o文件,然后再去链接。因此我们可以通过Makefile去帮我们执行整个编译的四个完整过程。

        Makefile 是一种用于自动化构建和管理程序的文件,它定义了一组规则和命令,用于构建、编译和链接源代码以生成可执行文件、库文件或其他目标文件。我们可以在Makefile中定义一些变量,用于存储编译器、编译选项、源文件列表、目标文件名等信息。通过使用变量,可以方便地在整个 Makefile 文件中重复使用和修改这些值。根据编译和链接的规则,以及依赖关系。每个规则包含一个目标文件和其依赖项,以及用于生成目标文件的命令。Makefile 使用这些规则来判断哪些文件需要重新编译。就比如说gcc -c hello.c -o hello,其中要生成的文件hello.i就是目标文件,而它是依赖于hello.c文件生成的,所以hello在这一个过程中是依赖文件。

hello:hello.c               //文件依赖关系
    gcc -c hello.c hello    //编译命令

这只是单个文件编译,那么在编译之前所说的test文件包含两个函数,一个头文件和一个主函数,我们也不需要去逐个编译,下面介绍三个自动变量。$@用于指代造成命令运行的目标,$^表示一个文件依赖关系中的所有依赖文件,$<依赖关系中的第一个依赖文件。

test:main.o fun1.o fun2.o    // test的依赖关系
    gcc $^ -o $@             // gcc main.o fun1.o fun2.o -o test
%.o:%.c                      // %.o通配符,指代所有要生成的.o目标文件
    gcc -c $< -o $@          // gcc -c main.c -o main.o
                             // gcc -c fun1.c -o fun1.o
                             // gcc -c fun2.c -o fun2.o

先提醒一下,gcc的前面是tab键,而不是空格。通过自动变量的替换,可以简化写Makefile的步骤,这样一个生成test的Makefile文件就写好了,然后只需要在文件所在目录输入make命令即可生成test可执行文件。如果哪一个文件有改动,make工具会自动识别该文件是否被更新或更改,然后只从新编译新的文件,再链接即可重新编译test文件。
 

linux@ubuntu:~/test/maketest$ make
gcc -c main.c -o main.o
gcc -c fun1.c -o fun1.o
gcc -c fun2.c -o fun2.o
gcc main.o fun1.o fun2.o -o test             
linux@ubuntu:~/test/maketest$ ./test
This is funtion one
This is funtion two
linux@ubuntu:~/test/maketest$ 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值