Makefile学习:第一章 GCC的简易用法

参考:《鸟哥的LINUX私房菜》

一、gcc 的简易用法

        假设我们先在linux的控制台界面中使用 nano hello.c ,进入文件后写一个简单的程序。现在要用GCC来编译运行,我们有两种方式:

// hello.c
#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

 1.1 分布编译链接:

gcc -c hello.c     # 仅预处理、编译

gcc -o hello hello.o    # 仅链接

# -o hello 指定输出的可执行文件名为hello
# 后面的 hello.o 是要链接的目标文件

  gcc -c hello.c这个命令告诉GCC仅进行预处理、编译(将C代码转换为汇编代码,再转换为目标代码)步骤,但不进行链接,最终生成一个 目标文件(.o文件)-c选项表示编译并停止,不链接。

        通过先gcc -c hello.c生成目标文件,然后再gcc -o hello hello.o进行链接,这种方式在大型项目中更为常见,尤其是在需要对多个源文件进行单独编译,最后统一链接的场景。这样做的好处是可以分开编译阶段和链接阶段,提高编译效率,特别是在修改了项目中的一部分代码时,只需要重新编译修改过的文件,而不是整个项目。

1.2 直接编译链接:

gcc -o hello hello.c

        直接使用gcc -o hello hello.c时,GCC完成了整个过程——预处理、编译、汇编、以及链接。它从源代码开始,直接产生一个可执行文件。这种方式适合于简单的项目或一次性编译的情况。

 1.3 最后运行可执行文件 ./hello

1.4 问题:为什么我们要制作出目标文件?

比如现在我们有一个 hello.c 主程序和 thanks.c 子程序:

hello.c (主程序)

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    thank();
    return 0;
}
thanks.c (子程序)

#include <stdio.h>

void thank(void) {
    printf("Thank you\n");
}

先对 hello.c 和 thanks.c 编译,再将 hello.o 和 thanks.o 链接到可执行文件 hello

        由于我们的源代码文件有时并非仅只有一个文件,所以我们无法直接进行编译。这个时候就需要先产生目标文件,然后再以链接制作成为二进制可执行文件。

        另外,假设我们更新了 thanks.c 文件的内容,那只要重新编译 thanks.c 来产生新的 thanks.o ,然后再以链接制作出新的二进制可执行文件即可,而不需要重新编译其他没有修改过的源代码文件。当我们实际在企业开发的时候,往往一个工程的代码量很大,如果将源代码全部编译则要消耗大量的时间,甚至性能不好的电脑或出现卡死的现象。

二、调用外部函数库:加入链接的函数库 

hello.c (主程序不变,但我们将调用thanks.c中的新功能)

#include <stdio.h>

// 如果在hello.c中直接调用了calculate_sine,则需要声明

extern double calculate_sine(double angle_degrees);

int main() {
    printf("Hello, World!\n");
    double angle_in_degrees = 45.0;
    double sine_value = calculate_sine(angle_in_degrees);
    printf("The sine of %.2f degrees is: %.4f\n", angle_in_degrees, sine_value);
    return 0;
}

thanks.c (添加计算正弦值的功能,使用math.h库)

#include <stdio.h>
#include <math.h> // 包含数学函数库

double calculate_sine(double angle_degrees) {
    double angle_radians = angle_degrees * M_PI / 180.0; // 将角度转换为弧度
    return sin(angle_radians); // 使用sin()函数计算正弦值
}

假设我们和刚刚一样的步骤: 

 正确步骤:

2.1 函数库的链接(库文件位于非标准路径) 一般情况

gcc -c hello.c thanks.c
gcc hello.o thanks.o -lm -o hello

         [-lm] 这是一个链接选项,告诉GCC在链接过程中链接数学库(Math Library)。这里的-l是一个通用的选项,用于指定要链接的库名,而紧跟其后的m指定了具体的库名。这里的m代表数学库(libm的缩写),它是标准C库的一部分,提供了许多数学相关的函数,比如sin(), cos(), sqrt()等。当编译器遇到代码中调用了这些函数时,就需要通过-lm来确保对应的库被链接进来,以便在运行时能够找到这些函数的实现。

        当你在GCC命令行中使用-lm标志时,实际上是在告诉编译器的链接阶段需要链接标准数学库。这个库可能以动态库(如libm.so静态库(如libm.a的形式存在。动态库在程序运行时被加载,而静态库则在编译时被直接嵌入到可执行文件中。在大多数Linux系统中,如果不特别指定,GCC通常会优先寻找动态库。

2.2 函数库的链接(库文件位于非标准路径)

        如果您的库文件位于非标准路径,比如一个特定的liblib64目录下,您需要使用-L选项来指定额外的库搜索路径,紧接着使用-l指定库名。例如,如果有一个库文件libcustom.so位于/path/to/my/libs/lib64目录下,您可以这样编译:

gcc hello.o thanks.o -L/path/to/my/libs/lib64 -lcustom -lm -o hello
  • -L/path/to/my/libs/lib64告诉GCC在指定的目录中查找库文件。
  • -lcustom指示链接器链接名为libcustom.solibcustom.a的库。

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值