Skip to content

Latest commit

 

History

History
243 lines (180 loc) · 7.65 KB

File metadata and controls

243 lines (180 loc) · 7.65 KB

Getting Started with Developing CUDA-Q

This document contains guidelines for contributing to the code in this repository. This document is relevant primarily for contributions to the nvq++ compiler, the CUDA-Q runtime, or to the integrated simulation backends. If you would like to contribute applications and examples that use the CUDA-Q platform, please follow the instructions for installing CUDA-Q instead.

Quick start guide

Before getting started with development, please create a fork of this repository if you haven't done so already and make sure to check out the latest version on the main branch. After following the instruction for setting up your development environment and building CUDA-Q from source, you should be able to confirm that you can run the tests and examples using your local build. If you edit this file to add a print statement

std::cout << "Custom registration of " << #PRINTED_NAME << "\n" << std::endl;

to the definition of the NVQIR_REGISTER_SIMULATOR macro, you should see this line printed when you build the code and run an example using the command

bash "$CUDAQ_REPO_ROOT/scripts/build_cudaq.sh" && \
nvq++ "$CUDAQ_REPO_ROOT/docs/sphinx/applications/cpp/grover.cpp" -o grover.out && \
./grover.out
# Build with specific options - verbose, debug build, run 8 jobs in parallel
bash "$CUDAQ_REPO_ROOT/scripts/build_cudaq.sh" -v -c Debug -j 8

Incremental Rebuilds After making changes, you can rebuild specific components without rebuilding everything:

cd "$CUDAQ_REPO_ROOT/build"
# Rebuild - faster than full build from scratch
ninja
# Rebuild specific component
ninja <target>

When working on compiler internals, it can be useful to look at intermediate representations for CUDA-Q kernels.

To see how the kernels in this example are translated, you can run

cudaq-quake $CUDAQ_REPO_ROOT/docs/sphinx/applications/cpp/grover.cpp

to see its representation in the Quake MLIR dialect. To see its translation to QIR, you can run

cudaq-quake $CUDAQ_REPO_ROOT/docs/sphinx/applications/cpp/grover.cpp |
cudaq-opt --canonicalize --add-dealloc |
quake-translate --convert-to=qir

Code style

With regards to code format and style, we distinguish public APIs and CUDA-Q internals. Public APIs should follow the style guide of the respective language, specifically this guide for C++, and the this guide for Python. The CUDA-Q internals on the other hand follow the MLIR/LLVM style guide. Please ensure that your code includes comprehensive doc comments as well as a comment at the top of the file to indicating its purpose.

Automated Code Quality Checks with Pre-commit (Recommended)

We use pre-commit hooks to automatically check code formatting, style, and common issues. This allows you to run the same checks locally that run in CI, catching issues before you push.

Benefits:

  • Catch formatting and linting issues locally before CI runs
  • Same checks run locally and in CI (guaranteed consistency)
  • Automatic formatting fixes where possible
  • Fast incremental checks (only checks changed files)

Prerequisites

Most formatting and linting checks work out-of-the-box with pre-commit. However, some checks require system dependencies:

  • aspell: for spell checking
  • node/npm: for link validation
  • go: for license header validation (the license-eye tool will be auto-installed)
# Ubuntu/Debian
sudo apt-get install aspell aspell-en nodejs npm golang

# macOS
brew install aspell node go

# Fedora/RHEL
sudo dnf install aspell aspell-en nodejs npm golang

# All platforms: Install markdown-link-check globally
npm install -g markdown-link-check

Installation (One-time Setup)

Devcontainer Users: If you're developing in the VS Code devcontainer, pre-commit and all required dependencies (Node.js, Go, aspell) are pre-installed. You only need to run pre-commit install to enable the hooks.

pip install pre-commit
pre-commit install  # Enable hooks for this repository

Usage

Automatic (if installed): Pre-commit hooks run automatically when you commit or push. Fast checks (formatting, linting) run on commit. All checks including spell checking run on push.

git add <files>
git commit -m "Your message"  # Fast formatting checks run
git push  # All checks including spell checking run

Manual:

# Run on staged files only
pre-commit run

# Run on all files (fast hooks only)
pre-commit run --all-files

# Run all hooks including slow ones (spell check, link validation)
pre-commit run --all-files --hook-stage pre-push

# Run a specific hook
pre-commit run clang-format --all-files
pre-commit run yapf --all-files

Bypass (emergency only):

git commit --no-verify  # Skip pre-commit hooks

What Gets Checked

Fast checks (run on commit):

  • C++ formatting (clang-format-16)
  • Python formatting (yapf with Google style)
  • Markdown linting
  • Trailing whitespace, end-of-file fixes
  • Large files, merge conflicts

All checks (run on push):

  • License header validation
  • Spell checking (Markdown, .rst, C++, Python)
  • Link validation in markdown files

Troubleshooting

Hook fails: Read the error message carefully. Most formatting hooks will show a diff of required changes. Fix the issue and try committing again.

Tool not found: If a hook complains about a missing tool:

  1. Check if it's a system dependency (aspell, markdown-link-check, Go) - see Prerequisites section above
  2. For pre-commit-managed tools, run:
pre-commit install-hooks  # Reinstalls all hook dependencies

Cache issues: If hooks behave unexpectedly, try clearing the cache:

pre-commit clean  # Clear cached hook environments
pre-commit run --all-files  # Rebuild cache

CI Integration

All checks that run in CI can be run locally using pre-commit. This reduces CI churn from formatting and linting failures. When you push code, the same pre-commit configuration runs in GitHub Actions, ensuring consistency.

Testing and debugging

CUDA-Q tests are categorized as unit tests on runtime library code and FileCheck tests on compiler code output. All code added under the runtime libraries should have an accompanying test added to the appropriate spot in the unittests folder. All code that directly impacts compiler code should have an accompanying FileCheck test. These tests are located in the test folder.

C++ tests

cd "$CUDAQ_REPO_ROOT/build"
ctest
# To run a specific test
ctest -R <test-name>

Python tests

python3 -m pytest -v python/tests/ --ignore python/tests/backends
for backendTest in python/tests/backends/*.py; do python3 -m pytest -v $backendTest; done

When running a CUDA-Q executable locally, the verbosity of the output can be configured by setting the CUDAQ_LOG_LEVEL environment variable. Setting its value to info will enable printing of informational messages, and setting its value to trace generates additional messages to trace the execution. These logs can be directed to a file by setting the CUDAQ_LOG_FILE variable when invoking the executable, e.g.

CUDAQ_LOG_FILE=grover_log.txt CUDAQ_LOG_LEVEL=info grover.out