Clangd
ci / checks (push) Successful in 42m38s

This commit is contained in:
khodowany
2026-09-11 00:02:36 -05:00
parent f84717990b
commit 693e232957
6 changed files with 33 additions and 28 deletions
+1
View File
@@ -1,5 +1,6 @@
build/
.clangd
.nvim.lua
.clang-format
pyrightconfig.json
+4
View File
@@ -41,6 +41,10 @@ When running directly outside the generated Modulus Docker image, set `PICO_SDK_
Editor settings live in `modulus.json` under `tooling.editor`. Modulus generates the ignored `.clangd`, `.clang-format`, and `pyrightconfig.json` files; edit the JSON settings rather than these outputs. The clangd configuration routes Zero/shared code to the native compile database and Pico code to its firmware database.
Modulus also generates `.nvim.lua` for Neovim 0.11+ with `exrc` enabled. Review and trust it when Neovim asks; it preserves the existing LSP capabilities/keybindings and runs clangd 19 in the build container for this repo. Run `python3 modulus.py lsp` once to prepare both databases and the shared read-only header cache. Other editors can use `python3 modulus.py clangd` as their language-server command. Startup never downloads or builds anything, and never falls back to host clangd.
`tooling.lsp.clangd` configures the server executable, arguments, trusted compiler paths, and additional header roots. Product Vamp adds the bare-metal ARM compiler and `/opt/pico-sdk`; standard-library and SDK definitions open from an image-keyed cache under `$XDG_CACHE_HOME/modulus/clangd` (default `~/.cache/modulus/clangd`). Set `tooling.editor.nvim.enabled` to `false` for a hand-managed editor setup. Existing unowned `.nvim.lua` files are preserved.
## Package
Product packaging targets Raspberry Pi OS/Debian trixie on ARM64 and optionally builds Pico firmware. Set `PICO_SDK_PATH` when building the firmware artifact:
+8
View File
@@ -52,6 +52,14 @@
},
"lsp": {
"enabled": true,
"clangd": {
"query_drivers": [
"/usr/bin/gcc-12", "/usr/bin/g++-12",
"/usr/bin/aarch64-linux-gnu-gcc-12", "/usr/bin/aarch64-linux-gnu-g++-12",
"/usr/bin/arm-none-eabi-gcc", "/usr/bin/arm-none-eabi-g++"
],
"header_roots": ["/opt/pico-sdk"]
},
"compile_databases": [
{
"name": "pico",
+7 -14
View File
@@ -19,6 +19,7 @@ COMMANDS = (
"test",
"package",
"lsp",
"clangd",
"run",
)
COMMON_DIR = pathlib.Path("build") / "build_common"
@@ -60,6 +61,7 @@ def runtime_ready(root):
return (
(root / TOOLS_DIR / "configure.py").is_file()
and (root / TOOLS_DIR / "lsp.py").is_file()
and (root / TOOLS_DIR / "clangd.py").is_file()
and (root / TOOLS_DIR / "run.py").is_file()
and (root / RUNTIME_DIR / "modulus" / "cli.py").is_file()
and (root / RUNTIME_DIR / "modulus" / "export.py").is_file()
@@ -485,22 +487,14 @@ def run_package(argv):
def delegate(command, argv):
root = repo_root()
if command == "clangd":
if not runtime_ready(root):
print("Modulus clangd tooling is missing; run ./modulus.py configure first", file=sys.stderr)
return 1
else:
ensure_runtime(root)
sys.path.insert(0, str(root / RUNTIME_DIR))
import modulus.cli
original_image_available = modulus.cli.docker_image_available
def current_build_image(context):
if not original_image_available(context):
return False
inspected = subprocess.run(
["docker", "image", "inspect", context.docker_image, "--format",
'{{index .Config.Labels "org.khodo.product-vamp.build-requirements"}}'],
capture_output=True, text=True, check=False,
)
return inspected.returncode == 0 and inspected.stdout.strip() == build_requirements_digest()
modulus.cli.docker_image_available = current_build_image
original_docker_run = modulus.cli.docker_run
def docker_run_with_host_socket(context, command, docker_args=None, env_overrides=None):
@@ -521,7 +515,6 @@ def delegate(command, argv):
try:
return modulus.cli.main(command)
finally:
modulus.cli.docker_image_available = original_image_available
modulus.cli.docker_run = original_docker_run
os.chdir(previous_cwd)
sys.argv = previous_argv
-1
View File
@@ -9,7 +9,6 @@
#include <functional>
#include <future>
#include <iostream>
#include <iterator>
#include <memory>
#include <string>
#include <string_view>
+10 -10
View File
@@ -1,7 +1,6 @@
import hashlib
import importlib.util
from pathlib import Path
import subprocess
import sys
import types
import unittest
@@ -21,14 +20,15 @@ class BuildBootstrapTests(unittest.TestCase):
package = types.ModuleType('modulus')
cli = types.ModuleType('modulus.cli')
package.cli = cli
available, docker_run = Mock(return_value=True), Mock()
cli.docker_image_available, cli.docker_run = available, docker_run
cli.main = lambda command: cli.docker_image_available(types.SimpleNamespace(docker_image='test-image'))
for label, expected in [('',False), ('outdated',False), (digest,True)]:
result = subprocess.CompletedProcess([], 0, label+'\n', '')
with self.subTest(label=label), patch.dict(sys.modules, {'modulus':package, 'modulus.cli':cli}), \
patch.object(bootstrap, 'ensure_runtime'), patch.object(bootstrap.subprocess, 'run', return_value=result), \
docker_run = Mock()
cli.docker_run = docker_run
cli.main = Mock(return_value=0)
with patch.dict(sys.modules, {'modulus':package, 'modulus.cli':cli}), \
patch.object(bootstrap, 'ensure_runtime') as prepare, \
patch.object(bootstrap, 'runtime_ready', return_value=True), \
patch.object(sys, 'path', list(sys.path)):
self.assertEqual(bootstrap.delegate('configure', []), expected)
self.assertIs(cli.docker_image_available, available)
self.assertEqual(bootstrap.delegate('clangd', []), 0)
prepare.assert_not_called()
docker_run.assert_not_called()
cli.main.assert_called_once_with('clangd')
self.assertIs(cli.docker_run, docker_run)