交叉编译

CMake交叉编译工具链

sysroot

在使用==Cmake==搭建交叉编译环境时,需要指定sysroot,这个sysroot到底是什么呢?

在嵌入式开发中,sysroot是一个为了方便移植和交叉编译而创建的特殊目录。他包含了用于目标系统的头文件、库文件。在交叉编译时,我们通常不希望用宿主机的头文件和库文件,而仅使用sysroot中的头文件和库文件,以保证生成的东西能够在目标系统运行

未设置--sysroot 设置了--sysroot=dir
头文件搜索路径 /usr/include dir/usr/include
依赖库搜索路径 /usr/lib dir/usr/lib

如何查看sysroot

可以用以下方式查看sysroot

1
${CC} -print-search-dirs

交叉编译后怎么放到开发板

我们在宿主机交叉编译一个第三方库后,为了能让编译出的程序能在开发板上跑起来,必须把一些重要的文件放到开发板的文件系统中(比如NFS),那么具体要移动哪些文件呢?

我们以tslib这个第三方库为例来看一下!

tslib在交叉编译 + make install后,会在install的目录下有4个子文件夹:

  • bin:一些测试该库的小程序
  • etc:该库用到的配置文件
  • include:一些头文件,用户在使用该第三方库编译自己的程序时需要
  • lib:一些动态/静态库文件,用户在:使用该第三方库编译自己的程序、运行依赖此第三方库的时候需要
  • share:文档之类的东西

不仅仅是tslib交叉编译后得到的是这样几个文件夹,其实=大多数第三方库==都是这样的==!

作为使用者,我们只需要拷贝一下几个文件夹:

  • 拷贝./bin目录中的所有可执行文件到${nfsroot}/usr/bin(==不必须==)
  • 拷贝./lib目录的所有文件到${nfsroot}/usr/lib
  • 拷贝./etc目录的所有配置文件到${nfsroot}/usr/etc

经过以上操作就行了,因为不需要在开发板上编译,所以就不需要拷贝./include目录下的头文件了

当然,库和可执行文件也不是必须放到这2个路径下,如果放在别的路径下的话,就得改环境变量,比较麻烦!

注意事项

  • 由于./lib下的库文件,可能存在链接关系,因此在拷贝时,最好先打包,拷贝整个压缩包,然后cd到目标路径后,再解压
1
2
3
4
5
6
cd install/lib
tar -czf libmqtt.tar.gz ./* #创建压缩包

cp libmqtt.tar.gz nfs/usr/lib
cd nfs/usr/lib
tar -vxzf libmqtt.tar.gz #解压缩

问题记录

问题一:

​ 在我们给嵌入式板子移植第三方库的时候,如果要移植的第三方库A又依赖了另一个第三方库B,则所有涉及到的库都得移植,这其实是个比较麻烦的事情。并且有的时候还有更复杂的问题:第三方库B没有用CMAKE构建,但是第三方库A却用find_package()的方式添加第三方库B!

​ 这个问题来自于我交叉编译MQTT库的时候,OpenSSL作为依赖,是用Makefile构建的,但是MQTT却用CMAKE构建,在我用CMAKE-GUI配置好了路径后,发现怎么CMAKE一直报错,找不到OpenSSL,最后我看了MQTT的CMakeLists.txt才发现问题所在!但是这样解决不了问题啊。要知道find_package()本质上是会寻找并运行CMAKE安装时自带的FindOpenSSL.cmake,所以我的解决方法是打开该文件,看他到底干了啥?

​ 最后发现FindOpenSSL.cmake中只是设置了几个变量:OpenSSL_xxx_PATH之类的,所以我在配置MQTT的CMAKE时,手动给这几个变量赋值,最后问题就解决了

问题二:

​ 编译MQTT的时候,一直提示找不到openssl/ssl.h,但是我已经把这个路径都放到环境变量里了

​ 问题出现的原因:mqtt代码里通过#include <openssl/ssl.h>来添加的,#include <xxx>只会在系统标准头文件目录搜索,而不会搜索其他位置,故我的解决方案是把OpenSSL的整个头文件目录都放到了mqtt的源码路径下

问题三:用错Makefile

​ 我们在手动编译第三方库的时候,一般会创建个build文件夹,然后在里面cmake ..make,注意此时使用的Makefile是build目录下的,有的工程顶层也有个Makefile,千万不能用错了,不然会出问题的