Skip to content

Commit 7263638

Browse files
committed
Add cross compile example
1 parent 2d24b62 commit 7263638

File tree

1 file changed

+230
-0
lines changed

1 file changed

+230
-0
lines changed
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
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 &lt;toolset&gt; ]<br/>
97+
{<br/>
98+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;using gcc<br/>
99+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<mark>: arm<br/>
100+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: $(HOME)/mlinux/3.3.6/sysroots/x86\_64-mlinux-linux/usr/bin/arm-mlinux-linux-gnueabi/arm-mlinux-linux-gnueabi-g++<br/>
101+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: &lt;compileflags&gt;&quot;-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&quot;</mark><br/>
102+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;<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+
&nbsp;&nbsp;&nbsp;&nbsp;using python<br/>
113+
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<mark>: 2.7<br/>
114+
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;: $(HOME)/mlinux/3.3.6/sysroots/arm926ejste-mlinux-linux-gnueabi/usr/bin<br/>
115+
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;: $(HOME)/mlinux/3.3.6/sysroots/arm926ejste-mlinux-linux-gnueabi/usr/include/python2.7<br/>
116+
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;: $(HOME)/mlinux/3.3.6/sysroots/arm926ejste-mlinux-linux-gnueabi/usr/lib</mark><br/>
117+
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;;<br/>
118+
}
119+
<br/>
120+
# List of --with-&lt;library&gt; and --without-&lt;library&gt;<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

Comments
 (0)