最近开始做基于Linux的嵌入式的开发,因为从事物联网方面的开发,所以从手头的一个物联网网关的项目入手。
我的项目安排是这样的:首先,熟悉linux应用开发和C语言基础;然后做一些开源项目的移植测试(mosquitto,paho等);对相关模块的代码有做加深了解;最后开始编写代码,做相关的开发工作。
由于是刚开始做linux的开发,感觉需要熟悉的东西太多了,所以想以博客的形式做一个记录。就以这篇mosquitto的交叉编译来开始吧:
mosquitto是一个开源的MQTT工具,相关的背景知识可以到如下官网了解;
https://mosquitto.org/
http://mqtt.org/
mosquitto在运行的时候需要用到几个比较重要的动态库libmosquitto.so, libssl.so, libcrypto.so,其中libmosquitto.so是由mosquitto的源
代码编译来的一些函数的动态库,另外两个则需要先进行交叉编译,生成ARM架构的动态库才可以在编译的时候应用。
1.交叉编译openssl
libssl.so和libcrypto.so其实是openssl的动态库,所以需要进行openssl的交叉编译。我用的是openssl-1.0.2e,版本之间应该差别不大
(没做过测试)。下载openssl源代码,用命令:wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2e.tar.gz
之后tar -zxvf openssl-1.0.2e.tar.gz将其解压
cd openssl-1.0.2e进入openssl目录
修改Makefile:
./config no-asm -shared --prefix=/usr/local/ssl-1.0.2/, 注意no-sam一定要有,--prefix为安装目录,如果不执行install可以不指定
另外,需要更改编译器,
vim Makefile
找到CC=gcc(也可能是CC=cc)
将其修改为CC=arm-linux-gnueabihf-gcc(你自己所用到的交叉编译器)
将SHLIB_VERSION_NUMBER=1.0.0改为1.0.2
将SHLIB_MINOR=0.0修改为0.2,保存退出
然后,执行make,需要等待大概3-5分钟左右的时间,make完毕。
此时可以发现,当前目录下出现了libssl.so.1.0.2和libcrypto.so.1.0.2
检查一下是否编译正确,在当前目录下执行file libssl.so.1.0.2, 显示如下
说明已经成功完成openssl的交叉编译,此时目录下的libssl.so.1.0.2和libcrypto.so.1.0.2即为后面编译所需要的动态库
2.交叉编译libmosquitto及mosquitto
这一部分是同时完成的。首先需要从官网下载mosquitto的源文件
wget https://mosquitto.org/files/source/mosquitto-1.4.8.tar.gz |
下载后解压,进入到mosquitto-1.4.8目录下。
下面就要对Makefile进行修改:
mosquitto的源代码分了几个部分,makefile也包含好几个,首先在主目录下有一个Makefile和一个config.mk,执行命令的时候,
会首先调用Makefile,Makefile里面第一行“include config.mk"就会将config.mk文件包含进来,相当于config.mk文件的内容也是
Makefile文件的内容,在主目录下的Makefile文件里面,会分别进入./lib, ./client, ./src这三个目录下分别执行make命令,而在对应
的这三个目录下,又分别有三个Makefile文件,分别对这三部分的相应内容进行编译。这里面需要修改的主要包括四个部分,第
一部分就是编译器的修改,第二部分是头文件的引用位置的修改,第三部分是动态库文件的调用位置的修改,还有一部分,指定
运行时动态库调用位置。
(1)首先修改编译器
打开config.mk文件,在文件末尾添加如下语句
CROSS_COMPILE=arm-linux-gnueabihf-
CC=gcc
CXX=g++
(2)接下来修改头文件的引用位置:
在config.mk文件中,有一行内容是”LIB_CFLAGS:=${CFLAGS} ${CPPFLAGS} -I. -I.. -I../lib“,指出了编译过程中需要的头文件可
以放置在如下几个目录:./ ./../ ./../lib,在这里,我们选择将openssl的头文件复制到主控Makefile所在的目录下(例如:
opensslconf.h的路径是/xx/xx/xx/openssl/opensslconf.h,其中/xx/xx/xx/是主控Makefile所在的路径。
PS:有一个问题需要注意,openssl的源文件中头文件那个文件夹中的所有文件都是软连接,如果采用拷贝的方法的话,需要将
所有的源文件拷贝过去,而不能拷贝软连接文件。
在src/目录下的Makefile中,作如下修改:
mosquitto_passwd.o : mosquitto_passwd.c
${CROSS_COMPILE}${CC} $(CFLAGS) ${CPPFLAGS} -c $< -o $@ -I../
最后添加的-I../指定了头文件的引用路径。
(3)修改动态库文件的调用位置
在config.mk中,将LIB_LDFLAGS:=${LDFLAGS} 修改为LIB_LDFLAGS:=${LDFLAGS} -L/usr/local/lib-arm,其中路径
/usr/local/lib-arm是笔者自己建立的,用于放置libssl.so, libcrypto.so, libmosquitto.so三个动态库的位置,加上这个路径,就能够
在编译时动态调用到这三个动态库文件;
在src/目录下的Makefile中,将
mosquitto : mosquitto.o bridge.o conf.o context.o 。。。。。。。
${CROSS_COMPILE}${CC} $^ -o $@ ${LDFLAGS} $(BRO KER_LIBS) 修改为:
${CROSS_COMPILE}${CC} $^ -o $@ ${LDFLAGS} -L/usr/local/lib-arm $(BRO KER_LIBS) -I../
其中 -L/usr/local/lib-arm指定编译时调用动态库的位置,而 -I../则指定头文件的位置
同样在该文件中,将如下位置做如下修改
mosquitto_passwd : mosquitto_passwd.o
${CROSS_COMPILE}${CC} $^ -o $@ ${LDFLAGS} -L/usr/local/lib-arm $(PAS SWD_LIBS)
原理同上
(4)
在config.mk文件中,将CLIENT_LDFLAGS:=后面的内容修改为如下
CLIENT_LDFLAGS:=$(LDFLAGS) -L../lib ../lib/libmosquitto.so.${SOVERSION} -Wl,-rpath,/usr/local/lib-arm
添加的内容为-Wl,-rpath,/usr/local/lib-arm,指定了程序在运行时调用动态库文件的路径,这样,我们在将执行文件拷贝到arm处
理器的时候,需要同时将动态库文件同时拷贝过去,并与执行文件放置在同一个目录下,或者放置在/usr/local/lib-arm目录下。
3.libuuid的交叉编译
基本与openssl的交叉编译类似,可参照执行。
至此,基本完成了mosquitto的交叉编译,可以将./src/mosquitto, ./client/mosquitto_sub, ./client/mosquitto_pub,
./lib/libmosquitto.so.1文件拷贝至arm环境下的linux系统的某一个目录进行执行,同时需要拷贝的还有mosquitto.conf(mosquitto的
配置文件,具体配置请参考mosquitto的官网),libssl.so, libcrypto.so,根据先前的设置,将其拷贝至/usr/local/lib-arm目录下即可。
cd到mosquitto所在的路径下,运行命令"./mosquitto -c /etc/mosquitto/mosquitto.conf -v",即可看到mosquitto正确运行:
交叉编译成功完成!