提示:如果您通过将SDK中的文件抽取出来的方式编译SDK,则可以跳过本章。

本文以将SDK移植到arm-linux 平台为例,演示一个完整的交叉编译移植过程。

对于嵌入式硬件平台的情况, 对编译出目标平台的libiot_sdk.a,需要经历如下几个步骤:

  • tools/board/目录下添加一个对应的配置文件,文件名规范为config.XXX.YYY,其中XXX部分就对应后面wrappers/os/XXX目录的HAL层代码。
  • 在配置文件中,至少要指定:
    • 交叉编译器OVERRIDE_CC的路径。
    • 交叉链接器OVERRIDE_LD的路径。
    • 静态库压缩器OVERRIDE_AR的路径。
    • 编译选项CONFIG_ENV_CFLAGS, 用于C文件的编译。
    • 链接选项CONFIG_ENV_LDFLAGS, 用于可执行程序的链接。
  • 尝试编译SDK,对可能出现的跨平台问题进行修正,直到成功产生目标格式的libiot_sdk.a
  • 最后, 您需要以任何您喜欢的编译方式,产生目标架构的libiot_hal.a
  • 若目标平台尚未被适配,则libiot_hal.a对应的源代码在C-SDK中并未包含,需要您自行实现HAL_*()接口。

下面以某款目前未官方适配的arm-linux目标平台为例,演示如何编译出该平台上可用的libiot_sdk.a

安装交叉编译工具链

仍以Ubuntu16.04开发环境为例。

$ sudo apt-get install -y gcc-arm-linux-gnueabihf

$ arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (Ubuntu/Linaro 4.8.4-2ubuntu1~14.04.1) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
            

添加配置文件

$ touch tools/board/config.arm-linux.demo

$ ls tools/board/
config.alios.mk3080  config.arm-linux.demo  config.ubuntu.x86
            

编辑配置文件

在这一步,需要设置编译选项和工具链,以及跳过编译的目录。


$ vim tools/board/config.arm-linux.demo

CONFIG_ENV_CFLAGS = \
    -D_PLATFORM_IS_LINUX_ \
    -Wall \
    -DNO_EXECUTABLES

CONFIG_ENV_LDFLAGS = \
    -lpthread -lrt

OVERRIDE_CC = arm-linux-gnueabihf-gcc
OVERRIDE_AR = arm-linux-gnueabihf-ar
OVERRIDE_LD = arm-linux-gnueabihf-ld

CONFIG_wrappers :=

            
重要 上面的最后1行表示跳过对wrappers目录的编译,以及-DNO_EXECUTABLES不要产生可执行程序。在编译未被适配平台的库时在最初是必要的,这样可以避免产生过多的错误。

注:上述配置文件的内容从某些浏览器复制出来之后将会丢失空行。

选择配置文件

$ make reconfig

SELECT A CONFIGURATION:

1) config.alios.mk3080
2) config.arm-linux.demo
3) config.ubuntu.x86

#? 2

SELECTED CONFIGURATION:

VENDOR :   arm-linux

MODEL  :   demo
            

交叉编译产生库文件libiot_sdk.a

注:本步骤不编译HAL,只是为了验证配置文件中的交叉编译参数是否正确,如果出现错误请对配置文件再次进行修改,直到编译成功。

$ make

BUILDING WITH EXISTING CONFIGURATION:


VENDOR :   arm-linux

MODEL  :   demo


[CC] infra_timer.o                      <=  ...
[CC] infra_json_parser.o                <=  ...
[CC] infra_preauth.o                    <=  ...
            

获取交叉编译的产物, 包括静态库和头文件

$ ls -1 output/release/lib/
libiot_sdk.a
libiot_tls.a
            

这里,libiot_sdk.a文件就是编译好的物联网平台SDK,已经是ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV)格式,也就是arm-linux格式的交叉编译格式了。

另外,libiot_tls.a是一个裁剪过的加解密库,您可以选择使用它,也可以选择使用平台自带的加解密库,以减小最终固件的尺寸。

$ ls -1 output/release/include/

dev_model_api.h
dev_sign_api.h
infra
mqtt_api.h
            

这里,dev_sign_api.h就是使用SDK中"设备签名"功能需要包含的头文件,类似mqtt_api.h是使用SDK中"MQTT上云"功能需要的,infra下的头文件也请加入编译搜索路径。

开发未适配平台的HAL层

对于实现平台抽象层接口HAL_XXX_YYY()的库libiot_hal.a,不限制其编译和产生的方式。

但是如果您愿意的话,当然仍然可以借助物联网平台设备端C-SDK的编译系统来开发和产生它。

复制一份HAL层实现代码

注:在wrappers/os下需要创建一个与tools/board/config.XXX.YYY中的XXX一样的目录用于存放HAL实现。

由于目标平台为arm-linux,因此可以复制Ubuntu下面的HAL实现,下面是操作示例:

$ cd wrappers/os/

$ ls
freertos  nos  nucleus  ubuntu

wrappers/os$ cp -rf ubuntu arm-linux

wrappers/os$ rm -f arm-linux/HAL_UART_linux.c

wrappers/os$ ls
arm-linux freertos  nos  nucleus  ubuntu

wrappers/os$ tree -A arm-linux/
arm-linux/
+-- HAL_AWSS_linux.c
+-- HAL_Crypt_Linux.c
+-- HAL_FS_Linux.c
+-- HAL_KV_linux.c
+-- HAL_OS_linux.c
+-- HAL_TCP_linux.c
+-- HAL_UDP_linux.c
            

打开之前被关闭的编译开关

$ vim tools/board/config.arm-linux.demo

CONFIG_ENV_CFLAGS = \
    -D_PLATFORM_IS_LINUX_ \
    -Wall\
    -DNO_EXECUTABLES

CONFIG_ENV_LDFLAGS = \
    -lpthread -lrt

OVERRIDE_CC = arm-linux-gnueabihf-gcc
OVERRIDE_AR = arm-linux-gnueabihf-ar
OVERRIDE_LD = arm-linux-gnueabihf-ld

# CONFIG_wrappers :=
          

可以看到在CONFIG_wrappers :=这一行前添加了一个#符号,代表这一行被注释掉了,wrappers将会进入编译过程。

尝试交叉编译被复制的HAL层代码

$ make reconfig

SELECT A CONFIGURATION:

1) config.alios.mk3080
2) config.arm-linux.demo
3) config.ubuntu.x86

#? 2

SELECTED CONFIGURATION:

VENDOR :   arm-linux
MODEL  :   demo

...


$ make
            

可以看到我们进展的十分顺利,被复制的代码wrappers/os/arm-linux/*.c直接编译成功了,产生了arm-linux格式的libiot_hal.a

交叉编译样例程序

这样有了libiot_hal.alibiot_tls.a,以及libiot_sdk.a,已经可以尝试交叉编译样例的可执行程序,并在目标嵌入式硬件开发板上运行一下试试了。

方法是去掉config.arm-linux.demo里面的-DNO_EXECUTABLES开关,使得*/examples/目录下的样例源码被编译出来。

注:删掉-DNO_EXECUTABLES开关时记得把上面一行-Wall后面的''符号也删掉。

修改后的config.arm-linux.demo内容如下所示:


$ vi tools/board/config.arm-linux.demo

CONFIG_ENV_CFLAGS = \
    -D_PLATFORM_IS_LINUX_ \
    -Wall

CONFIG_ENV_LDFLAGS = \
    -lpthread -lrt

OVERRIDE_CC = arm-linux-gnueabihf-gcc
OVERRIDE_AR = arm-linux-gnueabihf-ar
OVERRIDE_LD = arm-linux-gnueabihf-ld

# CONFIG_wrappers :=
            

可以看到在-DNO_EXECUTABLES开关从CONFIG_ENV_CFLAGS中去掉了,例子可执行程序进入了编译范围。

重新载入配置文件,交叉编译可执行程序

$ make reconfig

$ make            

如果有如下的编译输出,则代表mqtt-example等一系列样例程序已经被成功的编译出来,它们存放在output/release/bin目录下。

[LD] dev-sign-example                   <=  ...
[LD] mqtt-example                       <=  ...
[LD] linkkit-example-solo               <=  ...

$ cd output/release/bin/

$ ls
dev-sign-example  linkkit-example-solo  mqtt-example

$ file *

dev-sign-example:     ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked ...

linkkit-example-solo: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked ...

mqtt-example:         ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked ...
            

可以用file命令验证,这些可执行程序确实是交叉编译到arm-linux架构上的。

尝试运行样例程序

接下来,您就可以把样例程序例如mqtt-example,用SCPTFTP或者其它方式,拷贝下载到您的目标开发板上运行调试了。

  • 如果一切顺利,样例程序和同样例程在Ubuntu上运行效果相同,则证明wrappers/os/arm-linux部分的HAL层代码工作正常。
  • 如果样例程序运行起来,和同样例程在 Ubuntu上运行效果不同,则需要再重点修改调试HAL实现。
  • 也就是指wrappers/os/arm-linux目录的HAL层代码,因为这些代码是我们从Ubuntu主机部分复制的,完全可能并不适合arm-linux

如此反复直到确保libiot_hal.a的开发没问题为止。