Integrating libraries

Overview

In order to build complex simulations, the use of third party libraries is often required. Before integrating third party libraries with your Simulate simulations, make sure the following prerequisites are met:
  1. 1.
    A Simulate project is needed. You can create a sample project by running aether new.
  2. 2.
    Have a library to integrate with the Simulate simulation
    • if it is in source form, it must have a CMake build system and support a Linux build
    • if it is pre-compiled, either a static library (.a) or a shared library (.so), it must be compiled with x86_64-unknown-linux-gnu as the target triplet.
      For ABI compatibility, keep in mind that the Aether SDK uses Clang 10.0.0 with glibc 2.31 and libstdc++ from GCC 9.3.0.
  3. 3.
    Have Build Tools installed (component you can enable while installing the SDK)

Walkthrough

Let us assume that we have a dummy maths module in a directory called mathslib.
In this directory, include/arithmetic.h is the header of this library:
#pragma once
namespace maths
{
class arithmetic
{
public:
static float add(float a, float b);
static float subtract(float a, float b);
static float multiply(float a, float b);
static float divide(float a, float b);
};
}
And in src/arithmetic.cpp has its source code.
#include "arithmetic.h"
namespace maths
{
float arithmetic::add(float a, float b)
{
return a + b;
}
float arithmetic::subtract(float a, float b)
{
return a - b;
}
float arithmetic::multiply(float a, float b)
{
return a * b;
}
float arithmetic::divide(float a, float b)
{
return a / b;
}
}
There is a CMakeLists.txt in the mathslib directory root. You can see that the output directory for the shared library is the lib directory in the Aether project root.
cmake_minimum_required (VERSION 3.18)
add_library(arithmetic SHARED src/arithmetic.cpp)
set_target_properties(arithmetic PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
target_include_directories(arithmetic PUBLIC include)
The main CMakeLists.txt of the Aether simulation looks like:
cmake_minimum_required(VERSION 3.18)
set(CMAKE_VERBOSE_MAKEFILE ON)
project(simulation)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_STANDARD 17)
set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Any calls to add_subdirectory() should only be added after CMAKE_CXX_FLAGS have been set
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -g -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-function -Wno-c99-extensions")
add_subdirectory(muxer)
add_subdirectory(mathslib)
pkg_check_modules(AETHER REQUIRED aether aether-physx aether-ecs)
if(CMAKE_HOST_WIN32)
# On Windows, wrap paths in quotes (pkg-config workaround)
list(TRANSFORM AETHER_STATIC_LDFLAGS REPLACE "-L(.*)" "-L\"\\1\"")
endif()
# Create executable from sources
list(APPEND SRC_FILES
./simulate.cc
./main.cc
)
add_executable(simulation ${SRC_FILES})
# Add protocol files to includes
target_include_directories(simulation PRIVATE ${PROJECT_SOURCE_DIR})
# Link with Aether Libraries and fmt lib.
target_link_libraries(simulation ${AETHER_STATIC_LDFLAGS} ${AETHER_STATIC_LDFLAGS_OTHER} arithmetic)
# Add compiler flags for includes
target_compile_options(simulation PUBLIC ${AETHER_STATIC_CFLAGS} ${AETHER_STATIC_CFLAGS_OTHER})
install(TARGETS simulation muxer arithmetic)
In case of pre-built objects, the CMakeLists.txt file would need to be modified accordingly so that the headers and objects are found during the build process.
Run your simulation using aether run --library-folders <...> where <...> are the folder(s) that have the shared (.so) libraries (in this case, it will be the lib folder in the project root). Multiple folders can be delimited with semicolons (;). If any of your libraries depend on other shared libraries, remember to include them in the folder as well (you can use ldd in WSL to check for dependencies).

Examples of well-known libraries

Here are examples of CMakeLists.txt files for integrating with some popular third party libraries.

Eigen

Download Eigen, there is no need to build it separately as it is header-only. Thus, only the line include_directories(${USR_PATH_TO_EIGEN_REPO}) has to be present in the CMakeLists.txt file at the root of the simulation (where ${USR_PATH_TO_EIGEN_REPO} has to be set to the user path to the downloaded repo). An example CMakeLists.txt is shown below:
cmake_minimum_required(VERSION 3.18)
project(hello_world)
include_directories(${USR_PATH_TO_EIGEN_REPO})
add_executable(app main.cpp)
It should now be as straightforward as adding the desired Eigen headers (for example, #include <Eigen/Dense>) to main.cpp (or to other files of your simulation) and running the simulation with the normal aether run command without passing any libraries.

Boost

Download the Unix flavor of the Boost source code. Create a user-config.jam file in your home directory and add the following. Be aware that Aether Engine SDK location may change depending on your installation.
using clang : 10.0.0 : "clang++" :
<archiver>"llvm-ar"
<ranlib>"llvm-ranlib"
<cxxflags>"--target=x86_64-unknown-linux-gnu --sysroot=\"C:\\Program Files (x86)\\Hadean\\Aether Engine SDK\\BuildTools\\sysroot\""
<cflags>"--target=x86_64-unknown-linux-gnu --sysroot=\"C:\\Program Files (x86)\\Hadean\\Aether Engine SDK\\BuildTools\\sysroot\""
<linkflags>"--target=x86_64-unknown-linux-gnu --sysroot=\"C:\\Program Files (x86)\\Hadean\\Aether Engine SDK\\BuildTools\\sysroot\""
;
Run the following commands. The first will create b2.exe with your native C++ compiler. The second will build and install Boost to C:\boost.
bootstrap.bat
./b2.exe install -q toolset=clang target-os=linux abi=sysv --without-python --prefix=C:\boost\
Now you can use the Boost libraries in your simulation by adding few lines to your CMakeFiles.txt:
find_package(Boost 1.76.0 EXACT REQUIRED COMPONENTS json)
include_directories(${MATH_INCLUDEDIR}, ${BOOST_INCLUDEDIR})
target_link_libraries(simulation ${AETHER_STATIC_LDFLAGS} ${AETHER_STATIC_LDFLAGS_OTHER} ${Boost_LIBRARIES})
Don't forget to push the Boost libraries to the cluster by adding the parameter --library-folders "c:\boost\lib" to your aether run command.