前言:
源文件需要经过编译才能生成可执行文件。
在 Windows 下进行开发时,只需要点几个按钮即可编译,集成开发环境(比如 Visual studio)已经将各种编译 工具的使用封装好了。
Linux 下也有很优秀的集成开发工具,但是更多的时候是 直接使用编译工具;即使使用集成开发工具,也需要掌握一些编译选项。
PC 机上的编译工具链为 gcc、ld、objcopy、objdump 等,它们编译出来的 程序在 x86 平台上运行。要编译出能在 ARM 平台上运行的程序,必须使用交叉编译工具 xxx-gcc、xxx-ld 等(不同版本的编译器的前缀不一样,比如 arm-linux-gcc)
GCC 编译过程(精简版)
一个 C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇 编(assembly)和链接(linking)等 4 步才能变成可执行文件。
通过不同的 gcc 选项可以控制这些过程:
gcc 使用示例: 执行“gcc -o hello hello.c -v”时,可以查看到这些步骤:
可以手工执行以下命令体验一下:
常用编译选项
1.-c
预处理、编译和汇编源文件,但是不作链接,编译器根据源文件生成 OBJ 文 件。缺省情况下,GCC 通过用`.o'替换源文件名的后缀`.c',`.i',`.s'等, 产生 OBJ 文件名。可以使用-o 选项选择其他名字。GCC 忽略-c 选项后面任何无 法识别的输入文件。
2.-S
编译后即停止,不进行汇编。对于每个输入的非汇编语言文件,输出结果是 汇编语言文件。缺省情况下,GCC 通过用`.s'替换源文件名后缀`.c',`.i'等 147 / 566 等,产生汇编文件名。可以使用-o 选项选择其他名字。GCC 忽略任何不需要汇编 的输入文件。
3.-E
预处理后即停止,不进行编译。预处理后的代码送往标准输出。
4.-o file
指定输出文件为 file。无论是预处理、编译、汇编还是链接,这个选项都可 以使用。如果没有使用`-o'选项,默认的输出结果是:可执行文件为`a.out'; 修改输入文件的名称是`source.suffix',则它的 OBJ 文件是`source.o',汇 编文件是 `source.s',而预处理后的 C 源代码送往标准输出。
5.-v
显示制作 GCC 工具自身时的配置命令;同时显示编译器驱动程序、预处理器、 编译器的版本号。
示例1:找不到头文件目录,使用-I 指定头文件目录
示例2:libsub.so通常写为lsub,找不到库文件目录,使用-L 指定库文件目录
怎么编译多个文件
1.一起编译、链接:
gcc -o test main.c sub.c
2.分开编译,统一链接:
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -o test main.o sub.o
制作、使用动态库
1.制作、编译动态库:
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -shared -o libsub.so sub.o sub2.o sub3.o(可以使用多个.o 生成动态库)
gcc -o test main.o libsub.so
gcc -o test main.o libsub.so也可被替换:使用-L 指定库文件目录
2.运行:
1.先把 libsub.so 放到 Ubuntu 的/lib 目录,然后就可以运行 test 程序。
2.如果不想把 libsub.so 放到/lib,也可以放在某个目录比如/a,然后如下执行:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a
./test
制作、使用静态库
1.制作、编译静态库:
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
ar crs libsub.a sub.o
gcc -o test main.o libsub.a (如果.a 不在当前目录下,需要指定它的绝对或相对路径)
2.运行:
不需要把静态库 libsub.a 放到板子上,直接运行
注意:
执行 arm-buildroot-linux-gnueabihf-gcc -c -o sub.o sub.c 交叉编译需要在最后面加上-fPIC 参数。