嵌入式Linux应用开发基础知识(二)——GCC总体选项

GCC在编译时可以有很多选项可以进行选择,方便调试,本章着重介绍GCC的编译选项

1. GCC总体选项

  • -C: 预处理、编译和汇编源文件,但是不作链接,编译器根据源文件生成OBJ文件。缺省情况下,GCC通过用.o'替换源文件名的后缀.c’,.i',.s’等,产生OBJ文件名。可以使用-o选项选择其他名字。GCC忽略-c选项后面任何无法识别的输入文件。
  • -S:编译后即停止,不进行汇编。对于每个输入的非汇编语言文件,输出结果是汇编语言文件。缺省情况下,GCC通过用.s'替换源文件名后缀.c’,`.i’等等,产生汇编文件名。可以使用-o选项选择其他名字。GCC忽略任何不需要汇编的输入文件。
  • -E:预处理后即停止,不进行编译。预处理后的代码送往标准输出。
  • -o file:指定输出文件为file。无论是预处理、编译、汇编还是链接,这个选项都可以使用。如果没有使用-o'选项,默认的输出结果是:可执行文件为a.out’;修改输入文件的名称是source.suffix',则它的OBJ文件是source.o’,汇编文件是 `source.s’,而预处理后的C源代码送往标准输出。
  • -V : 显示制作GCC工具自身时的配置命令;同时显示编译器驱动程序、预处理器、编译器的版本号。

2. 实验

2.1 测试代码

main.c

#include <stdio.h>
#include "sub.h"

int main(int argc, char *argv[])
{
       int i;
       printf("Main fun!\n");
       sub_fun();
       return 0;
}

sub.c

void sub_fun(void)
{
       printf("Sub fun!\n");
}

sub.h

void sub_fun(void);

2.2 -C选项

-C选项是预处理、编译和汇编源文件,但是不作链接,所以生成的文件后缀为 .o 。我们可以使用如下命令逐一处理:

gcc  -c  -o  main.o  main.c
gcc  -c  -o  sub.o  sub.c

经过这一步我们就生成了main.o和sub.o OBJ文件, 如果我们想生成可执行文件的话,需要将这两个OBJ文件进行链接。

gcc  -o  test  main.o  sub.o

编译记录:
在这里插入图片描述
是不是突然会有疑问,使用

gcc -o test main.c sub.c 

可以达到相同的作用,而且还省这么多步骤,如果有几百上千的源文件,当我们只修改了其中一个文件时,采用上述一条命令进行编译的话,编译速度相当慢,我们就可以采用-C选项单独编译修改的源文件,最后再将所有的OBJ文件进行链接。

-S -E选项我们在上一张已经讲解了,在这里我们就不多赘述。

3. 附加选项

3.1 -Wall

这个选项基本打开了所有需要注意的警告信息,比如没有指定类型的声明、在声明之前就使用的函数、局部变量除了声明就没再使用等。
如下图所示:
在这里插入图片描述

3.2 -g 调试选项

以操作系统的本地格式(stabs,COFF,XCOFF,或DWARF)产生调试信息,GDB能够使用这些调试信息。在大多数使用stabs格式的系统上,-g'选项加入只有GDB才使用的额外调试信息。可以使用下面的选项来生成额外的信息:-gstabs+‘,-gstabs',-gxcoff+’,-gxcoff',-gdwarf+‘或`-gdwarf’,具体用法请读者参考GCC手册

3.3 -0 优化选项

3.3.1 -O或-O1

优化:对于大函数,优化编译的过程将占用稍微多的时间和相当大的内存。不使用-O'或-O1’选项的目的是减少编译的开销,使编译结果能够调试、语句是独立的:如果在两条语句之间用断点中止程序,可以对任何变量重新赋值,或者在函数体内把程序计数器指到其他语句,以及从源程序中精确地获取你所期待的结果。
不使用-O'或-O1’选项时,只有声明了register的变量才分配使用寄存器。
使用了-O'或-O1’选项,编译器会试图减少目标码的大小和执行时间。如果指定了-O'或-O1’选项,,-fthread-jumps'和-fdefer-pop’选项将被打开。在有delay slot的机器上,-fdelayed-branch'选项将被打开。在即使没有帧指针 (frame pointer)也支持调试的机器上,-fomit-frame-pointer’选项将被打开。某些机器上还可能会打开其他选项。

3.3.2 -O2

多优化一些。除了涉及空间和速度交换的优化选项,执行几乎所有的优化工作。例如不进行循环展开(loop unrolling)和函数内嵌(inlining)。和-O'或-O1’选项比较,这个选项既增加了编译时间,也提高了生成代码的运行效果。

3.3.3 -O3

优化的更多。除了打开-O2所做的一切,它还打开了-finline-functions选项。

3.3.4 -O0

不优化。

如果指定了多个-O选项,不管带不带数字,生效的是最后一个选项。
在一般应用中,经常使用-O2选项,比如对于options程序:

gcc  -O2  -c  -o  main.o  main.c
gcc  -O2  -c  -o  sub.o  sub.c
gcc  -o  test  main.o  sub.o

4. 目录选项

下列选项指定搜索路径,用于查找头文件,库文件,或编译器的某些成员。

4.1 -Idir

在头文件的搜索路径列表中添加dir 目录。
头文件的搜索方法为:如果以“#include < >”包含文件,则只在标准库目录开始搜索(包括使用-Idir选项定义的目录);如果以“#include “ ””包含文件,则先从用户的工作目录开始搜索,再搜索标准库目录。

4.2 -I-

任何在-I-'前面用-I’选项指定的搜索路径只适用于#include "file"'这种情况;它们不能用来搜索#include '包含的头文件。如果用-I'选项指定的搜索路径位于-I-'选项后面,就可以在这些路径中搜索所有的#include'指令(一般说来-I选项就是这么用的)。还有,-I-'选项能够阻止当前目录(存放当前输入文件的地方)成为搜索#include "file"'的第一选择。 -I-'不影响使用系统标准目录,因此,-I-'和-nostdinc’是不同的选项。

4.3 -Ldir

在`-l’选项的搜索路径列表中添加dir目录。

4.4 -I 实验

GCC编译器对于使用<>方式进行添加的头文件,编译器首先在系统目录下面进行查找,找不到则报错,而使用""方式添加的头文件,则先在程序的当前目录进行查找,找到不到时,再进入系统目录进行查找,再查找不到,则报错。如果我们使用<>添加用户的目录时,需要使用-I 指定查找路径。
我们将main.c改为如下代码:

#include <stdio.h>
#include <sub.h>

int main(int argc, char *argv[])
{
       int i;
       printf("Main fun!\n");
       sub_fun();
       return 0;
}

gcc -o test main.c sub.c

进行编译,如下图所示提示查找不到sub.h头文件
在这里插入图片描述
此时我们查看编译过程:
在这里插入图片描述
可以看到只在上图红框中的系统目录进行查找头文件
当我们添加-I选项(./表示当前目录)时,如下图所示
在这里插入图片描述
编译没有报错。
我们再看看编译过程
在这里插入图片描述
此时我们看到了 添加了个./ 的路径。
试想,如果不想加-I怎么办?那么此时你需要将sub.h头文件存放到系统路径下面,为了系统的稳定性,不建议这么做。

4.4 -L和-l 实验

-L和-l是针对库文件的,什么是库呢?相当于对源文件进行压缩一样,把库文件给别人,这样就看不到源代码了,相对比较安全。库文件分为动态库(.so文件)和静态库(.a文件)

4.4.1 生成动态库

动态库命名一般是采用libxx.so形式,lib为库文件的前缀,.so为后缀,加入-shared选项可以将多个OBJ文件打包生成一个库文件。
我们先生成目标文件

gcc -c -o main.o  main.c
gcc -c -o sub.o   sub.c
gcc -shared  -o libsub.so  sub.o // 链接库文件

使用shared参数链接成库文件

gcc -shared  -o libsub.so  sub.o // 链接库文件

4.4.2 编译动态库

编译时需要指定库名字(-l选项)和指定库文件存放的路径(-L选项),尤其注意的库文件的名字需要去掉前缀lib和后缀.so(-lsub)
执行下面命令用于链接main.o和libsub.so库文件, ./表示当前目录

gcc -o test3 main.o -L ./ -lsub

除了指定库文件的路径,我们也可以直接将库文件存放于系统路径,查看系统路径只需加上-v即可
在这里插入图片描述
不过不建议采用上述方式,这样不利于代码的移植。

同时我们也可以不用使用-l选项指定库文件名称和使用-L指定路径,直接可以把库文件当做OBJ文件进行编译,此时需要将库文件的全称写上

gcc -o test2 main.o libsub.so

4.4.3 运行包含动态库的程序

包含动态库的程序中如果需要运行程序,直接运行会报错的,需要先指定库文件的存放路径。如果不指定则会报如下错误:
在这里插入图片描述
设置库文件的运行路径时,需要设置LD_LIBRARY_PATH参数,使用方法如下所示:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:+路径
如果库文件在当前目录,那么执行如下命令:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

运行程序:
在这里插入图片描述

4.4.4 制作静态库

使用crs 选项可以指定静态库,静态库以lib作为前缀,使用.a作为后缀。
使用举例:

gcc -c -o main.o  main.c
gcc -c -o sub.o   sub.c
ar  crs  libsub.a  sub.o  sub2.o  sub3.o(可以使用多个.o生成静态库)
gcc  -o  test  main.o  libsub.a  (如果.a不在当前目录下,需要指定它的绝对或相对路径)

运行:
不需要把静态库libsub.a放到板子上。
注意:执行arm-linux-gnueabihf-gcc -c -o sub.o sub.c交叉编译需要在最后面加上 -fPIC参数。

5. 总结

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《嵌入Linux应用程序开发详解》是一本非常实用的Linux应用程序开发指导书,其主要讲解了嵌入Linux系统应用程序的开发过程、技术、工具和优化方法。 本书涵盖了Linux应用程序开发基础知识和实际案例,详细介绍了Linux系统的组成原理,以及如何开发应用程序。书中内容涉及嵌入Linux系统的内核、文件系统、网络等方面,通过实践案例,为读者解决了开发过程中遇到的各种问题。 本书结构清晰,内容实用,读者可以从中学习到很多Linux开发的技巧和经验。其中,本书还对Linux应用程序性能优化方面进行了详细讲解,介绍了如何优化系统调用、内存管理、文件系统等性能方面的技术和方法。 总之,《嵌入Linux应用程序开发详解》是一本非常好的嵌入Linux应用程序开发入门书,对于想要从事Linux应用程序开发的工程师或编程爱好者来说,都是一本值得推荐的书籍。 ### 回答2: “嵌入linux应用程序开发详解”是一本深入介绍嵌入linux应用程序开发的书籍,它详细讲解了嵌入Linux系统的基本原理、应用开发、系统调试等方面,适合想要学习嵌入Linux应用程序开发的人阅读。 该书籍首先介绍了嵌入系统的概念以及嵌入Linux系统的基本架构和启动流程,随后详细讲解了Linux系统下的应用程序开发,如进程管理、文件系统、网络编程、驱动程序等。此外,该书还介绍了如何在开发过程中使用调试器进行系统调试和性能分析。 在讲解应用程序开发的过程中,该书重点介绍了如何使用GCC编译器和GDB调试器,以及如何使用BusyBox和uClibc等开源软件库实现系统开发,读者可以通过这些工具和库知道如何实现嵌入Linux系统的开发过程。 总的来说,“嵌入linux应用程序开发详解”是一本非常适合想要深入学习嵌入Linux应用程序开发的人阅读的书籍,它全面深入地讲解了嵌入Linux系统的各个方面,不仅是一本理论性的书籍,还能带领读者一步步实际操作。 ### 回答3: 嵌入Linux应用程序开发详解PDF一书详细介绍了嵌入系统以及嵌入Linux系统的相关知识。本书首先介绍了嵌入系统中的硬件结构和软件结构,然后介绍了嵌入Linux系统以及Linux操作系统的基本工作原理和操作方法。 本书旨在帮助开发人员了解嵌入系统的基本原理以及如何使用Linux系统进行应用程序开发。本书以上传统的C语言为基础,通过介绍Linux下的文件系统、进程管理、内存管理、设备驱动等基础知识,使读者能够深入了解如何开发嵌入Linux应用程序,如网络应用程序、多媒体应用程序等。 本书特设了大量实例和应用场景,通过实例讲解的方帮助读者理解和掌握开发嵌入Linux应用程序的方法和技巧。此外,本书还介绍了嵌入Linux系统的调试、测试和优化等相关内容,让读者能够全面掌握嵌入Linux应用程序的开发过程。 总之,本书是一本深入浅出、实用性强的嵌入Linux应用程序开发详解。通过详细介绍嵌入系统和Linux操作系统的基础知识,以及丰富的实例和应用场景,本书可帮助读者快速掌握开发嵌入Linux应用程序的方法和技巧,从而提高其开发效率和成功率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零涂

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值