04 交叉编译
交叉编译
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 | cd install/lib |
问题记录
问题一:
在我们给嵌入式板子移植第三方库的时候,如果要移植的第三方库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,千万不能用错了,不然会出问题的