|
| 1 | +# Cross Compiling Azure IoT SDK for Python Example |
| 2 | +## Overview |
| 3 | + |
| 4 | +The goal of this document is to describe the steps required to cross compile the Azure IoT SDK for Python in order to allow the user to use Python to send and receive messages between the device and one's Azure IoT Hub. For this example, the target device will be the [MultiTech device](https://catalog.azureiotsuite.com/details?title=MultiConnect-Conduit&source=home-page). It will describe how to install the toolchain for the this device, build the required prerequisite software and finally cross compile the Azure IoT SDK for Python library. The procedure for other Linux based target devices should be very similar. |
| 5 | + |
| 6 | +This process will consist of three tasks: |
| 7 | + |
| 8 | +1. Download and install the MultiTech toolchain |
| 9 | +2. Download and build the Boost library against the MultiTech toolchain |
| 10 | +3. Download and build the Azure IoT SDK for Python against the MultiTech toolchain |
| 11 | + |
| 12 | +All commands will assume that you are starting with your current directory at your home directory. If you keep the directories names and relative locations the same as described this will save you from editing files later in the process. To switch to your home directory enter: |
| 13 | +``` |
| 14 | +cd ~ |
| 15 | +``` |
| 16 | +Please note that, due to width restrictions of this document, some of the entered commands may wrap on the page. They should be entered as a single line on the console. |
| 17 | + |
| 18 | +### Assumptions |
| 19 | + |
| 20 | +You are building the software on an Ubuntu distribution. For the purposes of testing this document I used Ubuntu 16.04 64-bit. |
| 21 | + |
| 22 | +You are a member of the sudo user group. You will only need to use sudo to install prerequisite software. All other steps can (and should) be performed as a standard user. |
| 23 | + |
| 24 | +### Prerequisites |
| 25 | + |
| 26 | +You will require a working Python before starting this process. Typically, most Linux distributions have Python installed out of the box. |
| 27 | + |
| 28 | +Other required software: |
| 29 | + |
| 30 | +- gcc – the C compiler |
| 31 | +- g++ – the C++ compiler |
| 32 | +- cmake – application used to generate build files |
| 33 | +- git – used to clone repositories from GitHub.com |
| 34 | + |
| 35 | +Install these packages with: |
| 36 | +``` |
| 37 | +sudo apt-get install cmake git build-essential curl libcurl4-openssl-dev libssl-dev uuid-dev |
| 38 | +``` |
| 39 | +### Editing Files |
| 40 | + |
| 41 | +You will need to create two files and modify one file during the course of this procedure. If you are using Ubuntu, then the simplest editor to use is nano. For example, if you wish to create a new file in your current directory simply type: |
| 42 | +``` |
| 43 | +nano mynewfile |
| 44 | +``` |
| 45 | +When you have completed your edits, press ctrl-o, press enter to save with the original file name and press ctrl-x to exit the editor. To edit an existing file simply replace _mynewfile_ with its name. |
| 46 | + |
| 47 | +## Step 1: Install the MultiTech toolchain |
| 48 | + |
| 49 | +The required toolchain can be found at MultiTech's website [here](http://www.multitech.net/developer/software/mlinux/mlinux-software-development/mlinux-c-toolchain/). We will need to download and install this toolchain to use it in later steps. The webpage contains detailed instructions on how to do that but, for convenience, I will document them here too. |
| 50 | +``` |
| 51 | +curl http://www.multitech.net/mlinux/sdk/3.3.6/mlinux-eglibc-x86\_64-mlinux-factory-image-arm926ejste-toolchain-3.3.6.sh > mlinux-toolchain-install.sh |
| 52 | +``` |
| 53 | +The SDK is around 420Mb so will take a while to download. |
| 54 | + |
| 55 | +Now modify the downloaded file to be a Linux executable and run it to install the toolchain. In this instance I am overriding the default install location with the -d option to a directory in my home directory. I've also added the -y flag to have it automatically reply yes to any questions. This will take a few minutes. |
| 56 | +``` |
| 57 | +chmod +x mlinux-toolchain-install.sh |
| 58 | +
|
| 59 | +./mlinux-toolchain-install.sh -d ~/mlinux/3.3.6 -y |
| 60 | +``` |
| 61 | +This concludes the installation of the MultiTech toolchain. |
| 62 | + |
| 63 | +## Step 2: Acquire and Build the Boost Library |
| 64 | + |
| 65 | +The Boost library is required for the Azure IoT SDK for Python. It provides several helper functions that ease the development of a binary Python library. The Python SDK utilizes these to provide a Python compatible binary that wraps the standard C SDK. The Boost library will need to be built from source code. |
| 66 | + |
| 67 | +Start by downloading the source archive from the Boost webpage and unpacking it: |
| 68 | +``` |
| 69 | +wget https://dl.bintray.com/boostorg/release/1.64.0/source/boost\_1\_64\_0.tar.gz |
| 70 | +
|
| 71 | +tar -xzf boost\_1\_64\_0.tar.gz |
| 72 | +``` |
| 73 | +This will also take a few minutes to complete. |
| 74 | + |
| 75 | +Now we need to run the Boost configuration script which tells the Boost build system what we want to build. |
| 76 | +``` |
| 77 | +cd boost\_1\_64\_0 |
| 78 | +
|
| 79 | +./bootstrap.sh --with-libraries=python –-prefix=${HOME}/boostmlinux-1-64-0 |
| 80 | +``` |
| 81 | +At this point we need to modify the file _project-config.jam_ to tell the Boost build system to use our MultiTech cross compile toolchain when we build it. To do this, with an editor of your choice, nano, vim, WinSCP, etc., (see Editing Files above) open this file and make the following modifications <mark>highlighted</mark> below. **Note:** Do not copy and paste the entire text below. The bootstrap command generates absolute paths in this file. These must not be replaced.<br/><br/> |
| 82 | +<div style="padding-left: 2em; background-color: #e6e6e6; font-family: Courier; font-color: red" > |
| 83 | +# Boost.Build Configuration<br/> |
| 84 | +# Automatically generated by bootstrap.sh<br/> |
| 85 | +<br/> |
| 86 | +import option ;<br/> |
| 87 | +import feature ;<br/> |
| 88 | +<mark>import os ;</mark><br/> |
| 89 | +<br/> |
| 90 | +<mark>local HOME = [ os.environ HOME ] ;</mark><br/> |
| 91 | +<br/> |
| 92 | +# Compiler configuration. This definition will be used unless<br/> |
| 93 | +# you already have defined some toolsets in your user-config.jam<br/> |
| 94 | +# file.<br/> |
| 95 | +<br/> |
| 96 | +if ! gcc in [ feature.values <toolset> ]<br/> |
| 97 | +{<br/> |
| 98 | + using gcc<br/> |
| 99 | + <mark>: arm<br/> |
| 100 | + : $(HOME)/mlinux/3.3.6/sysroots/x86\_64-mlinux-linux/usr/bin/arm-mlinux-linux-gnueabi/arm-mlinux-linux-gnueabi-g++<br/> |
| 101 | + : <compileflags>"-v --sysroot=$(HOME)/mlinux/3.3.6/sysroots/arm926ejste-mlinux-linux-gnueabi -L$(HOME)/mlinux/3.3.6/sysroots/arm926ejste-mlinux-linux-gnueabi/usr/lib"</mark><br/> |
| 102 | + ;<br/> |
| 103 | +} |
| 104 | +<br/> |
| 105 | +project : default-build \<toolset\>gcc ; |
| 106 | +<br/> |
| 107 | +# Python configuration |
| 108 | +<br/> |
| 109 | +import python ;<br/> |
| 110 | +if ! [ python.configured ]<br/> |
| 111 | +{<br/> |
| 112 | + using python<br/> |
| 113 | + <mark>: 2.7<br/> |
| 114 | + : $(HOME)/mlinux/3.3.6/sysroots/arm926ejste-mlinux-linux-gnueabi/usr/bin<br/> |
| 115 | + : $(HOME)/mlinux/3.3.6/sysroots/arm926ejste-mlinux-linux-gnueabi/usr/include/python2.7<br/> |
| 116 | + : $(HOME)/mlinux/3.3.6/sysroots/arm926ejste-mlinux-linux-gnueabi/usr/lib</mark><br/> |
| 117 | + ;<br/> |
| 118 | +} |
| 119 | +<br/> |
| 120 | +# List of --with-<library> and --without-<library><br/> |
| 121 | +# options. If left empty, all libraries will be built.<br/> |
| 122 | +# Options specified on the command line completely<br/> |
| 123 | +# override this variable.<br/> |
| 124 | +<br/> |
| 125 | +libraries = --with-python ; |
| 126 | +<br/> |
| 127 | +\# These settings are equivivalent to corresponding command-line<br/> |
| 128 | +\# options.<br/> |
| 129 | +<br/> |
| 130 | +option.set prefix : /home/markrad/boostmlinux-1-64-0 ;<br/> |
| 131 | +option.set exec-prefix : /home/markrad/boostmlinux-1-64-0 ;<br/> |
| 132 | +option.set libdir : /home/markrad/boostmlinux-1-64-0/lib ;<br/> |
| 133 | +option.set includedir : /home/markrad/boostmlinux-1-64-0/include ;<br/> |
| 134 | +<br/> |
| 135 | +\# Stop on first error |
| 136 | +<br/> |
| 137 | +option.set keep-going : false ;<br/> |
| 138 | +</div><br/> |
| 139 | +<div style="text-align: center; font-size: smaller">Figure 1: Modified project-config.jam</div> |
| 140 | + |
| 141 | +Build Boost for your MultiTech with the following command: |
| 142 | +``` |
| 143 | +./b2 toolset=gcc-arm --build-dir=${HOME}/boost-build-dir link=static install |
| 144 | +``` |
| 145 | +After this process is complete you will have a new directory in your home directory called boostmlinux-1-64-0 containing a lib and include directory. |
| 146 | + |
| 147 | +## Step 3: Build the Python SDK for a MultiTech Device |
| 148 | + |
| 149 | +Once again, starting from your home directory, clone the Azure IoT SDK for Python with the following command: |
| 150 | +``` |
| 151 | +git clone --recursive https://github.com/azure/azure-iot-sdk-python.git |
| 152 | +``` |
| 153 | +Now execute the following commands: |
| 154 | +``` |
| 155 | +cd azure-iot-sdk-python |
| 156 | +
|
| 157 | +mkdir cmake |
| 158 | +
|
| 159 | +cd build_all/linux |
| 160 | +``` |
| 161 | +You will need to create two files in this directory. With the editor of your choice first create _toolchain-mlinux.cmake_. Into this file enter the following: |
| 162 | +```cmake |
| 163 | +INCLUDE (CMakeForceCompiler) |
| 164 | +SET (CMAKE_SYSTEM_NAME Linux) # this one is important |
| 165 | +SET (CMAKE_SYSTEM_VERSION 1) # this one not so much |
| 166 | +
|
| 167 | +# Set up some paths for the build |
| 168 | +SET (CMAKE_SYSROOT $ENV{ML_SYSROOT}) |
| 169 | +SET (CMAKE_LIBRARY_PATH "$ENV{ML_SYSROOT}/usr/lib") |
| 170 | +SET (CMAKE_PREFIX_PATH "$ENV{ML_SYSROOT}/usr") |
| 171 | +SET (Boost_INCLUDE_DIR "$ENV{BOOST_ROOT}/include") |
| 172 | +SET (Boost_LIBRARY_DIR_RELEASE "$ENV{BOOST\_ROOT}/lib") |
| 173 | +
|
| 174 | +# Uncomment for a little debug info |
| 175 | +#message("Boost_INCLUDE_DIR ${Boost_INCLUDE_DIR}") |
| 176 | +#message("Boost_LIBRARY_DIR_RELEASE ${Boost_LIBRARY_DIR_RELEASE}") |
| 177 | +
|
| 178 | +# Set up the compilers and the flags |
| 179 | +SET (CMAKE_C_COMPILER $ENV{ML_HOSTTOOLS}/arm-mlinux-linux-gnueabi/arm-mlinux-linux-gnueabi-gcc) |
| 180 | +SET (CMAKE_CXX_COMPILER $ENV{ML_HOSTTOOLS}/arm-mlinux-linux-gnueabi/arm-mlinux-linux-gnueabi-g++) |
| 181 | +SET (CMAKE_C_FLAGS "-march=armv5te -marm -mthumb-interwork -mtune=arm926ej-s -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed") |
| 182 | +SET (CMAKE_CXX_FLAGS "-march=armv5te -marm -mthumb-interwork -mtune=arm926ej-s -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed") |
| 183 | +
|
| 184 | +# This is the file system root of the target |
| 185 | +SET (CMAKE_FIND_ROOT_PATH $ENV{ML_SYSROOT}) |
| 186 | +
|
| 187 | +# Search for programs in the build host directories |
| 188 | +SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) |
| 189 | +
|
| 190 | +# For libraries and headers in the target directories |
| 191 | +SET (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) |
| 192 | +
|
| 193 | +SET (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
| 194 | +``` |
| 195 | +<div style="text-align: center; font-size: smaller">Figure 2: CMake toolchain file</div> |
| 196 | + |
| 197 | +Create a second file called _mlinuxenv.sh_ and into it enter the following: |
| 198 | +```bash |
| 199 | +export ML_TOOLCHAINROOT=${HOME}/mlinux/3.3.6/sysroots |
| 200 | +export ML_HOSTTOOLS=${ML_TOOLCHAINROOT}/x86\_64-mlinux-linux/usr/bin |
| 201 | +export ML_SYSROOT=${ML_TOOLCHAINROOT}/arm926ejste-mlinux-linux-gnueabi |
| 202 | +export BOOST_ROOT=${HOME}/boostmlinux-1-64-0 |
| 203 | +export PATH=${ML_HOSTTOOLS}/bin:${ML_HOSTTOOLS}/bin/arm-mlinux-linux-gnueabi:$PATH |
| 204 | + |
| 205 | +cmake -DCMAKE_INSTALL_PREFIX=~/mlinux-out -DCMAKE_TOOLCHAIN_FILE=../build_all/linux/toolchain-mlinux.cmake .. |
| 206 | +``` |
| 207 | +<div style="text-align: center; font-size: smaller">Figure 3: Build Generator Script</div> |
| 208 | + |
| 209 | +Having created the two files, we are now ready to build the SDK. Enter the following commands: |
| 210 | +``` |
| 211 | +chmod a+x mlinuxenv.sh |
| 212 | +cd ../../cmake |
| 213 | +../build_all/linux/mlinuxenv.sh |
| 214 | +make install |
| 215 | +``` |
| 216 | +This will build the SDK and create the Python library. To check that the binary Python library has been built correctly enter: |
| 217 | +``` |
| 218 | +file ~/mlinux-out/lib/*.so |
| 219 | +``` |
| 220 | +This should result in two lines of output, one for _iothub\_client.so_ and one for _iothub\_service\_client.so_. The details should say that they are _ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked_ which is the appropriate architecture for your target machine. |
| 221 | + |
| 222 | +## Conclusion |
| 223 | + |
| 224 | +This document has described the procedure to cross compile the Azure IoT SDK binary Python library targeting a MultiTech device. |
| 225 | + |
| 226 | +Additionally, I have tested this procedure in a Windows Subsystem for Linux bash prompt successfully. This allows one to complete these steps without requiring an actual installation of Ubuntu. There is just one additional step you will need to take to use the Windows Subsystem for Linux. After you have installed the prerequisite software, run the command: |
| 227 | +``` |
| 228 | +sudo ln -s /usr/bin/python2.7 /usr/bin/python |
| 229 | +``` |
| 230 | +This will set up a soft symbolic link called python which is the command name the tools will expect to find. |
0 commit comments