Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rust integration (experimental) #99

Merged
merged 8 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*build
*build-cross
target
watcher.lua
workspace.yaml
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.14)

project(everest-framework
VERSION 0.6.2
VERSION 0.7.0
DESCRIPTION "The open operating system for e-mobility charging stations"
LANGUAGES CXX C
)
Expand All @@ -16,6 +16,7 @@ option(FRAMEWORK_INSTALL "Install the library (shared data might be installed an
option(CMAKE_RUN_CLANG_TIDY "Run clang-tidy" OFF)
option(EVEREST_ENABLE_JS_SUPPORT "Enable everestjs for JavaScript modules" ON)
option(EVEREST_ENABLE_PY_SUPPORT "Enable everestpy for Python modules" ON)
option(EVEREST_ENABLE_RS_SUPPORT "Enable everestrs for Rust modules" OFF)

# make own cmake modules available
list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
Expand Down Expand Up @@ -93,6 +94,10 @@ if (EVEREST_ENABLE_PY_SUPPORT)
add_subdirectory(everestpy)
endif()

if (EVEREST_ENABLE_RS_SUPPORT)
add_subdirectory(everestrs)
endif()

# FIXME (aw): should this be installed or not? Right now it is needed for the
# current packaging approach
install(TARGETS framework
Expand Down
19 changes: 19 additions & 0 deletions cmake/cxxrs.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function(emit_cxxrs_header)
set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/cxxbridge/rust/")
file(MAKE_DIRECTORY ${output_dir})
execute_process(COMMAND ${CXXBRIDGE} --header -o ${output_dir}cxx.h)
endfunction()

function(emit_cxxrs_for_module module_name)
set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/cxxbridge/${module_name}/")
file(MAKE_DIRECTORY ${output_dir})

add_custom_command(
OUTPUT ${output_dir}lib.rs.h ${output_dir}lib.rs.cc
COMMAND ${CXXBRIDGE} ${CMAKE_CURRENT_SOURCE_DIR}/${module_name}/src/lib.rs --header -o ${output_dir}lib.rs.h
COMMAND ${CXXBRIDGE} ${CMAKE_CURRENT_SOURCE_DIR}/${module_name}/src/lib.rs -o ${output_dir}lib.rs.cc
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${module_name}/src/lib.rs
COMMENT "Generating cxx for ${module_name}"
VERBATIM
Comment on lines +12 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • rather than calling the cxxbridge util here directly, I would call cxx_build::bridge from within the build.rs
  • I think, it should be the concern of this cxxrs.cmake script to figure out the path of CXXBRIDGE and not if its including script

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. The first one is a chicken and egg though: You would need to run cargo build to get the cpp code, which you need to run cmake to build the static C library, which cargo needs to link against. I.e. you would need to run cargo for only the build.rs file (which I do not think is possible), then run cmake, then cargo again. I think doing it here is the only possibility.
  2. I do not understand this comment. Can you expand?

)
endfunction()
35 changes: 35 additions & 0 deletions everestrs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
include(cxxrs)

find_program(CXXBRIDGE cxxbridge PATHS "$ENV{HOME}/.cargo/bin/")
if (CXXBRIDGE STREQUAL "CXXBRIDGE-NOTFOUND")
message("Could not find cxxbridge, trying to install with `cargo install cxxbridge-cmd'")
find_program(CARGO cargo PATHS "$ENV{HOME}/.cargo/bin/")
if (CARGO STREQUAL "CARGO-NOTFOUND")
message(FATAL_ERROR "Requires cargo available in path, install via rustup https://rustup.rs/")
endif()
execute_process(COMMAND ${CARGO} install cxxbridge-cmd --version 1.0.107)
find_program(CXXBRIDGE cxxbridge PATHS "$ENV{HOME}/.cargo/bin/")
endif()

emit_cxxrs_header()
emit_cxxrs_for_module(everestrs)

add_library(everestrs_sys STATIC
${CMAKE_CURRENT_BINARY_DIR}/cxxbridge/everestrs/lib.rs.cc
everestrs_sys/everestrs_sys.cpp
)

SirVer marked this conversation as resolved.
Show resolved Hide resolved
target_include_directories(everestrs_sys PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}/cxxbridge
)

# This is a requirement that linking works on systems enforcing PIE.
set_property(TARGET everestrs_sys PROPERTY POSITION_INDEPENDENT_CODE ON)
SirVer marked this conversation as resolved.
Show resolved Hide resolved
target_link_libraries(everestrs_sys
PRIVATE
everest::framework
everest::log
)

install(TARGETS everestrs_sys LIBRARY)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't binary ship this glue code library, as it depends on auto-generated stuff (`rust/cxx.h'), which will only be generated, when its using crate is build.

Copy link
Contributor Author

@SirVer SirVer Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do understand that you do not like the installing piece, however the comment is not actionable to me, I do not know what to do instead: To build any crate using everestrs, this library must be findable. The only way I know to make it findable is by installing it, that seems the EVerest way to go. If you have a better suggestion, I would be happy to try it out, but likely in a followup MR.

196 changes: 196 additions & 0 deletions everestrs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions everestrs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]
resolver = "2"
members = [
"everestrs",
]
SirVer marked this conversation as resolved.
Show resolved Hide resolved
11 changes: 11 additions & 0 deletions everestrs/everestrs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "everestrs"
version = "0.1.0"
edition = "2021"

[dependencies]
argh = "0.1.10"
cxx = { version = "1.0.107", features = ["c++17"] }
serde = { version = "1.0.175", features = ["derive"] }
serde_json = "1"
thiserror = "1.0.48"
29 changes: 29 additions & 0 deletions everestrs/everestrs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Rust support for everest

This is Rust support using cxx.rs to wrap the framework C++ library.

## Trying it out

- Install rust as outlined on <https://rustup.rs/>, which should just be this
one line: `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
- Built your workspace as outlined in `everest-core` README, make sure to tell
cMake to enable `EVEREST_ENABLE_RS_SUPPORT`. Note, that the Rust code relies
on being built in a workspace where `make install` was run once.
- You can now try building the code, but it will not do anything: `cd everestrs
&& cargo build --all`
- If you want to play with a node, check out `https://github.com/EVerest/everest-core/pull/344` in your workspace and run make install.
- Go to `everest-core/modules/RsSomkeTest` and run `cargo build` there.
- There is no support for building or installing Rust modules with cMake
currently, so let's fake the installation:
- Go to `everest-core/build/dist/libexec/everest/modules` and create the stuff needed for a module:
~~~bash
mkdir RsSmokeTest
ln -s ../../../../../../modules/RsSmokeTest/target/debug/smoke_test RsSmokeTest
ln -s ../../../../../../modules/RsSmokeTest/manifest.yaml .
~~~
- You should now be able to configure the `RsSmokeTest` module in your config
YAML.

## Status

This code is currently only supporting providing an interface to be implemented, i.e. no variables publish or receiving and no calling of other interfaces. Those features are straightforward, quick and easy to implement, but for now this is probably enough to iron out the integration questions.
Loading