From 86ebf6dd05594b12c7a685d282e9c0f295424ce3 Mon Sep 17 00:00:00 2001 From: makekryl Date: Sun, 1 Feb 2026 15:00:22 +0000 Subject: [PATCH 1/2] Launch ruff via uvx --- README.md | 7 ++++++- inv/tasks/check.py | 2 ++ pyproject.toml | 15 ++++++--------- ruff.toml | 4 ++++ uv.lock | 37 ++++++++----------------------------- 5 files changed, 26 insertions(+), 39 deletions(-) create mode 100644 ruff.toml diff --git a/README.md b/README.md index ff84095e..a0d13016 100644 --- a/README.md +++ b/README.md @@ -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` @@ -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 ` - selects the active toolchain @@ -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 ``` diff --git a/inv/tasks/check.py b/inv/tasks/check.py index a782a01f..39a356a1 100644 --- a/inv/tasks/check.py +++ b/inv/tasks/check.py @@ -37,6 +37,7 @@ class Formatter: alias="py", run=create_parallel_formatter( lambda filepath, dryrun: [ + "uvx", "ruff", "format", *(("--check",) if dryrun else ()), @@ -50,6 +51,7 @@ class Formatter: alias="py", run=create_parallel_formatter( lambda filepath, dryrun: [ + "uvx", "ruff", "check", "--select", diff --git a/pyproject.toml b/pyproject.toml index 2ec0dae6..0f65e0ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,17 +3,14 @@ name = "vanadium" version = "0.1.0" requires-python = ">=3.11" dependencies = [ - "ruff (>=0.11.11,<0.12.0)", - "invoke (>=2.2.0,<3.0.0)", - "types-invoke (>=2.0.0.10,<3.0.0.0)", - "pyyaml (>=6.0.2,<7.0.0)", + "invoke (>=2.2.0,<3.0.0)", + "types-invoke (>=2.0.0.10,<3.0.0.0)", ] [tool.uv] package = false -[tool.ruff] -indent-width = 2 - -[tool.ruff.lint] -select = ["E4", "E7", "E9", "F", "B", "I"] +[dependency-groups] +build = [ + "pyyaml (>=6.0.2,<7.0.0)", +] diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..435a0f93 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,4 @@ +indent-width = 2 + +[lint] +select = ["E4", "E7", "E9", "F", "B", "I"] diff --git a/uv.lock b/uv.lock index 290bd0bd..9e5e25fc 100644 --- a/uv.lock +++ b/uv.lock @@ -46,31 +46,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, ] -[[package]] -name = "ruff" -version = "0.11.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/53/ae4857030d59286924a8bdb30d213d6ff22d8f0957e738d0289990091dd8/ruff-0.11.11.tar.gz", hash = "sha256:7774173cc7c1980e6bf67569ebb7085989a78a103922fb83ef3dfe230cd0687d", size = 4186707, upload-time = "2025-05-22T19:19:34.363Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/14/f2326676197bab099e2a24473158c21656fbf6a207c65f596ae15acb32b9/ruff-0.11.11-py3-none-linux_armv6l.whl", hash = "sha256:9924e5ae54125ed8958a4f7de320dab7380f6e9fa3195e3dc3b137c6842a0092", size = 10229049, upload-time = "2025-05-22T19:18:45.516Z" }, - { url = "https://files.pythonhosted.org/packages/9a/f3/bff7c92dd66c959e711688b2e0768e486bbca46b2f35ac319bb6cce04447/ruff-0.11.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c8a93276393d91e952f790148eb226658dd275cddfde96c6ca304873f11d2ae4", size = 11053601, upload-time = "2025-05-22T19:18:49.269Z" }, - { url = "https://files.pythonhosted.org/packages/e2/38/8e1a3efd0ef9d8259346f986b77de0f62c7a5ff4a76563b6b39b68f793b9/ruff-0.11.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d6e333dbe2e6ae84cdedefa943dfd6434753ad321764fd937eef9d6b62022bcd", size = 10367421, upload-time = "2025-05-22T19:18:51.754Z" }, - { url = "https://files.pythonhosted.org/packages/b4/50/557ad9dd4fb9d0bf524ec83a090a3932d284d1a8b48b5906b13b72800e5f/ruff-0.11.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7885d9a5e4c77b24e8c88aba8c80be9255fa22ab326019dac2356cff42089fc6", size = 10581980, upload-time = "2025-05-22T19:18:54.011Z" }, - { url = "https://files.pythonhosted.org/packages/c4/b2/e2ed82d6e2739ece94f1bdbbd1d81b712d3cdaf69f0a1d1f1a116b33f9ad/ruff-0.11.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b5ab797fcc09121ed82e9b12b6f27e34859e4227080a42d090881be888755d4", size = 10089241, upload-time = "2025-05-22T19:18:56.041Z" }, - { url = "https://files.pythonhosted.org/packages/3d/9f/b4539f037a5302c450d7c695c82f80e98e48d0d667ecc250e6bdeb49b5c3/ruff-0.11.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e231ff3132c1119ece836487a02785f099a43992b95c2f62847d29bace3c75ac", size = 11699398, upload-time = "2025-05-22T19:18:58.248Z" }, - { url = "https://files.pythonhosted.org/packages/61/fb/32e029d2c0b17df65e6eaa5ce7aea5fbeaed22dddd9fcfbbf5fe37c6e44e/ruff-0.11.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a97c9babe1d4081037a90289986925726b802d180cca784ac8da2bbbc335f709", size = 12427955, upload-time = "2025-05-22T19:19:00.981Z" }, - { url = "https://files.pythonhosted.org/packages/6e/e3/160488dbb11f18c8121cfd588e38095ba779ae208292765972f7732bfd95/ruff-0.11.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8c4ddcbe8a19f59f57fd814b8b117d4fcea9bee7c0492e6cf5fdc22cfa563c8", size = 12069803, upload-time = "2025-05-22T19:19:03.258Z" }, - { url = "https://files.pythonhosted.org/packages/ff/16/3b006a875f84b3d0bff24bef26b8b3591454903f6f754b3f0a318589dcc3/ruff-0.11.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6224076c344a7694c6fbbb70d4f2a7b730f6d47d2a9dc1e7f9d9bb583faf390b", size = 11242630, upload-time = "2025-05-22T19:19:05.871Z" }, - { url = "https://files.pythonhosted.org/packages/65/0d/0338bb8ac0b97175c2d533e9c8cdc127166de7eb16d028a43c5ab9e75abd/ruff-0.11.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:882821fcdf7ae8db7a951df1903d9cb032bbe838852e5fc3c2b6c3ab54e39875", size = 11507310, upload-time = "2025-05-22T19:19:08.584Z" }, - { url = "https://files.pythonhosted.org/packages/6f/bf/d7130eb26174ce9b02348b9f86d5874eafbf9f68e5152e15e8e0a392e4a3/ruff-0.11.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:dcec2d50756463d9df075a26a85a6affbc1b0148873da3997286caf1ce03cae1", size = 10441144, upload-time = "2025-05-22T19:19:13.621Z" }, - { url = "https://files.pythonhosted.org/packages/b3/f3/4be2453b258c092ff7b1761987cf0749e70ca1340cd1bfb4def08a70e8d8/ruff-0.11.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:99c28505ecbaeb6594701a74e395b187ee083ee26478c1a795d35084d53ebd81", size = 10081987, upload-time = "2025-05-22T19:19:15.821Z" }, - { url = "https://files.pythonhosted.org/packages/6c/6e/dfa4d2030c5b5c13db158219f2ec67bf333e8a7748dccf34cfa2a6ab9ebc/ruff-0.11.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9263f9e5aa4ff1dec765e99810f1cc53f0c868c5329b69f13845f699fe74f639", size = 11073922, upload-time = "2025-05-22T19:19:18.104Z" }, - { url = "https://files.pythonhosted.org/packages/ff/f4/f7b0b0c3d32b593a20ed8010fa2c1a01f2ce91e79dda6119fcc51d26c67b/ruff-0.11.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:64ac6f885e3ecb2fdbb71de2701d4e34526651f1e8503af8fb30d4915a3fe345", size = 11568537, upload-time = "2025-05-22T19:19:20.889Z" }, - { url = "https://files.pythonhosted.org/packages/d2/46/0e892064d0adc18bcc81deed9aaa9942a27fd2cd9b1b7791111ce468c25f/ruff-0.11.11-py3-none-win32.whl", hash = "sha256:1adcb9a18802268aaa891ffb67b1c94cd70578f126637118e8099b8e4adcf112", size = 10536492, upload-time = "2025-05-22T19:19:23.642Z" }, - { url = "https://files.pythonhosted.org/packages/1b/d9/232e79459850b9f327e9f1dc9c047a2a38a6f9689e1ec30024841fc4416c/ruff-0.11.11-py3-none-win_amd64.whl", hash = "sha256:748b4bb245f11e91a04a4ff0f96e386711df0a30412b9fe0c74d5bdc0e4a531f", size = 11612562, upload-time = "2025-05-22T19:19:27.013Z" }, - { url = "https://files.pythonhosted.org/packages/ce/eb/09c132cff3cc30b2e7244191dcce69437352d6d6709c0adf374f3e6f476e/ruff-0.11.11-py3-none-win_arm64.whl", hash = "sha256:6c51f136c0364ab1b774767aa8b86331bd8e9d414e2d107db7a2189f35ea1f7b", size = 10735951, upload-time = "2025-05-22T19:19:30.043Z" }, -] - [[package]] name = "types-invoke" version = "2.0.0.10" @@ -86,15 +61,19 @@ version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "invoke" }, - { name = "pyyaml" }, - { name = "ruff" }, { name = "types-invoke" }, ] +[package.dev-dependencies] +dev = [ + { name = "pyyaml" }, +] + [package.metadata] requires-dist = [ { name = "invoke", specifier = ">=2.2.0,<3.0.0" }, - { name = "pyyaml", specifier = ">=6.0.2,<7.0.0" }, - { name = "ruff", specifier = ">=0.11.11,<0.12.0" }, { name = "types-invoke", specifier = ">=2.0.0.10,<3.0.0.0" }, ] + +[package.metadata.requires-dev] +dev = [{ name = "pyyaml", specifier = ">=6.0.2,<7.0.0" }] From a06a75579b816c243cc3b8c82f43522bdad8c69e Mon Sep 17 00:00:00 2001 From: makekryl Date: Sun, 1 Feb 2026 15:02:26 +0000 Subject: [PATCH 2/2] Setup CI --- .github/workflows/ci.yml | 101 ++++++++++++++++++ .../composite/run-in-devcontainer/action.yml | 18 ++++ .github/workflows/devcontainer.yml | 14 +-- bin/CMakeLists.txt | 18 ++++ cmake/external/fmt.cmake | 3 + cmake/external/gtest.cmake | 3 + cmake/external/reflectcpp.cmake | 4 +- cmake/external/tbb.cmake | 10 +- inv/config.py | 2 +- inv/params/test.py | 12 ++- inv/tasks/build.py | 36 ++++++- inv/tasks/check.py | 19 ++-- inv/tasks/test.py | 7 +- pyproject.toml | 1 + tasks.py | 4 +- uv.lock | 6 +- 16 files changed, 222 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/composite/run-in-devcontainer/action.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..f340eeb8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -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/ diff --git a/.github/workflows/composite/run-in-devcontainer/action.yml b/.github/workflows/composite/run-in-devcontainer/action.yml new file mode 100644 index 00000000..7338a481 --- /dev/null +++ b/.github/workflows/composite/run-in-devcontainer/action.yml @@ -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 }} diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml index 06df26f3..d7e13a9e 100644 --- a/.github/workflows/devcontainer.yml +++ b/.github/workflows/devcontainer.yml @@ -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: @@ -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 diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt index 82eef07b..fca59b78 100644 --- a/bin/CMakeLists.txt +++ b/bin/CMakeLists.txt @@ -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 +) diff --git a/cmake/external/fmt.cmake b/cmake/external/fmt.cmake index b080ab5c..d070cf62 100644 --- a/cmake/external/fmt.cmake +++ b/cmake/external/fmt.cmake @@ -4,4 +4,7 @@ FetchContent_Declare( GIT_TAG e69e5f977d458f2650bb346dadf2ad30c5320281 GIT_SHALLOW 1 ) + +set(FMT_INSTALL OFF CACHE BOOL "" FORCE) + FetchContent_MakeAvailable(fmt) diff --git a/cmake/external/gtest.cmake b/cmake/external/gtest.cmake index 3f0a2717..ee167912 100644 --- a/cmake/external/gtest.cmake +++ b/cmake/external/gtest.cmake @@ -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) diff --git a/cmake/external/reflectcpp.cmake b/cmake/external/reflectcpp.cmake index 39342d89..90c999ec 100644 --- a/cmake/external/reflectcpp.cmake +++ b/cmake/external/reflectcpp.cmake @@ -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) diff --git a/cmake/external/tbb.cmake b/cmake/external/tbb.cmake index 008fde22..b19fea81 100644 --- a/cmake/external/tbb.cmake +++ b/cmake/external/tbb.cmake @@ -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 ) diff --git a/inv/config.py b/inv/config.py index 835c4438..78719214 100644 --- a/inv/config.py +++ b/inv/config.py @@ -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 diff --git a/inv/params/test.py b/inv/params/test.py index 701281c4..d079ecbd 100644 --- a/inv/params/test.py +++ b/inv/params/test.py @@ -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: @@ -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( @@ -40,7 +42,11 @@ def accept( None, ), InjectableParam( - "only_build", + "skip_build", + False, + ), + InjectableParam( + "no_run", False, ), InjectableParam( diff --git a/inv/tasks/build.py b/inv/tasks/build.py index b21fc5cd..c7e5662e 100644 --- a/inv/tasks/build.py +++ b/inv/tasks/build.py @@ -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 @@ -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( @@ -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", }, ) @@ -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) @@ -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]] = {} diff --git a/inv/tasks/check.py b/inv/tasks/check.py index 39a356a1..fb15f0fb 100644 --- a/inv/tasks/check.py +++ b/inv/tasks/check.py @@ -67,7 +67,7 @@ class Formatter: alias="js", run=create_parallel_formatter( lambda filepath, dryrun: [ - "npx", + *("npx", "-y"), "prettier", "--check", *(() if dryrun else ("--write",)), @@ -83,7 +83,7 @@ class Formatter: } -def _run_formatter(formatter: Formatter, dryrun: bool, workers: int) -> int: +def _run_formatter(formatter: Formatter, dryrun: bool, jobs: int) -> int: files = git.list_files(formatter.file_extensions) total_files_count = len(files) @@ -98,21 +98,22 @@ def _run_formatter(formatter: Formatter, dryrun: bool, workers: int) -> int: print( print_prefix, f"running {colors.CYAN}{formatter.name}{colors.END} " - f"over {len(files)} out of {total_files_count} files in {workers} threads", + f"over {len(files)} out of {total_files_count} files in {jobs} threads", ) ts_start = time.time() - baddies = formatter.run(files, dryrun, workers) + baddies = formatter.run(files, dryrun, jobs) elapsed = time.time() - ts_start if not baddies: - print("", print_prefix, "all files are formatted", get_elapsed_time_msg(elapsed)) + print("└", print_prefix, "all files are formatted", get_elapsed_time_msg(elapsed)) return 0 print( - "", + "└", print_prefix, - f"{len(baddies)} files are not formatted: {', '.join(f"'{colors.PURPLE}{b}{colors.END}'" for b in baddies)}", + f"{len(baddies)} files are not formatted", + ", ".join(f"'{colors.PURPLE}{b}{colors.END}'" for b in baddies), get_elapsed_time_msg(elapsed), ) @@ -120,7 +121,7 @@ def _run_formatter(formatter: Formatter, dryrun: bool, workers: int) -> int: @task -def format(c: Context, fix: bool = False, workers: int = 4): +def format(c: Context, fix: bool = False, jobs: int = 4): baddies = 0 ts_start = time.time() @@ -128,7 +129,7 @@ def format(c: Context, fix: bool = False, workers: int = 4): baddies += _run_formatter( formatter=formatter, dryrun=not fix, - workers=workers, + jobs=jobs, ) elapsed = time.time() - ts_start diff --git a/inv/tasks/test.py b/inv/tasks/test.py index 18ff2749..45d80c29 100644 --- a/inv/tasks/test.py +++ b/inv/tasks/test.py @@ -12,9 +12,12 @@ @with_build_params @with_test_params def test(c: Context, label: str): - build_dir = build.build(c, target=f"build_{label}_tests") + if not c.config.vanadium.test.skip_build: + build_dir = build.build(c, target=f"build_{label}_tests") + else: + build_dir = build.get_build_dir(c) - if c.config.vanadium.test.only_build: + if c.config.vanadium.test.no_run: return args = [] diff --git a/pyproject.toml b/pyproject.toml index 0f65e0ce..3e562253 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ dependencies = [ [tool.uv] package = false +default-groups = "all" [dependency-groups] build = [ diff --git a/tasks.py b/tasks.py index 46f36e78..db2affeb 100644 --- a/tasks.py +++ b/tasks.py @@ -1,3 +1,5 @@ +import sys + from invoke import Collection, Context, Task, UnexpectedExit, task from invoke.runners import Local as LocalRunner from invoke.runners import Result as RunResult @@ -39,7 +41,7 @@ def run(self, command: str, **kwargs): "run": { "echo_format": f"{colors.LIGHT_GRAY}{colors.BOLD} ⟶ {{command}}{colors.END}", "echo": True, - "pty": True, + "pty": sys.stdout.isatty(), }, "runners": { "local": AlertingLocalRunner, diff --git a/uv.lock b/uv.lock index 9e5e25fc..f3fa620a 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.11" [[package]] @@ -65,7 +65,7 @@ dependencies = [ ] [package.dev-dependencies] -dev = [ +build = [ { name = "pyyaml" }, ] @@ -76,4 +76,4 @@ requires-dist = [ ] [package.metadata.requires-dev] -dev = [{ name = "pyyaml", specifier = ">=6.0.2,<7.0.0" }] +build = [{ name = "pyyaml", specifier = ">=6.0.2,<7.0.0" }]