Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter

- CitrineOS core extracted (CSMS OCPP 2.0.1)
- OpenOCPP extracted (firmware OCPP 1.6J/2.0.1)
- ShapeShifter library installed (pip install -e)
- ShapeShifter specification extracted
- EVerest extracted

TODO updated with progress
This commit is contained in:
Eric F
2026-06-08 00:38:27 -04:00
parent 468cfeaa50
commit d398a6ced2
7326 changed files with 1177561 additions and 7 deletions

View File

@@ -0,0 +1,307 @@
load("@rules_python//python:defs.bzl", "PyInfo")
load("//third-party/bazel/toolchains:defs.bzl", "CROSS_PYTHON_INCOMPATIBLE")
def _everest_env(ctx):
"""Everest Root rule
Rule creates a everest root from provided modules and config file.
"""
# Validate the input - we make sure that the set of provided modules matches
# the set of modules declared in config.yaml
validation_output = ctx.actions.declare_file(ctx.attr.name + ".validation")
ctx.actions.run(
inputs = ctx.attr.config_file[DefaultInfo].files,
outputs = [validation_output],
executable = ctx.executable._validation_tool,
arguments = [
"--output",
validation_output.path,
"--config",
ctx.attr.config_file[DefaultInfo].files.to_list()[0].path,
"--",
] +
[mod.label.name for mod in ctx.attr.modules],
)
symlinks = {}
files = []
py_toolchain = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"]
py_interpreter = py_toolchain.py3_runtime.interpreter.dirname.removeprefix("external/")
py_imports = []
py_transitive_sources = []
# Python modules get a special handling.
for mod in ctx.attr.modules + ctx.attr.test_modules:
if PyInfo in mod:
py_imports.extend(mod[PyInfo].imports.to_list())
py_transitive_sources.extend(mod[PyInfo].transitive_sources.to_list())
for mod in ctx.attr.modules + ctx.attr.test_modules:
# Find the manifest in the data_runfiles and use its path as prefix.
manifest = [
file
for file in mod[DefaultInfo].data_runfiles.files.to_list()
if file.basename in ["manifest.yaml", "manifest.yml"]
][0]
prefix = manifest.dirname
symlinks.update(
{
"libexec/everest/modules/{0}{1}".format(
mod.label.name,
file.path.removeprefix(prefix),
): file
for file in mod[DefaultInfo].data_runfiles.files.to_list()
if file.path.startswith(prefix)
},
)
[
files.append(file)
for file in mod[DefaultInfo].default_runfiles.files.to_list()
if not file.path.startswith(prefix)
]
config_file = ctx.attr.config_file[DefaultInfo].files.to_list()[0]
config_path = "etc/everest/{0}".format(config_file.basename)
symlinks.update({"bin/manager_impl": ctx.attr.manager[DefaultInfo].files.to_list()[0]})
symlinks.update(
{
config_path: config_file,
},
)
symlinks.update(
{
"etc/everest/default_logging.cfg": ctx.attr.default_logging_file[DefaultInfo].files.to_list()[0],
},
)
# EVerest expects that there is a `share/everest/www` directory but does
# not care about the content... We just symlink the config.yaml into it.
symlinks.update(
{
"share/everest/www/config.yaml": ctx.attr.config_file[DefaultInfo].files.to_list()[0],
},
)
symlinks.update(
{
"share/everest/schemas/{0}".format(file.basename): file
for file in ctx.attr.schemas[DefaultInfo].files.to_list()
},
)
symlinks.update(
{
"share/everest/interfaces/{0}".format(file.basename): file
for interfaces in ctx.attr.interfaces
for file in interfaces[DefaultInfo].files.to_list()
},
)
symlinks.update(
{
"share/everest/types/{0}".format(file.basename): file
for types in ctx.attr.types
for file in types[DefaultInfo].files.to_list()
},
)
symlinks.update(
{
"share/everest/errors/{0}".format(file.basename): file
for errors in ctx.attr.errors
for file in errors[DefaultInfo].files.to_list()
},
)
# For the executable we need to export the python specific variables by
# hand.
script = ctx.actions.declare_file("manager_wrapper.{}".format(ctx.label.name))
script_content = """\
#!/bin/sh
set -eu
SCRIPT_DIR=$(cd "$(dirname "$0")/.." && pwd)
export PATH="$SCRIPT_DIR/{py_interpreter}:$PATH"
{pythonpath_lines}
""".format(
py_interpreter = py_interpreter.removeprefix("external/"),
pythonpath_lines = "\n".join([
'export PYTHONPATH="$SCRIPT_DIR/{0}:$PYTHONPATH"'.format(imp)
for imp in py_imports
]),
)
if ctx.attr._is_test:
script_content += """
exec bin/manager_impl --prefix . --config {0} --check
""".format(config_path)
else:
script_content += """
if [ $# -gt 0 ]; then
exec bin/manager_impl "$@"
else
exec bin/manager_impl --prefix . --config {0}
fi
""".format(config_path)
ctx.actions.write(script, script_content, is_executable = True)
symlinks.update({"bin/manager": script})
runfiles = ctx.runfiles(
symlinks = symlinks,
files = files + [script],
)
return [
DefaultInfo(
executable = script,
runfiles = runfiles,
),
OutputGroupInfo(_validation = depset([validation_output])),
PyInfo(
imports = depset(py_imports),
transitive_sources = depset(py_transitive_sources),
),
]
ATTRS = {
"config_file": attr.label(
doc = """
The EVerest configuration file. It will be linked to
`/etc/everest/<basename>`""",
allow_single_file = True,
),
"manager": attr.label(
doc = "The EVerest manager.",
default = Label("//lib/everest/framework:manager"),
allow_single_file = True,
executable = True,
cfg = "target",
),
"schemas": attr.label(
doc = "The target with the EVerest schemas.",
default = Label("//lib/everest/framework/schemas"),
),
"interfaces": attr.label_list(
doc = "A list of targets with EVerest interfaces.",
default = [
Label("//lib/everest/framework/everestrs/tests/interfaces"),
],
),
"types": attr.label_list(
doc = "A list of targets with EVerest types.",
default = [
Label("//lib/everest/framework/everestrs/tests/types"),
],
),
"errors": attr.label_list(
doc = "A list of targets with EVerest errors.",
default = [
Label("//lib/everest/framework/everestrs/tests/errors"),
],
),
"default_logging_file": attr.label(
doc = "The target with the EVerest logging.ini file.",
default = Label("//lib/everest/framework/everestrs/tests:logging.ini"),
allow_single_file = True,
),
"modules": attr.label_list(
doc = """
The list of targets with the EVerest modules under test.
The rule validates that the set of provided modules matches the set of modules
defined in the given `config_file`.""",
allow_files = False,
),
"test_modules": attr.label_list(
doc = """
The list of targets with EVerest modules which are only enabled by the
`everest.testing` framework.
The rule will not enforce that these modules are defined in the given
`config_file`.
""",
allow_files = False,
),
"_validation_tool": attr.label(
default = Label("//lib/everest/framework/bazel/validate"),
executable = True,
cfg = "exec",
),
"_is_test": attr.bool(
default = False,
doc = "Indicates if target is test target to validate config",
),
}
everest_impl_env = rule(
implementation = _everest_env,
attrs = ATTRS,
executable = True,
toolchains = ["@bazel_tools//tools/python:toolchain_type"],
)
_everest_impl_test = rule(
implementation = _everest_env,
attrs = dict(ATTRS, _is_test = attr.bool(default = True)),
toolchains = ["@bazel_tools//tools/python:toolchain_type"],
doc = """
Creates an EVerest Test.
Example:
Suppose you have the EVerest modules `ModuleFoo` and `ModuleBar` and the
EVerest config `my_config.yaml` which uses both modules. The test will launch
the modules and return when the manager process returns.
Then you can create an environment by writing:
```
everest_test(
name = "my_everest_env",
modules = [":ModuleFoo", ":ModuleBar"],
config_file = ":my_config.yaml",
test_script=":my_test_script",
)
```
You can run it with `bazel test`.
""",
test = True,
)
def everest_test(name, target_compatible_with = [], **kwargs):
"""Wrapper around the everest_test rule that marks the target as
incompatible with cross-compilation platforms (no Python toolchain)."""
_everest_impl_test(
name = name,
target_compatible_with = CROSS_PYTHON_INCOMPATIBLE + target_compatible_with,
**kwargs
)
def everest_env(name, target_compatible_with = [], **kwargs):
"""
Creates an EVerest environment.
Example:
Suppose you have the EVerest modules `ModuleFoo` and `ModuleBar` and the
EVerest config `my_config.yaml` which uses both modules.
Then you can create an environment by writing:
```
everest_env(
name = "my_everest_env",
modules = [":ModuleFoo", ":ModuleBar"],
config_file = ":my_config.yaml",
)
```
You can either run this target with `bazel run` or pass it for example to a (py)
test which will run your tests against the environment.
"""
everest_impl_env(
name = name,
target_compatible_with = CROSS_PYTHON_INCOMPATIBLE + target_compatible_with,
**kwargs
)
everest_test(name = name + "__manager_test", tags = ["exclusive"], target_compatible_with = target_compatible_with, **kwargs)

View File

@@ -0,0 +1,22 @@
def rs_everest_module(
name,
manifest,
binary):
native.genrule(
name = "copy_to_subdir",
srcs = [binary, manifest],
outs = [
"{}/manifest.yaml".format(name),
"{}/{}".format(name, name),
],
cmd = "mkdir -p $(RULEDIR)/{} && ".format(name) +
"cp $(location {}) $(RULEDIR)/{}/{} && ".format(binary, name, name) +
"cp $(location {}) $(RULEDIR)/{}/".format(manifest, name),
)
native.filegroup(
name = name,
srcs = [
":copy_to_subdir",
],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,11 @@
load("@everest_framework_validate_crate_index//:defs.bzl", "all_crate_deps")
load("@rules_rust//rust:defs.bzl", "rust_binary")
rust_binary(
name = "validate",
srcs = glob(["src/**/*.rs"]),
deps = all_crate_deps(),
visibility = ["//visibility:public"],
edition = "2021",
)

View File

@@ -0,0 +1,305 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anstream"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
[[package]]
name = "anstyle-parse"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "clap"
version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "everest_validate"
version = "0.1.0"
dependencies = [
"clap",
"serde",
"serde_yaml",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "indexmap"
version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "proc-macro2"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "serde"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_yaml"
version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
"indexmap",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unsafe-libyaml"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

View File

@@ -0,0 +1,11 @@
[package]
name = "everest_validate"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "4.5.4", features = ["derive"] }
serde = { version = "1.0.200", features = ["derive"] }
serde_yaml = "0.9.34"

View File

@@ -0,0 +1,64 @@
use clap::Parser;
/// Validates the EVerest config.
#[derive(Parser, Debug)]
struct Args {
/// The output file to touch. Bazel will look for this one.
#[arg(long)]
output: String,
/// The input file containing the config. We will parse this file.
#[arg(long)]
config: String,
/// The list of expected modules.
#[arg(required = true)]
modules: Vec<String>,
}
/// The relevant sub-portion of EVerest's config.
mod config {
#[derive(Debug, serde::Deserialize)]
pub struct Module {
pub module: String,
}
#[derive(Debug, serde::Deserialize)]
pub struct EverestConfig {
pub active_modules: std::collections::HashMap<String, Module>,
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();
let config = std::fs::read_to_string(args.config)?;
let config: config::EverestConfig = serde_yaml::from_str(&config)?;
let config_modules: std::collections::HashSet<_> = config
.active_modules
.into_values()
.filter_map(|m| {
if &m.module == "ProbeModule" {
None
} else {
Some(m.module)
}
})
.collect();
let given_modules: std::collections::HashSet<_> = args.modules.into_iter().collect();
assert!(
given_modules == config_modules,
"given_modules != config_modules.\ngiven_modules: {:?}\nconfig_modules: {:?}",
given_modules,
config_modules
);
std::fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(args.output)?;
Ok(())
}