Getting Started - igor-krechetov/hsmcpp GitHub Wiki
There are 2 ways to add hsmcpp library to your project:
- compile, install and use library through pkg-config;
- add hsmcpp repository as a subfolder in your project and compile it together with your project.
- CMake 3.14+
- Python 3
Simplest way to build hsmcpp is to run build.sh script:
git clone https://github.com/igor-krechetov/hsmcpp.git
cd ./hsmcpp
./build.shYou can build hsmcpp with any tools that you have, but provided script build_vs.cmd requires Visual Studio 2015 or newer. Make sure to set correct path to your Visual Studio directory in build_vs.cmd:
call "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86By default only STD based dispatcher is enabled. To enable Qt based one uncomment following lines and change path to match your Qt directory:
set Qt5_DIR=C:\Qt\5.9\5.9.2\msvc2015\lib\cmake\Qt5
cmake -DHSMBUILD_DISPATCHER_GLIB=OFF -DHSMBUILD_DISPATCHER_GLIBMM=OFF ..To build GLib and GLibmm based dispatchers you will need to provide pkg-config and corresponding libraries yourself.
- HSMBUILD_VERBOSE: Enable/disable HSM verbosity (usually OFF since it's only needed for hsmcpp development)
- HSMBUILD_STRUCTURE_VALIDATION: Enable/disable HSM structure validation
- HSMBUILD_THREAD_SAFETY: Enable/disable HSM thread safety
- HSMBUILD_DEBUGGING: Enable/disable support for HSM debugging using hsmdebugger (recommended to turn off in production build)
- HSMBUILD_DISPATCHER_GLIB: Enable GLib dispatcher
- HSMBUILD_DISPATCHER_GLIBMM: Enable GLibmm dispatcher
- HSMBUILD_DISPATCHER_STD: Enable std::thread based dispatcher
- HSMBUILD_DISPATCHER_QT: Enable Qt based dispatcher
- HSMBUILD_TESTS: Build unittests
- HSMBUILD_EXAMPLES: Build examples
Options can be applied when calling cmake:
cmake -DHSMBUILD_TESTS=OFF -DHSMBUILD_EXAMPLES=OFF ..Let's create the smallest state machine which would represent a switch button:

For more complex examples see /examples folder.
For simplicity we are going to use STD dispatcher to avoid additional dependencies. Source code is available in /examples/00_helloworld/00_helloworld_std.cpp
#include <chrono>
#include <thread>
#include <hsmcpp/hsm.hpp>
#include <hsmcpp/HsmEventDispatcherSTD.hpp>
using namespace std::chrono_literals;
enum class States
{
OFF,
ON
};
enum class Events
{
SWITCH
};
int main(const int argc, const char**argv)
{
std::shared_ptr<HsmEventDispatcherSTD> dispatcher = std::make_shared<HsmEventDispatcherSTD>();
HierarchicalStateMachine<States, Events> hsm(States::OFF);
hsm.initialize(dispatcher);
hsm.registerState(States::OFF, [&hsm](const VariantVector_t& args)
{
printf("Off\n");
std::this_thread::sleep_for(1000ms);
hsm.transition(Events::SWITCH);
});
hsm.registerState(States::ON, [&hsm](const VariantVector_t& args)
{
printf("On\n");
std::this_thread::sleep_for(1000ms);
hsm.transition(Events::SWITCH);
});
hsm.registerTransition(States::OFF, States::ON, Events::SWITCH);
hsm.registerTransition(States::ON, States::OFF, Events::SWITCH);
hsm.transition(Events::SWITCH);
dispatcher->join();
return 0;
}To use hsmcpp as a pkg-config module you can follow template: /examples/cmake_templates/CMakeLists_pkgconfig.txt
# This is example showing how to use hsmcpp through pkg-config
cmake_minimum_required(VERSION 2.6)
project(example)
set(BINARY_NAME "example")
set(CMAKE_CXX_STANDARD 14)
# Find HSMCPP package
include(FindPkgConfig)
pkg_check_modules(HSMCPP REQUIRED hsmcpp_std)
# Apply HSMCPP definitions
add_definitions(${HSMCPP_CFLAGS_OTHER})
add_executable(${BINARY_NAME} main.cpp)
# Add HSMCPP include directory
target_include_directories(${BINARY_NAME} PUBLIC ${HSMCPP_INCLUDE_DIRS})
# Link with HSMCPP library
target_link_libraries(${BINARY_NAME} PUBLIC ${HSMCPP_LDFLAGS})To compile hsmcpp together with your project you can follow template: /examples/cmake_templates/CMakeLists_pkgconfig.txt
# This is an example showing how to use hsmcpp library as a source code
cmake_minimum_required(VERSION 2.6)
project(example)
set(BINARY_NAME "example")
set(CMAKE_CXX_STANDARD 14)
# Configure HSMCPP library
SET(HSMBUILD_EXAMPLES OFF CACHE BOOL "Disable HSM examples")
SET(HSMBUILD_TESTS OFF CACHE BOOL "Disable HSM tests")
SET(HSMBUILD_DISPATCHER_GLIB OFF CACHE BOOL "Disable Glib dispatcher")
SET(HSMBUILD_DISPATCHER_GLIBMM OFF CACHE BOOL "Disable Glibmm dispatcher")
SET(HSMBUILD_DISPATCHER_QT OFF CACHE BOOL "Disable Qt dispatcher")
SET(HSMBUILD_DISPATCHER_STD ON CACHE BOOL "Enable STD dispatcher")
# Include hsmcpp directory (this is folder where hsmcpp code was checked out from Git)
add_subdirectory(hsmcpp)
# Apply compiler flags needed for HSMCPP
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${HSMCPP_CXX_FLAGS}")
# Apply HSMCPP definitions
add_definitions(${HSM_DEFINITIONS_STD})
add_executable(${BINARY_NAME} main.cpp)
# Add HSMCPP include directory
target_include_directories(${BINARY_NAME} PUBLIC ${HSMCPP_STD_INCLUDE})
# Link with HSMCPP library
target_link_libraries(${BINARY_NAME} PUBLIC ${HSMCPP_STD_LIB})Maybe the easiest option to use hsmcpp in your project is to download it directly from GitHub and compile it together with your application. The downsides of this approach are:
- dependency on Internet connection availability and GitHub;
- a bit longer clean build time due to the necessity to download hsmcpp library files (since files are stored in your temporary build folder).
You can use this CMake template: /examples/cmake_templates/CMakeLists_fetch.txt
# This is an example showing how to use hsmcpp library directly from GitHub
cmake_minimum_required(VERSION 2.6)
project(example)
set(BINARY_NAME "example")
set(CMAKE_CXX_STANDARD 14)
# wrapper function to download hsmcpp
function(installHsmcpp)
include(FetchContent)
message("Downloading hsmcpp...")
FetchContent_Declare(hsmcpp
GIT_REPOSITORY https://github.com/igor-krechetov/hsmcpp.git
GIT_TAG main
)
FetchContent_MakeAvailable(hsmcpp)
endfunction()
# Configure and install HSMCPP library
SET(HSMBUILD_EXAMPLES OFF CACHE BOOL "Disable HSM examples")
SET(HSMBUILD_TESTS OFF CACHE BOOL "Disable HSM tests")
SET(HSMBUILD_DISPATCHER_GLIB OFF CACHE BOOL "Disable Glib dispatcher")
SET(HSMBUILD_DISPATCHER_GLIBMM OFF CACHE BOOL "Disable Glibmm dispatcher")
SET(HSMBUILD_DISPATCHER_QT OFF CACHE BOOL "Disable Qt dispatcher")
SET(HSMBUILD_DISPATCHER_STD ON CACHE BOOL "Enable STD dispatcher")
installHsmcpp()
# ----------------------------------------------------------------------
# Application specific code. This is just an example it there are no restrictions to use it specifically in this way
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${HSMCPP_CXX_FLAGS}")
set(BINARY_NAME "myapplication")
# add defined needed by HSMCPP (based on your dispatcher type)
add_definitions(${HSM_DEFINITIONS_STD})
add_executable(${BINARY_NAME} main.cpp ${GEN_SRC})
# generate state machine code (optional)
set(GEN_DIR ${CMAKE_BINARY_DIR}/gen)
file(MAKE_DIRECTORY ${GEN_DIR})
generateHsm(GEN_HSM ./statemachine.scxml "MyStateMachine" ${GEN_DIR} "GEN_SRC")
add_dependencies(${BINARY_NAME} GEN_HSM)
# generate state machine diagram (optional)
set(GEN_DIR_DIAGRAM ${CMAKE_BINARY_DIR}/gen_diagram)
file(MAKE_DIRECTORY ${GEN_DIR_DIAGRAM})
generateHsmDiagram(GEN_HSM_DIAGRAM ./statemachine.scxml ${GEN_DIR_DIAGRAM}/statemachine.plantuml)
add_dependencies(${BINARY_NAME} GEN_HSM_DIAGRAM)
target_include_directories(${BINARY_NAME}
PRIVATE
${HSMCPP_STD_INCLUDE} # add HSMCPP to include path
${CMAKE_BINARY_DIR}
)
# link with HSMCPP library (based on used dispatcher)
target_link_libraries(${BINARY_NAME} PRIVATE ${HSMCPP_STD_LIB})
# set compiler options for HSMCPP library (based on used dispatcher)
target_compile_options(${BINARY_NAME} PRIVATE ${HSMCPP_STD_CXX_FLAGS})