Skip to content
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
101 changes: 101 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: CI

on:
push:
branches:
- master
pull_request:
branches:
- master
merge_group:
branches:
- master

concurrency:
group: ${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read

# Ensure scripts are run with pipefail. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
# (note: does not have effect on the commands run inside devcontainer)
defaults:
run:
shell: bash

jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- name: Pull Devcontainer
uses: ./.github/workflows/composite/run-in-devcontainer
with: { run: uv sync --no-group build }

- name: Check code formatting
uses: ./.github/workflows/composite/run-in-devcontainer
with:
run: |
uv run inv check.format \
--jobs $(nproc)

test:
runs-on: ubuntu-latest
strategy:
matrix:
toolchain: [clang] # TODO: fix gcc build
kind: [unit, e2e]
steps:
- uses: actions/checkout@v5

- name: Pull Devcontainer
uses: ./.github/workflows/composite/run-in-devcontainer
with: { run: uv sync }

- name: Build tests
uses: ./.github/workflows/composite/run-in-devcontainer
with:
run: |
uv run inv test.${{ matrix.kind }} --sanitizers \
--toolchain ${{ matrix.toolchain }} \
--jobs $(nproc) --no-run

- name: Run tests
uses: ./.github/workflows/composite/run-in-devcontainer
with:
run: |
uv run inv test.${{ matrix.kind }} --sanitizers \
--toolchain ${{ matrix.toolchain }} \
--jobs $(nproc) --skip-build

release:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v5

- name: Pull Devcontainer
uses: ./.github/workflows/composite/run-in-devcontainer
with: { run: uv sync }

- name: Build Vanadium tools
uses: ./.github/workflows/composite/run-in-devcontainer
with:
run: |
uv run inv build --target vanadium_tools --release

- name: Install Vanadium tools
uses: ./.github/workflows/composite/run-in-devcontainer
with:
run: |
mkdir out/install
uv run inv build.install --dir out/install --release

- name: Upload artifact
uses: actions/upload-artifact@v6
with:
name: release
path: out/install/
18 changes: 18 additions & 0 deletions .github/workflows/composite/run-in-devcontainer/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Run in Devcontainer

inputs:
run:
required: true
type: string

runs:
using: 'composite'
steps:
- name: Run in Devcontainer
uses: devcontainers/ci@v0.3
with:
cacheFrom: ghcr.io/${{ github.repository }}-devcontainer
push: never
runCmd: |
set -euxo pipefail
${{ inputs.run }}
14 changes: 7 additions & 7 deletions .github/workflows/devcontainer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ on:
branches:
- master
paths:
- .devcontainer/**
- '.devcontainer/**'

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

jobs:
build:
Expand All @@ -29,6 +29,6 @@ jobs:
- name: Build and push Devcontainer image
uses: devcontainers/ci@v0.3
with:
imageName: ghcr.io/${{ github.repository_owner }}/vanadium-devcontainer
cacheFrom: ghcr.io/${{ github.repository_owner }}/vanadium-devcontainer
imageName: ghcr.io/${{ github.repository }}-devcontainer
cacheFrom: ghcr.io/${{ github.repository }}-devcontainer
push: always
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,14 @@ Vanadium is a non-commercial project licensed under the BSD 3-Clause License, an
Vanadium written in modern C++23, with CMake used as the build system. Python is used as auxilary language for development purposes, [pyinvoke](https://github.com/pyinvoke/invoke) is used for project tasks orchestration and [uv](https://github.com/astral-sh/uv) for Python package and environment management.

Following is required to build the project:

- `cmake`
- `clang >= 19` or `gcc >= 14`
- `python >= 3.12` for AST stuff generation
- `python >= 3.11` for AST stuff generation
- `flex` and `bison` to generate ASN.1 parser

Optionally, you may need:

- `ninja` as a faster CMake build backend
- `gdb` and `valgrind` for development
- `clang-format >= 19`
Expand Down Expand Up @@ -134,6 +136,7 @@ $ ./out/build/clang-debug-sanitizers/bin/tidy/vanadium_tidy
```

About the `inv build` flags:

- `--reconfigure` runs CMake reconfiguration before build, it may be skipped if you don't need it
- `--sanitizers` appends `-sanitizers` suffix to the active CMake preset, selecting the corresponding one (see `CMakePresets.json`)
- `--toolchain <clang|gcc>` - selects the active toolchain
Expand Down Expand Up @@ -168,11 +171,13 @@ CMake's CTest is used as the test runner and [gtest](https://google.github.io/go
There's two kind of tests - unit tests and end-to-end (e2e) tests. Unit tests are placed within corresponding targets' directories and end-to-end tests are placed in `test/`.

- To run unit tests:

```sh
$ inv test.unit
```

- To run end-to-end tests:

```sh
$ inv test.e2e
```
Expand Down
18 changes: 18 additions & 0 deletions bin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,21 @@ add_subdirectory(astdump)
add_subdirectory(fmt)
add_subdirectory(tidy)
add_subdirectory(lsp)

###

set(VANADIUM_TOOLS_TARGETS
vanadium_astdump
vanadium_fmt
vanadiumd
vanadium_tidy
)

add_custom_target(vanadium_tools DEPENDS ${VANADIUM_TOOLS_TARGETS})

install(TARGETS ${VANADIUM_TOOLS_TARGETS}
RUNTIME DESTINATION bin
COMPONENT runtime
LIBRARY DESTINATION lib
COMPONENT runtime
)
3 changes: 3 additions & 0 deletions cmake/external/fmt.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ FetchContent_Declare(
GIT_TAG e69e5f977d458f2650bb346dadf2ad30c5320281
GIT_SHALLOW 1
)

set(FMT_INSTALL OFF CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(fmt)
3 changes: 3 additions & 0 deletions cmake/external/gtest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ FetchContent_Declare(
GIT_TAG 6910c9d9165801d8827d628cb72eb7ea9dd538c5
GIT_SHALLOW 1
)

set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
if(MSVC)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
endif()

FetchContent_MakeAvailable(googletest)

include(GoogleTest)
4 changes: 2 additions & 2 deletions cmake/external/reflectcpp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ FetchContent_Declare(
PATCH_COMMAND ${REFLECTCPP_SOURCE_PATCH_COMMAND}
)

set(REFLECTCPP_JSON OFF)
set(REFLECTCPP_TOML ON)
set(REFLECTCPP_JSON OFF CACHE BOOL "" FORCE)
set(REFLECTCPP_TOML ON CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(reflectcpp)
10 changes: 6 additions & 4 deletions cmake/external/tbb.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ FetchContent_Declare(
PATCH_COMMAND ${TBB_SOURCE_PATCH_COMMAND}
)

set(TBB_TEST OFF)
set(TBB_DISABLE_HWLOC_AUTOMATIC_SEARCH ON)
set(TBBMALLOC_BUILD OFF CACHE BOOL "" FORCE)
set(TBB_TEST OFF CACHE BOOL "" FORCE)
set(TBB_DISABLE_HWLOC_AUTOMATIC_SEARCH ON CACHE BOOL "" FORCE)
set(TBB_ENABLE_IPO OFF CACHE BOOL "" FORCE) # IPO should not make a noticeable difference
#
if(VANADIUM_STATIC_BUILD)
set(BUILD_SHARED_LIBS OFF)
set(TBB_INSTALL OFF CACHE BOOL "" FORCE)
endif()

FetchContent_MakeAvailable(tbb)

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# TODO: prevent leaking of -Wno-error to dependencies
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(tbb PRIVATE
-Wno-error=stringop-overflow
)
Expand Down
2 changes: 1 addition & 1 deletion inv/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ def get_preset(config: str, toolchain: str = DEFAULT_TOOLCHAIN):
return preset


def get_build_dir(preset: str) -> Path:
def get_preset_build_dir(preset: str) -> Path:
return OUTPUT_DIR / "build" / preset
12 changes: 9 additions & 3 deletions inv/params/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ def accept(
jobs: int | None = None,
filter: str | None = None,
exclude: str | None = None,
only_build: bool = False,
skip_build: bool = False,
no_run: bool = False,
ctest_args: str | None = None,
) -> None:
if "test" not in c.config.vanadium:
Expand All @@ -21,7 +22,8 @@ def accept(
cfg.jobs = jobs
cfg.filter = filter
cfg.exclude = exclude
cfg.only_build = only_build
cfg.skip_build = skip_build
cfg.no_run = no_run
cfg.ctest_args = ctest_args

return inject_task_params(
Expand All @@ -40,7 +42,11 @@ def accept(
None,
),
InjectableParam(
"only_build",
"skip_build",
False,
),
InjectableParam(
"no_run",
False,
),
InjectableParam(
Expand Down
36 changes: 32 additions & 4 deletions inv/tasks/build.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import sys
from pathlib import Path

from invoke import Context, task

from inv.config import (
CMAKE_PRESETS,
TOOLCHAINS,
get_build_dir,
get_preset,
get_preset_build_dir,
)
from inv.params.build import with_build_params

Expand All @@ -23,10 +26,15 @@ def opt(name: str, cond: bool):
),
toolchain=c.config.vanadium.build.toolchain,
)
build_dir = get_build_dir(preset)
build_dir = get_preset_build_dir(preset)
return preset, build_dir


def get_build_dir(c: Context):
_, build_dir = _get_cmake_params(c)
return build_dir


@task
@with_build_params
def configure(
Expand All @@ -36,7 +44,7 @@ def configure(
c.run(
f"cmake -DCMAKE_GENERATOR=Ninja --preset '{preset}' -B '{build_dir}'",
env={
"CMAKE_COLOR_DIAGNOSTICS": "ON",
"CMAKE_COLOR_DIAGNOSTICS": "ON" if sys.stdout.isatty() else "OFF",
},
)

Expand All @@ -47,7 +55,7 @@ def build(
c: Context,
target: str | None = None,
):
_, build_dir = _get_cmake_params(c)
build_dir = get_build_dir(c)

if c.config.vanadium.build.reconfigure or not build_dir.exists():
configure(c)
Expand All @@ -63,6 +71,26 @@ def build(
return build_dir


@task
@with_build_params
def install(
c: Context,
dir: str | None = None,
):
build_dir = get_build_dir(c)

args = [
"--component runtime",
]
if dir:
assert Path(dir).exists(), f"directory '{dir}' does not exist"
args.append(f"--prefix '{dir}'")

c.run(f"cmake --install '{build_dir}' {' '.join(args)}")

return build_dir


@task
def list_configs(c: Context):
configs: dict[str, set[str]] = {}
Expand Down
Loading