1、file hello 查看文件类型
可以看到文件类型是x86_64,它是不能在ARM架构上运行的,因为它们的指令集不同。我们需要使用交叉编译工具比如arm-linux-gnueabihf-gcc来编译hello.c才能得到在ARM上运行的可执行文件
可以看的此时是32bit,ARM架构上的可执行文件
点击查看代码
#include <stdio.h>
/* 执行命令: ./hello weidongshan
* argc = 2
* argv[0] = ./hello
* argv[1] = weidongshan
*/
int main(int argc, char **argv)
{
if (argc >= 2)
printf("Hello, %s!\n", argv[1]);
else
printf("Hello, world!\n");
return 0;
}
根据上面代码,有以下几个问题:
(1).c文件有什么作用,和.h文件有什么区别
.h文件是头文件,通常包含一些函数或变量的声明
.c文件是通常包含的是函数或变量的定义
(2)include的头文件在哪里?
(3)printf函数在哪?
下面的回答来自韦东山老师教程
2、gcc编译过程
gcc是编译器的统称,包括PC平台、交叉编译工具链的gcc都是类似的功能,只是名称不一样,用法基本相同
编译过程分为四步:预处理、编译(生成汇编.s文件)、汇编(生成.o二进制文件)、链接(将.o文件链接成为可执行文件)
根据实际情况,编译可以统称上述四个步骤,也可以单独指编译生成汇编文件这一步
如何编译多个文件?
如何制作、使用动态库
什么是动态库?
动态库(Dynamic Library)是一种共享的库文件,它在程序运行时被加载到内存中,并由多个程序共享使用。在链接时,可执行文件只包含对动态库的引用,而不包含实际的库代码。运行时,动态库会被加载到操作系统指定的内存位置,并可被多个程序共享使用。因此,程序运行时依赖动态库,需要动态库保持正确性。
静态库(Static Library)是一组编译好的目标文件的集合,它们被链接到最终的可执行文件中。在编译时,静态库的代码会被完整地复制到可执行文件中,因此最终的可执行文件独立于库的存在。也因此,在运行时程序不依赖于库是否存在,但是增加了可执行文件的大小从而增加了内存使用。
动态库制作编译代码示例
点击查看代码
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 -lsub -L /libsub.so/所在目录/
gcc -o test main.o -lsub -L ./
//其中-l指定动态库名称会省略lib前缀和.so后缀,也即-lsub相当于libsub.so,后面的./表示在当前路径下寻找动态库
提示加载时找不到链接时的动态库!为什么?
链接的时候动态库的位置和运行时是一样的吗?踩坑!
程序在运行时和编译时查找的动态库路径是不一样的,编译时你可以指定动态库所在的任意一个路径,因此编译时只是包含了对库的名称以及函数的引用,但是运行时需要将库加载到指定的内存位置,此时系统会去环境变量指定的路径中查找,比如各种/lib,/usr/lib等各种lib路径下查找,但是你的动态库并没有放到指定的路径下,因此有两种方法解决:
(1)将制作的动态库放到环境变量指定的动态库路径下,比如/lib
(2)导出环境变量,增加动态库所在的路径,比如
点击查看代码
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a
//$LD_LIBRARY_PATH表示原动态库路径,在后面加上/a表示加上/a也成为动态库路径
//但是这种方式只是单次有效,最好还是把动态库放到环境变量指定路径中
制作使用静态库
点击查看代码
ar crs libsub.a sub.o sub2.o sub3.o(可以使用多个.o 生成静态库)
//ar就是压缩的意思。.a是静态库的后缀名。通过ar命令生成静态库
一些有用的编译选项
点击查看代码
gcc -E main.c // 查看预处理结果,比如头文件是哪个
gcc -E -dM main.c > 1.txt // 把所有的宏展开,存在 1.txt 里
gcc -Wp,-MD,abc.dep -c -o main.o main.c // 生成依赖文件 abc.dep,后面 Makefile 会用
echo 'main(){}'| gcc -E -v - // 它会列出头文件目录、库目录(LIBRARY_PATH)
总结一下内容
在编译时,头文件使用尖括号<>,会在指定的目录查找,也可以使用-I 指定查找目录。对于库,指定库名后也会在指定的目录查找,也可以使用-L指定目录
运行时,对于动态链接,会去环境变量指定的编译器的各种lib目录下查找,比如/lib,/usr/lib等,也可以使用export导出增加指定的动态库文件路径,但是只能在本次生效