Skip to content

Build and Development Environment

ruferp edited this page Aug 5, 2016 · 25 revisions

Building and Developing an Agent

Introduction

EOS SDK lets you develop agents on any 32-bit Linux environments, making it easy to compile and test new programs. This is because the SDK is simply a collection of C++ header files. On a real switch or vEOS instance, these headers are exposed in the library libeos.so, provided by the EosSdk.i686.rpm extension, and contain the implementation for communicating with Sysdb and the rest of EOS. However, in your development environment, these headers are backed by stubbed-out functionality provided by the EosSdk-stubs.tar.gz bundle, and is free from any EOS-specific dependencies. Your agent builds against this stub library and produces a binary executable that, when copied to the switch, dynamically links against the full libeos.so implementation.

This GitHub repository contains the entirety of the headers, stub implementation and examples. To develop against a specific version of the SDK, you can view and download a tarball from the releases page. We welcome improvements to stubs functionality, along enhancements to header comments and examples via pull requests. You can submit bug reports and suggestions through GitHub's issue tracker.

Set up

In order to compile C++ programs, you will need a 32-bit Linux system that has the following software installed:

Component Minimum Version
g++ 4.5.1
glibc 2.13 (libc version 6)
automake 1.14 (minimum version supported)
autoconf 2.66
m4 1.4.14

These build tools are included with many distributions, including Ubuntu 12.04, Fedora Core 14, and Fedora Core 18. On Ubuntu systems, the build tools are included with g++-multilib, while Fedora systems use libraries from the libgcc.i686, glibc-devel.i686, and libstdc++.i686 RPMs.

We recommend that users create a new (virtual) machine with one of these operating systems installed. Advanced users can cross-compile from a 64-bit environment to a 32-bit one. We provide a Debian package with a cross-compiler that will give you a compile environment that exactly matches the one we use to build EOS itself, see the "cross-compiler" chapter further down.

Creating the stubs library

Once you have a system that meets the above requirements, download the stubs tarball with the same version as the release of the EosSdk.i686.rpm you plan on using. Then un-tar the package:

bash# tar xzf <SDK-stubs-version>.tar.gz

and run the build.sh script, which will configure the build system and make the stubbed version of libeos.so.

bash# cd <Newly-created-untarred-SDK-stubs-folder>
bash# ./build.sh
bash# sudo make install

The recommended set of flags when building your code can be found in build.sh's CFLAGS variable, and can be edited to include the compilation flags you prefer. Build output is saved in config.log, and will show relevant information in case of a compilation error.

Building the Python bindings

If you'd like to use Python, you can simply transfer your program to the switch, as the language does not require a compilation step. However, you may find it useful to generate the Python bindings locally so you can inspect the naming changes, run unit tests, or use pylint in your development environment. To do so, first install SWIG and then invoke build.sh with the --enable-python flag:

bash# ./build.sh --enable-python
bash# sudo make install
bash# python -c "import eossdk; print eossdk.version"
1.3.1

Building your agent

After creating the libeos.so library, you can build your agent:

bash# g++ -std=gnu++0x -o MyAgent MyAgent.cpp -leos

The -std=gnu++0x indicates that this should be built using the C++11 standard, and -leos lets the compiler know that we are linking against the libeos.so library we built in the previous steps. You may pass additional compilation flags to g++ in order to create binaries with higher levels of optimization, debuggability, compiler warnings, etc. To see the recommended list of parameters the stubs library is built with, you can view the CFLAGS variable that build.sh uses for compilation:

CFLAGS='-Os -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wno-unused -Wno-uninitialized -fasynchronous-unwind-tables'
CFLAGS_32B='-m32 -march=i686 -mtune=atom'

At this point, you have a working C++ binary and a real EOS agent! This binary can be unit tested and even run locally. Currently the stubs only have minimal functionality, though, so agents run locally will not do much. When used in conjunction with a library that lets you externally trigger events, like GoogleMock, you can write tests that invoke any handlers you've overridden. Once you copy this executable to a switch with the extension installed, you can run the agent and it will link against the functional SDK implementation.

Linking against other libraries

You may wish to use third party libraries when writing your agent so you use can externally developed code and open source projects. You can accomplish this in two ways. The first is to statically link against the library. This is fairly straightforward: when compiling your program, set the appropriate flags to link against the library statically, which will cause the third party libraries logic to be included in the resulting binary. The second approach is dynamic linking. This requires that the external library is also available on the switch, and thus should be packaged as an extension and installed before attempting to run the agent. The only caveat is that linked libraries, just like your own agent, must be built for a 32 bit environment.

Word of Caution

If you want to statically link with a different version of a standard library that libeos.so also links against, then depending on the case, this might cause binary incompatibility issues, as can be the case with libstdc++ that defines the std::map etc. data structures, since some EosSdk APIs use those data structures, which are thus passed between your code and our code, and therefore should have been compiled against the same header files to ensure binary compatibility. Since libstdc++ is normally tied to the gcc version, and libstdc++ is not as backwards compatible / versioned as libc is, this essentially means that if you use such EosSdk APIs, you better use the same gcc version as EOS did to build itself.

Cross-Compiler

To facilitate the building requirements, we have a cross-compiler for Ubuntu, distributed as a Debian package, that you can install on your system in case you do not have the same version of gcc and libraries than those used in the EOS ecosystem. Because libstdc++ is tied to the gcc version, and we upgraded our gcc during EOS release 4.17.0F, we have 2 cross-compiler packages.

Cross-Compiler Package Use With EOS Target installs to
arista-fc14.deb < 4.17 /opt/arista/fc14/
arista-fc14-gcc-4-9.deb >= 4.17 /opt/arista/fc14-gcc4.9/

The cross-compiler itself is a 32bit executable, which your 64bit system can run as long as the corresponding libraries have been installed:

sudo apt-get install -y libc6-i386

That cross-compiler comes with all the standard libraries as they are installed on the EOS switch (and links against those, not the ones natively installed on Ubuntu). However, that cross-compiler environment does not have the exact same SSL library as the switches, nor the corresponding SSL related development header files (we do keep SSL current in terms of security vulnerabilities, so it changes quite often). We might include SSL in future cross-compiler releases though.

The debian package is installed like this:

sudo dpkg -i arista-fc14.deb

and can be un-installed with the corresponding -r option.

Here is a full end-to-end example:

# install the cross-compiler
ncftpget ftp://ftp.arista.com/data/ar/crossgcc/arista-fc14.deb
sudo dpkg -i arista-fc14.deb

# get EosSdk headers and build the stubbed libeos.so
mkdir build; cd build/
scp you@machine:/somewhere/EosSdk-stubs-1.5.4.tar.gz .
tar -xzvf EosSdk-stubs-1.5.4.tar.gz
cd EosSdk-stubs-1.5.4/
PATH=/opt/arista/fc14/bin:$PATH ./build.sh

# add one of the example shipped with the stubs to the makefile and build again
vim Makefile.am # add the lines below
    noinst_PROGRAMS = HelloWorld
    HelloWorld_SOURCES = examples/HelloWorld.cpp
    HelloWorld_LDADD = libeos.la
sudo apt-get install autoconf
autoreconf --force
PATH=/opt/arista/fc14/bin:$PATH ./build.sh

# copy to switch and run it
scp .libs/HelloWorld root@myEosRouter:/tmp
ssh myEosRouter
myEosRouter# configure
myEosRouter(config)# daemon HelloWorld
myEosRouter(config-daemon)# exe /tmp/HelloWorld
myEosRouter(config-daemon)# no shut
myEosRouter(config-daemon)# bash cat /var/log/agents/HelloWorld-$(pidof HelloWorld)
myEosRouter(config-daemon)# show daemon
...

# install the development headers to /opt/arista/fc14/usr/include/eos/ 
# and the stubbed EosSdk library to /opt/arista/fc14/usr/lib/libeos.so
# (where the crosss-compiler will naturally look for them).
sudo make install

Note that if you constantly switch between different EosSdk versions and share a build server, then you might want to install the headers/library elsewhere and provide a -I directive to the compiler and a -L to the linker, depending on the target version. Alternatively, you could run build.sh as part of your build system which picks the correct EosSdk-stubs-xxx.tar.gz (that is, never install them, like we did with the HelloWorld example above).

Download the Cross Compiler

Currently only available via ftp (old files get sweeped, so might disappear):

ftp://ftp.arista.com/data/ar/crossgcc/arista-fc14.deb
ftp://ftp.arista.com/data/ar/crossgcc/arista-fc14-gcc4-9.deb