Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Build system
Browse files Browse the repository at this point in the history
daniel-noland committed Nov 8, 2024
1 parent 66c3cb2 commit 8870716
Showing 867 changed files with 127,966 additions and 16,511 deletions.
36 changes: 11 additions & 25 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,26 +1,12 @@
[target.'cfg(debug_assertions)']
runner = 'sudo -E'
rustflags = [
"-C", "linker=clang",
"-C", "link-arg=-fuse-ld=lld",
"-C", "link-arg=--ld-path=/home/dnoland/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld/ld.lld",
"-C", "opt-level=0",
"-C", "lto=false",
]
[env]
COMPILE_ENV = { value = "compile-env", relative = true, force = false }
PATH = { value = "compile-env/bin", relative = true, force = true }
LD_LIBRARY_PATH = { value = "compile-env/lib", relative = true, force = true }
LIBCLANG_PATH = { value = "compile-env/lib", relative = true, force = true }

[target.'cfg(not(debug_assertions))']
rustflags = [
"-C", "linker=clang",
"-C", "link-arg=-fuse-ld=lld",
"-C", "link-arg=--ld-path=/home/dnoland/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld/ld.lld",
"-C", "opt-level=3",
"-C", "codegen-units=1",
"-C", "linker-plugin-lto",
"-C", "lto=thin",
"-C", "embed-bitcode=yes",
# Full RELRO as a basic security measure
# <https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro>
"-C", "relro-level=full",
# "-Z", "sanitizer=cfi",
# "-Z", "sanitizer=safestack",
]
[build]
target = "x86_64-unknown-linux-gnu"

[alias]
just = ["just", "cargo"]
sterile = ["just", "sterile", "cargo"]
26 changes: 26 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[profile.default]
retries = 3
test-threads = "num-cpus"
status-level = "all"
final-status-level = "all"
failure-output = "immediate"
success-output = "immediate"
fail-fast = "false"

[profile.default.junit]
path = "default.xml"
store-success-output = true
store-failure-output = true

[profile.dev]

[profile.dev.junit]
path = "dev.xml"
store-success-output = true
store-failure-output = true

[profile.release]
[profile.release.junit]
path = "release.xml"
store-success-output = true
store-failure-output = true
16 changes: 0 additions & 16 deletions .devcontainer/devcontainer.json

This file was deleted.

5 changes: 3 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -6,10 +6,11 @@ updates:
directories:
- /
schedule:
interval: "daily"
interval: "weekly"
versioning-strategy: "widen"
groups:
dev-dependencies:
applies-to: version-updates
applies-to: "version-updates"
patterns:
- "*"
update-types:
124 changes: 0 additions & 124 deletions .github/workflows/build-and-deploy-docs.yml

This file was deleted.

70 changes: 70 additions & 0 deletions .github/workflows/bump.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: "bump.yml"
on:
workflow_dispatch:
inputs:
debug_enabled:
type: "boolean"
description: "Run with tmate enabled"
required: false
default: false
schedule:
# Check for updates at 3:18am every day.
# I avoid midnight because everyone uses midnight and
# I don't need to contribute to load spikes.
- cron: "18 3 * * *"

concurrency:
group: "${{ github.workflow }}:${{ github.ref }}"
cancel-in-progress: true

permissions:
contents: "write"
pull-requests: "write"
packages: "read"
id-token: "write"
jobs:
update:
runs-on: "ubuntu-latest"
steps:
- name: "login to ghcr.io"
uses: "docker/login-action@v3"
with:
registry: "ghcr.io"
username: "${{ github.actor }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: "Checkout"
uses: "actions/checkout@v4"
- name: "install rust"
uses: "dtolnay/rust-toolchain@stable"
- uses: "cargo-bins/cargo-binstall@main"
- name: "install cargo-deny"
run: |
cargo binstall --no-confirm cargo-deny
- name: "deny check"
run: |
cargo deny check
- name: "install envsubst"
run: |
sudo apt-get update
sudo apt-get --yes --no-install-recommends gettext
- run: |
./scripts/update-versions.sh
- name: "Create Pull Request"
uses: "peter-evans/create-pull-request@v7"
with:
branch: "bump/dpdk-sys"
title: "bump/dpdk-sys"
labels: |
automated
dependencies
signoff: "true"
commit-message: "bump/dpdk-sys"
sign-commits: "true"
body: "bump dpdk-sys"

- name: "Setup tmate session for debug"
if: ${{ failure() && github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
uses: "mxschmitt/action-tmate@v3"
timeout-minutes: 60
with:
limit-access-to-actor: true
138 changes: 138 additions & 0 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# The primary point of this workflow is to ensure that the developer experience is good.
# We take a very vanilla ubuntu image, install all necessary dependencies via "normal" means,
# and then run the build and test steps as described in the README.md file.

# The artifacts produced by these builds are not intended to be used for anything other than
# ensuring that the developer experience is good.

# Production artifacts are produced in a sterile environment (in another CI workflow).

name: "dev.yml"
on:
merge_group:
workflow_dispatch:
inputs:
debug_enabled:
type: "boolean"
description: "Run with tmate enabled"
required: false
default: false
push: {}

concurrency:
group: "${{ github.workflow }}:${{ github.ref }}"
cancel-in-progress: true

permissions:
contents: "read"
packages: "write"
id-token: "write"

jobs:
build:
strategy:
fail-fast: false
matrix:
rust:
- toolchain: "stable"
optional: false
- toolchain: "beta"
optional: true
- toolchain: "nightly"
optional: true
just:
- version: "1.36.0"
continue-on-error: ${{ matrix.rust.optional }}
runs-on: "lab"
timeout-minutes: 45
steps:
- name: "login to ghcr.io"
uses: "docker/login-action@v3"
with:
registry: "ghcr.io"
username: "${{ github.actor }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: "install rust"
uses: "dtolnay/rust-toolchain@stable"
with:
toolchain: "${{ matrix.rust.toolchain }}"
targets: "x86_64-unknown-linux-gnu,x86_64-unknown-linux-musl"
- name: "Checkout"
uses: "actions/checkout@v4"
- uses: "cargo-bins/cargo-binstall@main"
- name: "install just"
run: |
cargo binstall --no-confirm just
- name: "install nextest"
run: |
cargo binstall --no-confirm cargo-nextest
- name: "install cargo-deny"
run: |
cargo binstall --no-confirm cargo-deny
- run: |
just cargo deny check
- name: "install openssl and libssl-dev (needed for markdown-test-report)"
run: |
sudo apt-get update
sudo apt-get --yes --no-install-recommends install pkg-config openssl libssl-dev colorized-logs
- name: "install markdown-test-report"
run: |
cargo binstall --no-confirm markdown-test-report
- name: refresh-compile-env
run: |
just --yes refresh-compile-env
- run: |
just --yes fake-nix
- run: |
just cargo +${{matrix.rust.toolchain}} build --locked --profile=dev --target=x86_64-unknown-linux-gnu
continue-on-error: ${{ matrix.rust.optional }}
- name: "tests: rust ${{ matrix.rust.toolchain }} profile=dev target=x86_64-unknown-linux-gnu"
run: |
export GITHUB_STEP_SUMMARY
just debug=true rust=${{matrix.rust.toolchain}} profile=dev target=x86_64-unknown-linux-gnu test
just debug=true rust=${{matrix.rust.toolchain}} profile=dev target=x86_64-unknown-linux-gnu report
continue-on-error: ${{ matrix.rust.optional }}

- run: |
just cargo +${{matrix.rust.toolchain}} build --locked --profile=dev --target=x86_64-unknown-linux-musl
continue-on-error: ${{ matrix.rust.optional }}
- name: "tests: rust ${{ matrix.rust.toolchain }} profile=dev target=x86_64-unknown-linux-musl"
run: |
export GITHUB_STEP_SUMMARY
just debug=true rust=${{matrix.rust.toolchain}} profile=dev target=x86_64-unknown-linux-musl test
just debug=true rust=${{matrix.rust.toolchain}} profile=dev target=x86_64-unknown-linux-musl report
continue-on-error: ${{ matrix.rust.optional }}

- run: |
just cargo +${{matrix.rust.toolchain}} build --locked --profile=release --target=x86_64-unknown-linux-gnu
continue-on-error: ${{ matrix.rust.optional }}
- name: "tests: rust ${{ matrix.rust.toolchain }} profile=release target=x86_64-unknown-linux-gnu"
run: |
export GITHUB_STEP_SUMMARY
just debug=true rust=${{matrix.rust.toolchain}} profile=release target=x86_64-unknown-linux-gnu test
just debug=true rust=${{matrix.rust.toolchain}} profile=release target=x86_64-unknown-linux-gnu report
continue-on-error: ${{ matrix.rust.optional }}

- run: |
just cargo +${{matrix.rust.toolchain}} build --locked --profile=release --target=x86_64-unknown-linux-musl
continue-on-error: ${{ matrix.rust.optional }}
- name: "tests: rust ${{ matrix.rust.toolchain }} profile=release target=x86_64-unknown-linux-musl"
run: |
export GITHUB_STEP_SUMMARY
just debug=true rust=${{matrix.rust.toolchain}} profile=release target=x86_64-unknown-linux-musl test
just debug=true rust=${{matrix.rust.toolchain}} profile=release target=x86_64-unknown-linux-musl report
continue-on-error: ${{ matrix.rust.optional }}

- uses: "actions/upload-artifact@v4"
if: ${{ always() }}
with:
name: "test-results-${{ matrix.rust.toolchain }}"
path: "target/nextest/"

- name: "Setup tmate session for debug"
if: ${{ failure() && github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
uses: "mxschmitt/action-tmate@v3"
timeout-minutes: 60
with:
limit-access-to-actor: true
132 changes: 132 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: "docs.yml"

on:
workflow_dispatch:
inputs:
debug_enabled:
type: "boolean"
description: "Run the build with tmate debugging enabled"
pull_request: { }
merge_group:
push:
branches:
- "main"

concurrency:
group: "${{ github.workflow }}:${{ github.event.pull_request.number || github.event.after }}"
cancel-in-progress: true

permissions:
contents: "read"
pages: "write"
id-token: "write"
pull-requests: "read"
statuses: "write"

jobs:
check_changes:
name: "Deduce required tests from code changes"
runs-on: "ubuntu-latest"
outputs:
docs: "${{ steps.changes.outputs.docs }}"
steps:
- name: "Checkout"
if: "${{ !github.event.pull_request }}"
uses: "actions/checkout@v4"
with:
persist-credentials: "false"
fetch-depth: "0"
- name: "Check code changes"
uses: "dorny/paths-filter@v3"
id: "changes"
with:
# For "push" events, compare against the "ref" base branch.
# For "pull_request" events, this is ignored and will compare against
# the pull request base branch.
base: "${{ github.ref }}"
filters: |
docs:
- '*.nix'
- 'flake.lock'
- 'design-docs/**'
- 'nix/**'
- '.github/workflows/build-and-deploy-docs.yml'
build:
name: "Build and deploy documentation"
needs: [ check_changes ]
if: "${{ needs.check_changes.outputs.docs == 'true' }}"
runs-on: "ubuntu-latest"
steps:

- uses: "cargo-bins/cargo-binstall@main"
- run: |
cargo binstall --no-confirm just
- name: "Checkout"
uses: "actions/checkout@v4"

- name: "Extract branch name"
shell: "bash"
run: |
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
id: "extract_branch"

- name: "Extract git hash"
shell: "bash"
run: |
echo "git_hash=${GITHUB_SHA}" >> $GITHUB_OUTPUT
id: "extract_hash"

- name: "Build design docs"
run: |
just mdbook build
- name: "Copy design doc build to publish directory"
run: |
set -euxo pipefail
mkdir --parent "${{ github.workspace }}/publish/"
cp -r ./design-docs/src/mdbook/book "${{ github.workspace }}/publish/design-docs"
- name: "(Push) Setup Pages"
if: "${{ !github.event.pull_request }}"
uses: "actions/configure-pages@v5"

- name: "(Push) Upload design-docs"
if: "${{ !github.event.pull_request }}"
uses: "actions/upload-pages-artifact@v3"
with:
# Upload design-docs build directory content
path: 'publish/design-docs'

- name: "(Push) Deploy to GitHub Pages"
if: "${{ !github.event.pull_request }}"
id: "deployment"
uses: "actions/deploy-pages@v4"
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

- name: "(PR) Deploy documentation preview"
if: "${{ github.event.pull_request }}"
uses: "nwtgck/actions-netlify@v2"
with:
publish-dir: "${{ github.workspace }}/publish/design-docs"
alias: "preview-${{ github.event.number }}"
deploy-message: "${{ github.event.pull_request.title }}"
github-token: "${{ secrets.GITHUB_TOKEN }}"
fails-without-credentials: "true"
enable-commit-status: "true"
enable-pull-request-comment: "false"
enable-commit-comment: "false"
enable-github-deployment: "false"
env:
NETLIFY_AUTH_TOKEN: "${{ secrets.NETLIFY_AUTH_TOKEN }}"
NETLIFY_SITE_ID: "${{ secrets.NETLIFY_SITE_ID }}"
timeout-minutes: 5

- name: "Setup tmate session for debug"
if: ${{ failure() && github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
uses: "mxschmitt/action-tmate@v3"
timeout-minutes: 60
with:
limit-access-to-actor: true
198 changes: 198 additions & 0 deletions .github/workflows/sterile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# This is a sterile build and test workflow that uses the `dev-env` container image
# to build and test the project in a sterile environment.
# Artifacts produced by this workflow are intended to be used for production.
name: "sterile.yml"
on:
push:
merge_group:
workflow_dispatch:
inputs:
debug_enabled:
type: "boolean"
description: "Run with tmate enabled"
required: false
default: false

concurrency:
group: "${{ github.workflow }}:${{ github.ref }}"
cancel-in-progress: true

jobs:
test:
permissions:
contents: "read"
packages: "read"
id-token: "write"
runs-on: "lab"
strategy:
fail-fast: false
matrix:
rust:
- "stable"
- "nightly"
steps:
- name: "login to ghcr.io"
uses: "docker/login-action@v3"
with:
registry: "ghcr.io"
username: "${{ github.actor }}"
password: "${{ secrets.GITHUB_TOKEN }}"

- name: "install rust"
uses: "dtolnay/rust-toolchain@stable"
with:
toolchain: "${{ matrix.rust }}"
targets: "x86_64-unknown-linux-gnu"

- uses: "cargo-bins/cargo-binstall@main"
- name: "install just"
run: |
cargo binstall --no-confirm just
- name: "Checkout"
uses: "actions/checkout@v4"

- name: "dev/gnu sterile test"
if: ${{ always() }}
run: |
export GITHUB_STEP_SUMMARY
just rust="${{matrix.rust}}" profile=dev target=x86_64-unknown-linux-gnu sterile test
mkdir dev.gnu
cp -a ./target/nextest dev.gnu
- name: "release/gnu sterile test"
if: ${{ always() }}
run: |
export GITHUB_STEP_SUMMARY
just rust="${{matrix.rust}}" profile=release target=x86_64-unknown-linux-gnu sterile test
mkdir release.gnu
cp -a ./target/nextest release.gnu
- name: "dev/musl sterile test"
if: ${{ always() }}
run: |
export GITHUB_STEP_SUMMARY
just rust="${{matrix.rust}}" profile=dev target=x86_64-unknown-linux-musl sterile test
mkdir dev.musl
cp -a ./target/nextest dev.musl
- name: "release/musl sterile test"
if: ${{ always() }}
run: |
export GITHUB_STEP_SUMMARY
just rust="${{matrix.rust}}" profile=release target=x86_64-unknown-linux-musl sterile test
mkdir release.musl
cp -a ./target/nextest release.musl
- name: "install markdown-test-report"
if: ${{ always() }}
run: |
sudo apt-get update
sudo apt-get --yes --no-install-recommends install \
colorized-logs \
libssl-dev \
openssl \
pkg-config
cargo binstall --no-confirm markdown-test-report
- name: "dev/gnu report"
if: ${{ always() }}
run: |
export GITHUB_STEP_SUMMARY
export CARGO_TARGET_DIR=dev.gnu
just rust="${{matrix.rust}}" profile=dev target=x86_64-unknown-linux-gnu report
- name: "dev/musl report"
if: ${{ always() }}
run: |
export GITHUB_STEP_SUMMARY
export CARGO_TARGET_DIR=dev.musl
just rust="${{matrix.rust}}" profile=dev target=x86_64-unknown-linux-musl report
- name: "release/gnu report"
if: ${{ always() }}
run: |
export GITHUB_STEP_SUMMARY
export CARGO_TARGET_DIR=release.gnu
just rust="${{matrix.rust}}" profile=release target=x86_64-unknown-linux-gnu report
- name: "release/musl report"
if: ${{ always() }}
run: |
export GITHUB_STEP_SUMMARY
export CARGO_TARGET_DIR=release.musl
just rust="${{matrix.rust}}" profile=release target=x86_64-unknown-linux-musl report
- uses: "actions/upload-artifact@v4"
if: ${{ always() }}
with:
name: 'rust-${{matrix.rust}}-test-results'
path: "target/nextest"

- name: "Setup tmate session for debug"
if: ${{ failure() && github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
uses: "mxschmitt/action-tmate@v3"
timeout-minutes: 60
with:
limit-access-to-actor: true

push:
permissions:
contents: "read"
packages: "write"
id-token: "write"
runs-on: "lab"
strategy:
fail-fast: false
matrix:
rust:
- "stable"
- "nightly"
steps:
- name: "login to ghcr.io"
uses: "docker/login-action@v3"
with:
registry: "ghcr.io"
username: "${{ github.actor }}"
password: "${{ secrets.GITHUB_TOKEN }}"

- name: "install rust"
uses: "dtolnay/rust-toolchain@stable"
with:
toolchain: "${{ matrix.rust }}"
targets: "x86_64-unknown-linux-gnu"

- uses: "cargo-bins/cargo-binstall@main"
- name: "install just"
run: |
cargo binstall --no-confirm just
- name: "Checkout"
uses: "actions/checkout@v4"

- name: "install rust"
uses: "dtolnay/rust-toolchain@stable"
with:
toolchain: "${{ matrix.rust }}"
targets: "x86_64-unknown-linux-gnu"

- uses: "cargo-bins/cargo-binstall@main"
- run: |
cargo binstall --no-confirm cargo-deny
- run: |
just cargo deny check
- run: |
just rust="${{matrix.rust}}" profile=debug target=x86_64-unknown-linux-gnu push-container
- run: |
just rust="${{matrix.rust}}" profile=release target=x86_64-unknown-linux-gnu push-container
- run: |
just rust="${{matrix.rust}}" profile=debug target=x86_64-unknown-linux-musl push-container
- run: |
just rust="${{matrix.rust}}" profile=release target=x86_64-unknown-linux-musl push-container
- name: "Setup tmate session for debug"
if: ${{ failure() && github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
uses: "mxschmitt/action-tmate@v3"
timeout-minutes: 60
with:
limit-access-to-actor: true
30 changes: 0 additions & 30 deletions .github/workflows/update-flake.yml

This file was deleted.

13 changes: 12 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -3,4 +3,15 @@
/result*
/target/**
/design-docs/src/mdbook/book/**
/dpdk-sys/sysroot/**
/sysroot/**
/nix/result*
/sysroot
/dev-env
/compile-env/
/dev-env-template/etc
/sterile
/artifact
/design-docs/src/mdbook/src/mdbook-plantuml-img/
/.vscode
/.run/
/.bin
549 changes: 464 additions & 85 deletions Cargo.lock

Large diffs are not rendered by default.

41 changes: 6 additions & 35 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -12,47 +12,18 @@ resolver = "2"
[workspace.dependencies]

bindgen = { version = "0.70.1" }
bolero = { version = "0.11.1" }
cc = { version = "1.1.36" }
bolero = { version = "=0.10.1" } # TODO: update as soon as resolution bug with 0.11 or better is fixed
cc = { version = "1.1.31" }
criterion = { version = "0.5.1", default-features = true }
doxygen-rs = { version = "0.4.0" }
etherparse = { version = "0.16.0", default-features = false, features = [] }
libc = { version = "0.2.161" }
rstest = { version = "0.22.0", default-features = false, features = [] }
serde = { version = "1.0.214", default-features = false, features = ["derive", "alloc", "rc"] }
rand = { version = "0.8.5", default-features = false, features = [] }
rstest = { version = "0.23.0", default-features = false, features = [] }
serde = { version = "1.0.213", default-features = false, features = ["derive", "alloc", "rc"] }
syscalls = { version = "0.6.18" }
thiserror = { version = "2.0.0", package = "thiserror-no-std" } # replace with regular thiserror when https://github.com/dtolnay/thiserror/pull/304 lands
tracing = { version = "0.1.40", default-features = false, features = ["attributes"] }
tracing-subscriber = { version = "0.3.18" }
tracing-test = { version = "0.2.5" }

[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 1
overflow-checks = false
#split-debuginfo = "packed"
strip = "none"
# NOTE: I expect that we will use objcopy / strip to keep the debug symbols in a separate file
# We _could_ just compile without them, but if you need debug symbols for a release build, you
# are already having a rough day, and if you need them and don't have them, then you are having a
# worse day :)
#
# That said, debug-assertions should still be false so that compiler optimizations are not
# inhibited.
debug = true
debug-assertions = false

[profile.dev]
opt-level = 0
lto = false
incremental = true
debug = true

[profile.analysis]
inherits = "dev"
codegen-units = 1
lto = "thin"
incremental = false

[profile.fuzz]
inherits = "release"
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch AS dataplane
ARG ARTIFACT
COPY --link --chown=0:0 "${ARTIFACT}" /dataplane
WORKDIR /
ENTRYPOINT ["/dataplane"]
116 changes: 116 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Hedgehog Dataplane

## Build instructions

### Prerequisites

- Recent `x86_64` linux machine of some kind required for development
- Bash (you very likely have this)
- [Docker](https://www.docker.com/) (install through your package manager)
- Cargo / Rust (install via [`rustup`](https://rustup.rs/))

* :warning: You need a recent version of rust (1.82.0 or better) to build the project.

```bash
rustup update
```
* :warning: You need to install both the glibc and musl targets to use the default builds.

```bash
rustup target add x86_64-unknown-linux-gnu
rustup target add x86_64-unknown-linux-musl
```

- [just](https://github.com/casey/just) (install through your package manager or cargo)

## Step 0. Clone the repository

```bash
git clone git@github.com:githedgehog/dataplane.git
cd dataplane
```

## Step 1. Get the sysroot

In the source directory, run

```bash
just refresh-compile-env
```

You should now have a directory called `compile-env` which contains the tools needed to build `dpdk-sys` such as `clang` and `lld`.
You should also have `./compile-env/sysroot` which contains the libraries that `dpdk-sys` needs to link against.
Both `x86_64-unknown-linux-gnu` and `x86_64-unknown-linux-musl` targets are currently supported.

## Step 2. Fake nix

The sysroot is currently built using nix, but you don't need nix to build the project.
The idea is to symlink `/nix` to `./compile-env/nix` so that the build scripts can find the libraries they need.
This is a compromise between requiring the developer to understand nix (which can be non-trivial) and requiring the developer to have a bunch of libraries installed on their system.
> [!WARNING]
> This is a hack!
> It works fine but the plan won't work if you already have /nix.
> If you already have /nix talk to me, and we will make it work.
> It should be pretty easy (we will just need to export some stuff
> from `dpdk-sys`)

```bash
just fake-nix
```

> [!NOTE]
> If you move your project directory, you will need to run `just fake-nix refake` to update the symlinks.

## Step 3. Build the project

At this point you should be able to run

```bash
just cargo build
```

You should now have statically linked ELF executables in `target/x86_64-unknown-linux-gnu/debug/scratch` and `target/x86_64-unknown-linux-musl/debug/scratch`.

You can build in release mode with

```bash
just cargo build --profile=release
```

at which point the executables will be in `target/x86_64-unknown-linux-gnu/release/scratch` and `target/x86_64-unknown-linux-musl/release/scratch`.

## Step 4. Run the tests (debug mode)

To run the test suite, you can run

```bash
just cargo test
```

By default, this will run just the glibc tests.
To run the test suite under musl, try

```bash
just cargo test --target x86_64-unknown-linux-musl
```

To run the test suite under release mode

```bash
just cargo test --profile=release
```

> [!WARNING]
> Release builds may not work on your development machine!
>
> The release build's dependencies are compiled with `-march=x86-64-v4` because we expect to release with a very new processor.
> As a result, getting `SIGILL` on an older chip is no surprise.
> We test release builds in CI, but they may not work on your dev box ¯\\\_(ツ)\_\/¯
> [!NOTE]
> Why the `just` in `just cargo build ...`?
>
> `just` is computing the correct `RUSTFLAGS` for us depending on the profile.
> After that it simply calls `cargo build`.
> Normally we would include those kinds of setting in `Cargo.toml` but `cargo` can not currently express all the `RUSTFLAGS` we are using (thus the `just` wrapper).
54 changes: 0 additions & 54 deletions default.nix

This file was deleted.

233 changes: 233 additions & 0 deletions deny.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
# see https://github.com/EmbarkStudios/cargo-deny for docs
[graph]
targets = []
#exclude = []
all-features = false
no-default-features = false
#features = []

# The output table provides options for how/if diagnostics are outputted
[output]
feature-depth = 1

[advisories]
ignore = []
[licenses]
unused-allowed-license = "allow"
allow = [
"AFL-1.1",
"AFL-1.2",
"AFL-2.0",
"AFL-2.1",
"AFL-3.0",
# "AGPL-3.0", # Causes issues to some companies, such as Google. Deny for now.
"Apache-1.1",
"Apache-2.0",
"APSL-2.0",
"Artistic-2.0",
"BSD-2-Clause",
"BSD-3-Clause",
"BSL-1.0",
"CDDL-1.0",
"CPAL-1.0",
"CPL-1.0",
"ECL-2.0",
"EFL-2.0",
"EPL-1.0",
"EPL-2.0",
"EUDatagrid",
"EUPL-1.1",
"EUPL-1.2",
# "GPL-2.0", # rejected till we have a good case where we need them
# "GPL-3.0", # rejected till we have a good case where we need them
"HPND",
"Intel",
"IPA",
"IPL-1.0",
"ISC",
"LGPL-2.1",
"LGPL-3.0",
"LPL-1.02",
"MIT",
"MPL-1.1",
"MPL-2.0",
"MS-PL",
"MS-RL",
"NCSA",
"Nokia",
"OFL-1.1",
"OSL-1.0",
"OSL-2.0",
"OSL-2.1",
"OSL-3.0",
"PHP-3.01",
"Python-2.0",
"QPL-1.0",
"RPSL-1.0",
"SISSL",
"Sleepycat",
"SPL-1.0",
"Unlicense",
"UPL-1.0",
"W3C",
"Zlib",
"ZPL-2.0",
"ZPL-2.1",
]
# The confidence threshold for detecting a license from license text.
# The higher the value, the more closely the license text must be to the
# canonical license text of a valid SPDX license file.
# [possible values: any between 0.0 and 1.0].
confidence-threshold = 1.0
# Allow 1 or more licenses on a per-crate basis, so that particular licenses
# aren't accepted for every possible crate as with the normal allow list
exceptions = [
# Each entry is the crate and version constraint, and its specific allow
# list
#{ allow = ["Zlib"], crate = "adler32" },
# mostly harmless
{ allow = ["Unicode-DFS-2016"], crate = "unicode-ident" },
]

# Some crates don't have (easily) machine readable licensing information,
# adding a clarification entry for it allows you to manually specify the
# licensing information
#[[licenses.clarify]]
# The package spec the clarification applies to
#crate = "ring"
# The SPDX expression for the license requirements of the crate
#expression = "MIT AND ISC AND OpenSSL"
# One or more files in the crate's source used as the "source of truth" for
# the license expression. If the contents match, the clarification will be used
# when running the license check, otherwise the clarification will be ignored
# and the crate will be checked normally, which may produce warnings or errors
# depending on the rest of your configuration
#license-files = [
# Each entry is a crate relative path, and the (opaque) hash of its contents
#{ path = "LICENSE", hash = 0xbd0eed23 }
#]

[licenses.private]
# If true, ignores workspace crates that aren't published, or are only
# published to private registries.
# To see how to mark a crate as unpublished (to the official registry),
# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.
ignore = true
# One or more private registries that you might publish crates to, if a crate
# is only published to private registries, and ignore is true, the crate will
# not have its license(s) checked
registries = [
#"https://sekretz.com/registry
]

# This section is considered when running `cargo deny check bans`.
# More documentation about the 'bans' section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
[bans]
# Lint level for when multiple versions of the same crate are detected
multiple-versions = "deny"
# Lint level for when a crate version requirement is `*`
wildcards = "deny"
# The graph highlighting used when creating dotgraphs for crates
# with multiple versions
# * lowest-version - The path to the lowest versioned duplicate is highlighted
# * simplest-path - The path to the version with the fewest edges is highlighted
# * all - Both lowest-version and simplest-path are used
highlight = "all"
# The default lint level for `default` features for crates that are members of
# the workspace that is being checked. This can be overridden by allowing/denying
# `default` on a crate-by-crate basis if desired.
workspace-default-features = "allow"
# The default lint level for `default` features for external crates that are not
# members of the workspace. This can be overridden by allowing/denying `default`
# on a crate-by-crate basis if desired.
external-default-features = "allow"
# List of crates that are allowed. Use with care!
allow = [
#"ansi_term@0.11.0",
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" },
]
# List of crates to deny
deny = [
#"ansi_term@0.11.0",
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" },
# Wrapper crates can optionally be specified to allow the crate when it
# is a direct dependency of the otherwise banned crate
#{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] },
]

# List of features to allow/deny
# Each entry the name of a crate and a version range. If version is
# not specified, all versions will be matched.
#[[bans.features]]
#crate = "reqwest"
# Features to not allow
#deny = ["json"]
# Features to allow
#allow = [
# "rustls",
# "__rustls",
# "__tls",
# "hyper-rustls",
# "rustls",
# "rustls-pemfile",
# "rustls-tls-webpki-roots",
# "tokio-rustls",
# "webpki-roots",
#]
# If true, the allowed features must exactly match the enabled feature set. If
# this is set there is no point setting `deny`
#exact = true

# Similarly to `skip` allows you to skip certain crates during duplicate
# detection. Unlike skip, it also includes the entire tree of transitive
# dependencies starting at the specified crate, up to a certain depth, which is
# by default infinite.
skip-tree = [
#"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies
#{ crate = "ansi_term@0.11.0", depth = 20 },
]

[[bans.skip]]
name = "dpdk-sys"
reason = "workspace internal"

[[bans.skip]]
name = "scratch"
reason = "workspace internal"

[[bans.skip]]
name = "dpdk"
reason = "workspace internal"

[[bans.skip]]
name = "net"
reason = "workspace internal"

[[bans.skip]]
name = "syn"
reason = "syn is basically always a build time dependency so we aren't shipping multiple versions"

# This section is considered when running `cargo deny check sources`.
# More documentation about the 'sources' section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
[sources]
# Lint level for what to happen when a crate from a crate registry that is not
# in the allow list is encountered
unknown-registry = "deny"
# Lint level for what to happen when a crate from a git repository that is not
# in the allow list is encountered
unknown-git = "deny"
# List of URLs for allowed crate registries. Defaults to the crates.io index
# if not specified. If it is specified but empty, no registries are allowed.
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
# List of URLs for allowed Git repositories
allow-git = []

[sources.allow-org]
# github.com organizations to allow git sources for
github = []
# gitlab.com organizations to allow git sources for
gitlab = []
# bitbucket.org organizations to allow git sources for
bitbucket = []
52 changes: 0 additions & 52 deletions design-docs/README.md

This file was deleted.

438 changes: 0 additions & 438 deletions design-docs/ieee.csl

This file was deleted.

35 changes: 5 additions & 30 deletions design-docs/src/mdbook/book.toml
Original file line number Diff line number Diff line change
@@ -6,8 +6,10 @@ src = "src"
title = "Hedgehog Dataplane Design Notes"

[preprocessor.plantuml]
plantuml-cmd = "plantuml"
#plantuml-cmd = "/lib/openjdk/bin/java -jar /lib/plantuml.jar"
plantuml-cmd = "/bin/plantuml"
after = ["links"]
use-data-uris = false

[preprocessor.mermaid]
after = ["links"]
@@ -21,40 +23,13 @@ no-css = true
trust = true
strict = false

[preprocessor.citeproc]

after = ["links"]

bibliography = "sources/sources.bib"
bibliography-style = "./theme/bibliography-style.csl"

backtick_code_blocks = "preserve"
bracketed_spans = "transpile"
citations = "transpile"
definition_lists = "preserve"
emoji = "transpile"
fenced_code_attributes = "preserve"
fenced_code_blocks = "preserve"
fenced_divs = "transpile"
footnotes = "preserve"
hard_line_breaks = "preserve"
inline_notes = "preserve"
mark = "preserve"
markdown_in_html_blocks = "preserve"
link_attributes = "transpile"
task_lists = "preserve"

[preprocessor.alerts]

[preprocessor.admonish]
command = "mdbook-admonish"
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`

[output]

[output.html]
additional-css = ["./mdbook-admonish.css"]
additional-css = []
additional-js = ["./theme/external/mermaid.min.js", "./theme/external/mermaid-init.js"]
curly-quotes = true
smart-punctuation = true
preferrred-dark-theme = "ayu"
default-theme = "light"
348 changes: 0 additions & 348 deletions design-docs/src/mdbook/mdbook-admonish.css

This file was deleted.

35 changes: 35 additions & 0 deletions design-docs/src/mdbook/mermaid-init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
(() => {
const darkThemes = ['ayu', 'navy', 'coal'];
const lightThemes = ['light', 'rust'];

const classList = document.getElementsByTagName('html')[0].classList;

let lastThemeWasLight = true;
for (const cssClass of classList) {
if (darkThemes.includes(cssClass)) {
lastThemeWasLight = false;
break;
}
}

const theme = lastThemeWasLight ? 'default' : 'dark';
mermaid.initialize({ startOnLoad: true, theme });

// Simplest way to make mermaid re-render the diagrams in the new theme is via refreshing the page

for (const darkTheme of darkThemes) {
document.getElementById(darkTheme).addEventListener('click', () => {
if (lastThemeWasLight) {
window.location.reload();
}
});
}

for (const lightTheme of lightThemes) {
document.getElementById(lightTheme).addEventListener('click', () => {
if (!lastThemeWasLight) {
window.location.reload();
}
});
}
})();
2,186 changes: 2,186 additions & 0 deletions design-docs/src/mdbook/mermaid.min.js

Large diffs are not rendered by default.

140 changes: 0 additions & 140 deletions design-docs/src/mdbook/sources/sources.bib

This file was deleted.

6 changes: 6 additions & 0 deletions design-docs/src/mdbook/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -5,3 +5,9 @@
- [Hardware selection for dataplane project](./dataplane/hardware.md)
- [Offloading the dataplane](./dataplane/offloading-plan.md)
- [DPDK abstraction map](./dataplane/map-of-dpdk.md)
- [Build process](./build/index.md)
- [Prerequisites](./build/prerequisites.md)
- [Compile env](./build/compile-env.md)
- [fake-nix](./build/fake-nix.md)
- [Build dataplane](./build/just-cargo-build.md)
- [Sterile builds](./build/sterile-build.md)
78 changes: 78 additions & 0 deletions design-docs/src/mdbook/src/build/compile-env.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# `compile-env`

Now that we have the [prerequisites](./prerequisites.md) installed, we need to set up our sysroots and build tools.

## The "what"

This should be the easy part:

```bash
just refresh-compile-env
```

This command will use docker to pull the sysroots and compile tools which match the version of `dataplane` you are going to build.

> [!NOTE]
>
> Q: Why use docker here? What's wrong with a tar.zst?
>
> A: Because of layers!
> The compile env is fairly large (~6GB) and the layers allow for incremental updates.
> If you end up downloading multiple compile-env versions, they will likely share many of the same layers and only require a (comparatively) small amount of additional disk space.

## The "why"

When you ran `just refresh-compile-env` then you `docker pull` the `compile-env` container image.
The script then turns the `compile-env` image into a directory in the source root of the `dataplane` project called `compile-env`.

The `compile-env` directory basically looks like this:

<figure title="compile-env">

```puml
@startwbs
!pragma toez true
* compile-env
** "nix" as nix
*** {the actual files}
** bin
***_ llvm-*
***_ clang
***_ lld
** lib
***_ build dep libs
** sysroot
*** x86_64-unknown-linux-gnu
**** debug
***** lib
******_ dpdk-libs
******_ rdma-libs
******_ deps
**** release
***** lib
******_ dpdk-libs
******_ rdma-libs
******_ deps
*** x86_64-unknown-linux-musl
**** debug
***** lib
******_ dpdk-libs
******_ rdma-libs
******_ deps
**** release
***** lib
******_ dpdk-libs
******_ rdma-libs
******_ deps
@endwbs
```
> High-level anatomy of the `compile-env`.
</figure>
With that we have distributed (to the developer) all the necessary libraries to link against as well as the exact verison of llvm/clang used to link them.

Unfortunately, for reasons well outside of scope here, the files in `compile-env` are broken symlinks at this point.

We need to fix that.

68 changes: 68 additions & 0 deletions design-docs/src/mdbook/src/build/fake-nix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Fake nix

Take a look at the `/nix` directory under `compile-env` and you will find the actual libraries and files used for this project.
The other directories under `compile-env` pretty much just have symlinks which are _supposed_ to point to `/nix/$whatever`.

The `just fake-nix` recipe hacks around this by making `./compile-env/nix` the target of symlink from `/nix`.

> [!WARNING]
> This is a hack!
> It works fine but the plan won't work if you already have /nix.
> If you already have /nix talk to me, and we will make it work.
> It should be pretty easy (we will just need to export some stuff
> from `dpdk-sys`).
>
> Yeah, I would love to have a better method of dealing with that
> in the future.

After running `just fake-nix` you get this type of effect.

<figure title="fake-nix">

```puml
@startwbs
!pragma toez true
* /
**_ "/nix" as nix_sym
** ...
*** $project-dir
**** compile-env
***** "nix" as nix
***** bin
******_ llvm-*
******_ clang
******_ lld
***** lib
******_ build dep libs
***** sysroot
****** x86_64-unknown-linux-gnu
******* debug
******** lib
*********_ dpdk-libs
*********_ rdma-libs
*********_ deps
******* release
******** lib
*********_ dpdk-libs
*********_ rdma-libs
*********_ deps
****** x86_64-unknown-linux-musl
******* debug
******** lib
*********_ dpdk-libs
*********_ rdma-libs
*********_ deps
******* release
******** lib
*********_ dpdk-libs
*********_ rdma-libs
*********_ deps
nix_sym -> nix
@endwbs
```
> High-level anatomy of the `compile-env`.
</figure>

After this point, we make `cargo` use the compile environment via the settings in `.cargo/config.toml`.
74 changes: 74 additions & 0 deletions design-docs/src/mdbook/src/build/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# The build system

If you consider the whole process, the `dataplane` (by necessity) has a fairly complex build.
As a result, much effort has gone into creating a simple development experience.

### Goals:

1. The developer should never need to install DPDK or any of its dependencies manually.
This requirement stems from the desire to avoid "works on my machine" type behavior.
2. The build should not be hostile to standard developer tooling (e.g. IDE integration or debuggers).
Wrapping up cargo in a complex build system would do exactly that.
3. The build should be reproducible (when built in a sterile environment) so that the same source code will always produce the same binary.
This is important for debugging and testing purposes.

### Non goals:

1. Easy development environment on non-Linux systems. Sorry. DPDK doesn't really like Windows or Mac.
2. Easy development environment on non x86_64 systems. We may change in the future to support ARM.

## How it works

The build is split into two main parts.

1. [`dpdk-sys`]

The job of `dpdk-sys` is to compile a [sysroot](https://www.baeldung.com/linux/sysroot) which `dataplane` can consume.[^um-actually]

2. [`dataplane`]

The job of `dataplane` is to consume the sysroots and other build tools provided by `dpdk-sys` to actually compile and build the `dataplane` binary we will ship.

<figure title="Build-system data-flow">

```puml
@startuml
!pragma toez true
box "hedgehog stuff" #e0eeee
participant dataplane
participant "dpdk-sys" as dpdk_sys
end box
participant nixpkgs
participant "container\nregistry" as container_registry
participant "external\nsource repos" as external
dpdk_sys -> nixpkgs : build instructions plz
nixpkgs -> dpdk_sys : here ya go
dpdk_sys -> external: fetch code
external -> dpdk_sys: here ya go
dpdk_sys -> dpdk_sys : follow build instructions
note left
This is a **long** build
end note
dpdk_sys -> container_registry : push compile-env
container_registry -> dpdk_sys : got it
dataplane -> container_registry : compile-env plz
container_registry -> dataplane : here ya go
dataplane -> dataplane : put compile-env\nin a dir named "compile-env"
dataplane -> dataplane : ""just sterile-build""
note right
""cargo build"" (called by ""just sterile-build"") now has
access to the many "".a"" files required to compile
and link the dataplane.
It also has a consistent version of LLVM and clang to
work with.
end note
dataplane -> container_registry : push container
container_registry -> dataplane : got it
@enduml
```
> Sequence diagram for dpdk-sys / dataplane interaction.
</figure>
[`dpdk-sys`]: https://github.com/githedgehog/dpdk-sys
[`dataplane`]: https://github.com/githedgehog/dataplane
[^um-actually]: In fact, `dpdk-sys` produces four sysroots. One for each combination of dev/release builds and gnu64 and musl64 builds.
50 changes: 50 additions & 0 deletions design-docs/src/mdbook/src/build/just-cargo-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# `just` cargo

Now we can simply run

```bash
cargo build
```

or

```bash
just cargo build
```

to compile to the (dev) version of the project.


You can also run

```bash
just cargo build --release
```

> [!WARNING]
> [^release-mode]: Release builds may not work on your development machine!
>
> The release build's dependencies are compiled with `-march=x86-64-v4` because we expect to release with a very new processor.
> As a result, getting `SIGILL` on an older chip is no surprise.
> We test release builds in CI, but they may not work on your dev box ¯\\\_(ツ)\_\/¯

## The tests

Running the tests should be easy.

```bash
cargo test
```

or

```bash
just cargo test
```

should take care of it for normal development flows.

But there is a second level to this story.

Sterile builds!
35 changes: 35 additions & 0 deletions design-docs/src/mdbook/src/build/prerequisites.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Prerequisites

You will need the following before we can begin.

- A recent `x86_64` linux machine of some kind required for development.
- Bash (you very likely have this, but if not you will need to install it).
- [Docker](https://www.docker.com/) (install through your package manager)
- Cargo / Rust (I recommend installing via [`rustup`](https://rustup.rs/))

* :warning: You need a recent version of rust (1.82.0 or better) to build the project.
Run

```bash
rustup update
```

from time to time to stay up to date.

- [just](https://github.com/casey/just)

You can install `just` via your package manager, but I recommend installing it via `cargo` as it will likely be more up to date.

```
cargo install just
```
or, if you have [cargo-binstall], run
```
cargo binstall just
```
[cargo-binstall]: https://github.com/cargo-bins/cargo-binstall
29 changes: 29 additions & 0 deletions design-docs/src/mdbook/src/build/sterile-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Sterile builds

The trouble with calling something like `cargo build` is that the compile isn't sterile.

That is to say, that the build doesn't have a precise, know, portable, and deterministic (pure) version of all dependencies between developer machines.

For example, we don't know exactly what version of rust you compiled with.
Nor exactly what version of libc that rust came with.

The sterile environment builds the project in a _very_ minimal container so we can be sure what are actual dependencies are.

Running

```bash
just sterile-build
```

will build the project in a container which (by design) is missing anything that might "contaminate" the build (i.e. introduce an undocumented dependency).

Sterile builds are slower and more hostile to normal development flows.
On the other hand, they better approximate the CI environment and are a good thing to run before submitting a PR.

Likewise, you can run

```bash
just test
```

to run the tests in a minimal (sterile) environment.
8 changes: 6 additions & 2 deletions design-docs/src/mdbook/src/css/main.css
Original file line number Diff line number Diff line change
@@ -683,12 +683,16 @@ figure {
display: inline-block;
}

figure:target .figure-label::before {
figure:target::before {
content: var(--target-icon);
display: inline-block;
margin-inline-start: calc(-1 * var(--target-icon-distance));
width: var(--target-icon-distance);
min-width: 100%;
}

a.figure-label, a.figure-label:visited, a.figure-label:target, a.figure-label:hover {
text-decoration: unset;
color: unset;
}

.footnote-definition:has(p > a:first-child:target)::before {
9 changes: 5 additions & 4 deletions design-docs/src/mdbook/src/js/main.js
Original file line number Diff line number Diff line change
@@ -261,7 +261,7 @@ figureBlockquoteToCaption = () => {
});
figures.forEach((figure, i) => {
if (!figure.id) {
figure.id = `figure/${figure.title.replace(/\s/g, '-').toLowerCase()}`;
figure.id = `figure/${figure.title.replace(/\s/g, '-').toLowerCase()}`;
}
});
figures.forEach((figure, i) => {
@@ -272,9 +272,10 @@ figureBlockquoteToCaption = () => {
}
const caption = document.createElement('figcaption');
const captionAnchor = document.createElement('a');
captionAnchor.setAttribute('href', `#${figure.id}`);
captionAnchor.setAttribute('href', `#figure/${figure.id}`);
captionAnchor.classList.add('header');
const figureLabel = document.createElement('em');
const figureLabel = document.createElement('a');
figureLabel.href = `#${figure.id}`;
figureLabel.classList.add('figure-label');
figureLabel.innerText = `Figure ${i + 1}: ${figure.getAttribute('aria-label')}`;
figure.prepend(figureLabel);
@@ -286,7 +287,7 @@ figureBlockquoteToCaption = () => {
});
};

// This should not be used in a security sensitive browsing context
// This should not be used in a security-sensitive browsing context
const embedPlantuml = async () => {
const svgImgs = document.querySelectorAll('img[src$=".svg"][src*="mdbook-plantuml"]');
for (const svgImg of svgImgs) {

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 8870716

Please sign in to comment.