Component Building Guide

Introduction

This section will take you through creating a Sming Component from start to finish, based on a real example from Pull Request #1992.

The aim here is to make an existing library, https://github.com/nomis/ModbusMaster, available for applications to use within the framework.

Various options and settings are only mentioned here, but are linked through to Sming build system where you can find full details of what they are and how they work.

You will need to be familiar with GIT and the use of submodules.

Structure

You should carefully consider how to incorporate third-party code. The choices are:

  1. Add an existing third-party library directly as a Component, patching if required;

  2. Add the a submodule as a sub-directory within a Component;

  3. Copy code from an existing library (honouring any license agreement conditions) and modify/rewrite as necessary;

  4. Start from scratch. If drawing on ideas from other implementations those should be attributed.

We could use (a), but that is appropriate only for very simple libraries, or those written for Sming but stored in an external repository (e.g. FlashString). You can find more details on this process in Adding External Sources.

Note

Bear in mind that the asynchronous architecture of Sming can be at odds with code written for Arduino. In this example, the main ModbusMasterTransaction code incorporates a loop which effectively halts program execution until a timeout occurs or a response is received. Fixing that could require extensive patching, so option (c) or (d) may be more appropriate.

For now we are using option (b), so we’ll start by creating the Component directory:

cd $SMING_HOME/Libraries
mkdir ModbusMaster
cd ModbusMaster

Note

Do not use $SMING_HOME/Components. This is reserved for framework libraries.

Now add the submodule:

git submodule add --name Libraries.ModbusMaster https://github.com/nomis/ModbusMaster

This does three things:

  1. Clones the external repository to the ModbusMaster sub-directory;

  2. Adds an entry to the .gitmodules file with the URL, local path and specified name;

  3. Stages both changes, with a link indicating which commit should be used.

Note

The dotted name format is a Sming convention.

Before committing, we need to edit the .gitmodules file. Open in a text editor and follow the instructions therein.

You should now re-stage and commit the changes before proceeding.

Patching

Where minor changes are required to third-party code then these can be applied automatically as patches. See Adding External Sources and GIT Submodules for details.

For ModbusMaster, we want to make a slight change to how the timeout is configured, so this is provided in a file called ModbusMaster.patch.

Supported architectures

Unless there are specific reasons not to do so, Components should work on all supported architectures. In particular, it should build and run under the Host Emulator.

In order to do this, you should remove any low-level code from the library by:

  • Using Sming support classes or drivers (see Esp8266 Drivers); or

  • Placing low-level code into separate code modules or header files.

If a Component is intended only to work with specific hardware then ensure appropriate checks are incorporated so that building fails gracefully on un-supported architectures. You can do this in the component.mk file:

ifneq ($(SMING_ARCH),Esp8266)
$(error MyComponent currently only supports the ESP8266 architecture)
endif

Component configuration

For very simple Components the default settings are adequate:

  • Source code must be in the base directory or a sub-directory called src

  • Public header files must be in a sub-directory called include

The source files will be compiled into a library, in this case clib-ModbusMaster.a.

To change the defaults, provide a component.mk file and set entries as required:

Submodules

We need to tell Sming about the submodules:

COMPONENT_SUBMODULES := ModbusMaster
Source code

Put the source code into a separate directory (or directories) and add those to COMPONENT_SRCDIRS.

You can also use COMPONENT_SRCFILES.

For ModbusMaster, all the source code is in the submodule so we set this to COMPONENT_SRCDIRS := ModbusMaster/src.

Header files

Keep public and private .h or .hpp files in separate directories.

Add the public ones to COMPONENT_INCDIRS.

Any private headers can be set in EXTRA_INCDIR.

For ModbusMaster, we set this to COMPONENT_INCDIRS := ModbusMaster/src

Configuration options

ModbusMaster provides the MB_RESPONSE_TIMEOUT variable.

This is mapped onto a #define value with the same name using COMPONENT_CXXFLAGS.

Note: Don’t confuse this with COMPONENT_CFLAGS which is only used when building .c source files.

If the value changes we want Sming to rebuild both the library and any code which uses it, so we assign it to the COMPONENT_VARS variable list. Users can check the value by running make list-config.

Dependencies

If your library depends on other libraries to build, these must be declared in the component.mk file by setting COMPONENT_DEPENDS variable.

ModbusMaster doesn’t have any so this entry is not required.

Documentation

A Component MUST have a README.md (markdown) or README.rst (reStructuredText) file with a level 1 heading and brief introduction at an absolute minimum.

Note

You may not be familiar with .rst files but they are a considerably improvement on markdown and well worth investing a little time to learn.

See Contributing for further details.