OpenOCF a minimal implementation of the OCF protocol, derived from Iotivity.
Differences:
-
Minimal, 100% C11 - only the C code from Iotivity, none of the C++ stuff
-
The build system is Bazel instead of Scons.
-
The code has been converted (reorganized) to a c-without-include-headers style, using makeheaders from D.Richard Hipp of Sqlite fame.
-
Refactoring and renaming.
-
API is the same, but source layout and some filenames have been changed.
-
Easy cross-compilation (current targets: Raspberry Pi 3B, WindRiver Linux on Intel IoT Gateway, ARM, Android NDK)
-
-
Arduino code is removed.
-
Java/Android support has been migrated to a separate repo, iochibity-java
-
No Android-specific code in OpenOCF (Work In Progress). Android support in Iotivity involves having the stack call into Android to create objects etc. This has been removed.
-
The source is in src/ and third_party/.
|
Warning
|
The source tree has been reorganized substantially: |
-
csdk → //src
-
security → //src/sec
-
security/provisioning → //src/provisioning
-
src and include subdirs have been removed - source and header files go in same director (bazel treats header files as source; this makes good sense imho)
-
most header files are generated at build time, using makeheaders. The exceptions are .h files whose names have a leading underscore, e.g.
src/ocf/_device.h; such files are processed by makeheaders, but are not #included anywhere.
|
Note
|
Using makeheaders to support a header-free style of programming may be
unorthodox, but so far it has been a very positive experience. Each
source file includes exactly one header, generated by makeheaders, of
the same name. For example, See the original documentation for a description of the rationale and working of makeheaders. There are a few tricky bits to be aware of. For example, if a function signature uses a datatype declared elsewhere (e.g. uint32_t, from stdint.h), then that header must be #included before the (generated) prototype in the generated headers that need it. To enable this, enclose the #include within "#if INTERFACE … #endif". It is also possible to trip up makeheaders by going overboard with macros. |
|
Important
|
Status: OpenOCF is based on Iotivity 1.3.0 and will be upgraded to new versions as they are released. On the Mac, network monitoring is not yet implemented. It runs, but will not detect network changes. |
First configure, then build.
OpenOCF uses GNU autotools (autoconf, etc.) for configuration. You
will also need to configure the third-party libs. (Just coap so far). The
instructions are at the top of third_party/coap/BUILD.
OpenOCF uses the Bazel build system.
OpenOCF is written in the c-without-include-headers style made possible by makeheaders. This requires a preprocessing step as part of the build.
Prerequisites: Bazel, GNU autotools. On Windows: msys2, mingw-64.
|
Warning
|
See notes below if you are building on Windows. |
OpenOCF uses GNU autotools for configuration, as do some of the third-party libs like libcoap.
libcoap: automated. see src/coap/libcoap/BUILD.
OpenOCF: see the shell files in ./bin. To configure for the local machine: .bin/local_config.sh.
For cross-compiling,
Prep: first we construct the list of files to be processed by makeheaders; this list varies by platform, so we use a Bazel target:
$ bazel build :mkhdrs|
Note
|
for cross-compiling (e.g. targeting android) you must supply the appropriate --config value, e.g.: |
$ bazel build :mkhdrs --config=rpi-arm8This creates ./bazel-bin/mkhdrs.dat. We process this to create our
headers. First build the makeheaders program:
$ bazel build tools/makeheadersThe result will be ./bazel-bin/tools/makeheaders/makeheaders. Since makeheaders is extremely unlikely to change, you can copy it to a directory on your path, e.g.
$ cp ./bazel-bin/tools/makeheaders/makeheaders $HOME/binNow use it to produces the internal library headers, then the public API exposed to application developers:
$ makeheaders -f bazel-bin/mkhdrs.dat
$ makeheaders -f bazel-bin/mkhdrs.dat -H > include/openocf_h.hSee e.g. ./bin/rpi3b_arm8_mkhdrs.sh
Targets are defined by BUILD files; cross-compilation by flags. Before building, see tools/bazel.rc and make sure you’ve got the right ones. You can build any target. Examples:
-
$ bazel build src/provisioning -
$ bazel build src/comm -
etc
The main target for building OpenOCF for use by an application is
//:openocf. You can build it like so: $ bazel build :openocf.
|
Warning
|
third-party libraries are built using Bazel’s support for
external repos using the new_http_archive facility, as specified in
the WORKSPACE file. You cannot build them using the above syntax; you
have to use @ syntax. For example, instead of bazel build
src/sec/mbedtls, do bazel build @mbedtls//:mbedtls.
|
Now build test apps:
$ bazel build examples/discovery:server
$ bazel build examples/discovery:clientOutput executables will be in `./bazel-bin/examples/discovery
This example has been built and tested on Ubuntu (16.04.3 LTS), macOS Sierra (10.12.6), Windows 7, Raspberry Pi 3b, and Wind River Linux.
|
Important
|
As you develop code, you will need to rerun makeheaders
whenever you make a change affecting the visibility of your code
(fortunately makeheaders is lightning-fast). For example, if you
change a function prototype or add code that refers to something in
another file. If you add or remove source files, you will also need to
rerun $ bazel build :mkhdrs before rerunning makeheaders. In the
future I hope to automate all this so a single bazel command will do
the all the right things.
|
Prerequisites: mingw shell and GNU tools (autoheader, autoconf, etc.). Recommend using msys2. Use pacman to install needed packages.
|
Important
|
Currently only the MSVC compiler is supported. That’s the default for Bazel builds. Support for the Mingw GCC compiler is almost complete but there are still a few unresolved bugs. Patches welcome. |
Libcoap (in third_party/coap) does not work with mingw64 out of the
box; it requires some patches that have not been submitted yet. Search
third_party/coap/src/coap_io.c for "GAR" to see what’s needed.
Windows needs some special therapy. Since we’re using mingw-based
tools for feature test configuration but compiling with MSVC tools, we
get some false positives: headers that exist in the mingw environment
but not the MSVC environment. Specifically, the generated
src/_openocf_config.h file will #define the following:
HAVE_LIBPTHREAD HAVE_PTHREAD_H HAVE_STRINGS_H HAVE_SYS_SOCKET_H HAVE_SYS_TIME_H TIME_WITH_SYS_TIME HAVE_UNISTD_H HAVE_SYS_UNISTD_H
These must be #undefined if compiling with the MSVC toolchain. As a
convenience we provide src/_openocf_config_win.h which you can copy
to src/_openocf_config.h instead of running ./configure.
Cross-platform builds require source-code configuration and a toolchain for cross-compiling. See CROSSCOMPILE for details.
Support for Android builds is provided natively by Bazel; see the
Tutorial.
By default, Bazel will target the armeabi-v7a architectures; to target
one of the other architectures supported by Android you must pass the
appropriate --fat_apk_cpu and --android_cpu options; these options
are used in the BUILD files to configure the build. As a convenience,
several Android configurations are defined in tools/bazel.rc.
|
Warning
|
Bazel will only use the Android NDK toolchain for android_binary targets. |
Assuming myapp is an android_binary target, you would build it for arm64-v8a as follows:
$ ./bin/android_config.sh v8a
$ bazel build myapp --config=android-arm8This configuration is defined in tools/bazel.rc. The config shell
script will run ./configure and build the :mkhdrs target with
appropriate parameters to configure the source code.
Cross-platform builds using crosstool-NG toolchains to target the Raspberry Pi 3B and generic Linux are also supported.
|
Note
|
crosstool-NG on MacOS requires special treatment; see CROSSCOMPILE for details. |
crosstool-NG toolchain: armv8-rpi3-linux-gnueabihf
Configure the source:
$ ./bin/rpi3b_config.shThis will run ./configure with appropriate parameters, and then run
bazel build :mkhdrs to generate the headers.
To build:
$ bazel build tools/browser/server --config=rpi3b-arm8Configurations are defined in tools/bazel.rc; they drive the
config_settings used to configure the build. The config_settings are
defined in config/BUILD. The --config option is documented at
A User’s
Guide to Bazel.