交叉编译时关于头文件和库的那些事儿

摘要:本文主要介绍了嵌入式应用程序开发中,与头文件、库文件相关的知识。例如:默认的头文件路径、默认的库文件路径、指定头文件路径、指定库文件路径、编译静态库&动态库。

1. 开发环境

本文使用的是百问网研发的 IMX6ULL_PRO 板的开发环境。

操作系统:Ubuntu 18.04

交叉编译工具链:arm-buildroot-linux-gnueabihf-gcc

linux@ubuntu:~$ arm-buildroot-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=/home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/arm-buildroot-linux-gnueabihf-gcc.br_real
COLLECT_LTO_WRAPPER=/home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../libexec/gcc/arm-buildroot-linux-gnueabihf/7.5.0/lto-wrapper
Target: arm-buildroot-linux-gnueabihf
Configured with: ./configure --prefix=/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host --sysconfdir=/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host/etc --enable-static --target=arm-buildroot-linux-gnueabihf --with-sysroot=/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host/arm-buildroot-linux-gnueabihf/sysroot --enable-__cxa_atexit --with-gnu-ld --disable-libssp --disable-multilib --disable-decimal-float --with-gmp=/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host --with-mpc=/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host --with-mpfr=/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host --with-pkgversion='Buildroot 2020.02-gee85cab' --with-bugurl=http://bugs.buildroot.net/ --disable-libquadmath --enable-tls --enable-plugins --enable-lto --enable-threads --with-isl=/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host --with-abi=aapcs-linux --with-cpu=cortex-a7 --with-fpu=neon-vfpv4 --with-float=hard --with-mode=arm --enable-languages=c,c++,fortran --with-build-time-tools=/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host/arm-buildroot-linux-gnueabihf/bin --enable-shared --enable-libgomp
Thread model: posix
gcc version 7.5.0 (Buildroot 2020.02-gee85cab)

2. 查询默认路径

编译器有自己默认搜索的头文件路径和库文件路径。我们可以通过echo 'main(){}'| arm-buildroot-linux-gnueabihf-gcc -E -v -命令获取这些默认路径的信息。

linux@ubuntu:~$ echo 'main(){}'| arm-buildroot-linux-gnueabihf-gcc -E -v -
... 省略 ...

#include "..." search starts here:
#include <...> search starts here:
 /home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/include
 /home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/include-fixed
 /home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/../../../../arm-buildroot-linux-gnueabihf/include
 /home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include
End of search list.

... 省略 ...

LIBRARY_PATH=/home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/:/home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/:/home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/../../../../arm-buildroot-linux-gnueabihf/lib/:/home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/lib/:/home/linux/100ask/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/

... 省略 ...

在命令的执行结果中:

  • #include <...> search starts here:End of search list.之间的信息就是编译器默认搜索的头文件路径

  • LIBRARY_PATH=后面的信息就是编译器默认搜索的库文件路径。

3. 指定头文件路径

如果我们的头文件没有放在编译器默认的搜索路径下,那么就需要使用-I参数指定头文件所在的路径。

假设我们源代码文件hello.c使用的头文件分别位于/home/linux/include/mnt/include两个路径下,那么在编译时需要添加-I /home/linux/include -I /mnt/include参数。

编译命令如下:

arm-buildroot-linux-gnueabihf-gcc -I /home/linux/include -I /mnt/include -o hello hello.c

4. 指定库文件路径

如果我们的库文件没有放在编译器默认的搜索路径下,那么就需要使用-L参数指定库文件所在的路径。

假设我们源代码文件hello.c使用的库文件分别位于/home/linux/lib/mnt/lib两个路径下,那么在编译时需要添加-L /home/linux/lib -L /mnt/lib参数。

arm-buildroot-linux-gnueabihf-gcc -L /home/linux/lib -L /mnt/lib -o hello hello.c

5. 编译&使用自己的库文件

5.1 静态库 VS. 静态库

静态库(Static Library)和动态库(Dynamic Library)是两种常见的库类型,它们的主要区别在于编译时期和运行时期的行为不同。

静态库是在编译时期被链接到程序中的,也就是说,静态库的代码被复制到了程序中,成为程序的一部分。这意味着,程序在运行时不需要再加载静态库,因此静态库的执行速度较快。另外,静态库在程序中的使用也比较简单,只需要在编译时将其链接到程序中即可。

动态库是在程序运行时期被加载的,也就是说,动态库的代码不会被复制到程序中,而是在程序运行时从磁盘加载到内存中。这意味着,动态库的执行速度相对较慢,但是多个程序可以共享同一个动态库,从而节省内存。此外,动态库的更新和维护也更加方便,因为只需要替换动态库文件即可,不需要重新编译程序。

综上所述,静态库的优点是速度快、使用简单,缺点是占用空间较大,不便于更新和维护;动态库的优点是节省内存、方便更新和维护,缺点是速度相对较慢。

5.2 编译&使用静态库

  • 假设我们要将sub.cadd.c两个源文件编译成名为libnum.a的静态库,需要执行的命令如下:

    arm-buildroot-linux-gnueabihf-gcc -c sub.c -o sub.o
    arm-buildroot-linux-gnueabihf-gcc -c add.c -o add.o
    arm-buildroot-linux-gnueabihf-ar rcs libnum.a sub.o add.o
    

    静态库的命名需要是 lib[功能名称].a,例如 libnum.alibmath.a 等等。

  • 接下来,我们在编译hello.c时通过-l参数指定使用libnum.a,同时还需要-L参数指明libnum.a所在的目录。

    arm-buildroot-linux-gnueabihf-gcc -o hello hello.c -lnum -L .        (.表示libnum.a位于当前目录)
    

    需要注意的是,使用-l参数时不要使用库文件的全名,只需要功能名称即可。例如,libnum.a对应的是num, libmath.a对应的是math

  • 最后,将可执行文件hello拷贝到开发板上即可执行(不需要拷贝libnum.a文件)。

5.3 编译&使用动态库

  • 假设我们要将sub.cadd.c两个源文件编译成名为libnum.so的动态库,需要执行的命令如下:

    arm-buildroot-linux-gnueabihf-gcc -c sub.c -o sub.o
    arm-buildroot-linux-gnueabihf-gcc -c add.c -o add.o
    arm-buildroot-linux-gnueabihf-gcc -shared -o libnum.so sub.o add.o
    

    动态库的命名需要是 lib[功能名称].so,例如 libnum.solibmath.so 等等。

  • 接下来,我们在编译hello.c时通过-l参数指定使用libnum.so,同时还需要-L参数指明libnum.so所在的目录。

    arm-buildroot-linux-gnueabihf-gcc -o hello hello.c -lnum -L .        (.表示libnum.so位于当前目录)
    

    需要注意的是,使用-l参数时不要使用库文件的全名,只需要功能名称即可。例如,libnum.so对应的是num, libmath.so对应的是math

  • 最后,需要将可执行文件hellolibnum.so都拷贝到开发板上才可以执行。

    注意:libsum.so可以放到/lib目录下,系统执行hello时会自动去该目录下获取libsum.so。如果想要把libsum.so放到其他目录,那么需要将lissum.so所在的目录添加到开发板的LD_LIBRARY_PATH环境变量中。例如,我们把libsum.so放到/home/linux/hello_lib目录下,那么需要执行如下命令修改LD_LIBRARY_PATH环境变量:

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/linux/hello_lib
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值