mlpack

🔗 Crosscompile mlpack example for an embedded hardware

In this article, we explore how to add mlpack to a CMake project that cross-compiles code to embedded hardware. See also these related other guides, which may be useful to read before this one:

🔗 Cloning mlpack example respository

mlpack has an example repository that shows a number of applications and use cases for mlpack, including embedded deployment. In this tutorial, we are interested in the embedded/ directory, which provides a CMake project template that compiles a random forest application to embedded hardware. This project template can be adapted to a new project, or its pieces can be incorporated into an existing CMake project.

The first step is to clone the examples repository:

git clone git@github.com:mlpack/examples.git

Next, let’s look at the CMakeLists.txt (e.g. the CMake configuration) in the embedded/crosscompile_random_forest/ directory.

🔗 CMakeLists.txt

The first part of the code, printed below or available here, defines the project name and includes two useful CMake configuration files: * mlpack.cmake: finds mlpack’s dependencies and download them if necessary. * ConfigureCrossCompile.cmake: set up CMake configuration for cross-compilation. * crosscompile-toolchain.cmake: invoke CMake crosscompilation infrastructure. * crosscompile-arch-config.cmake: add necessary flags depending on the architecture (optional).

Then we need to call fetch_mlpack(ON) to download mlpack including all dependencies, cross-compile OpenBLAS and set up all the necessary parameters to find these dependencies. Most of mlpack’s dependencies are header-only with the exception of OpenBLAS; thus this is expected to be a quick step.

fetch_mlpack() will detect if cross compilation is necessary or not depending on the command that is executed when running cmake. Based on this, it will compile OpenBLAS.

cmake_minimum_required(VERSION 3.11)
project(main)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
include(CMake/mlpack.cmake)
include(CMake/ConfigureCrossCompile.cmake)

// Download all of mlpack's dependencies and cross-compile OpenBLAS.
fetch_mlpack(ON)

Setting up include directories and source files

The last part of our CMakeFiles.txt consists of merging all of the components above together. First we need to start including the directories of our program. You will need to do the same for your software if you are trying to integrate this example into an existing codebase; this should be done by defining an include variable using set directive or add them directly in target_include_directories. Regarding the source code, a similar process by either adding then to add_executables or by appending the source files to SOURCES_FILES variable.

Finally do not forget to add any external library that you need to link against in target_link_libraries.

## Add your source files to SOURCES_FILES list
set(SOURCE_FILES main.cpp)
add_executable(RandomForest main.cpp ${SOURCES_FILES})

# If needed, add any additional include directories here.
target_include_directories(RandomForest PRIVATE
  ${MLPACK_INCLUDE_DIRS}
  # Add more include directories here...
)

# If your application needs to link against more than just mlpack's
# dependencies, be sure to list them here.
target_link_libraries(RandomForest PRIVATE -static
  ${MLPACK_LIBRARIES}
  # List additional dependencies to link against here.
)

Optimization and cross-compilation

If you are interested in adding specific compiler flags to optimize operations on your hardware, you can either set CMAKE_CXX_FLAGS manually, or look at the copy of CMake/crosscompile-arch-flags.cmake in your project, find the appropriate ARCH_NAME section, and add the new compilation flags to that file.

Once you have added all the source files and the headers for your applications, you can create your own build directory and build the software using cmake, and then make. Your cmake command should be similar to the following:

cmake \
    -DARCH_NAME=(Check below) \
    -DCMAKE_CROSSCOMPILING=ON \
    -DCMAKE_TOOLCHAIN_FILE=../CMake/crosscompile-toolchain.cmake \
    -DTOOLCHAIN_PREFIX=(Check below) \
    -DCMAKE_SYSROOT=(Check below) \

In order to fill the TOOLCHAIN_PREFIX and CMAKE_SYSROOT variables, use this table.

If your preferred architecture is missing, or if the table needs an update, please submit a PR to the repository and help us keep it up to date!