Welcome to NIXL! This document provides guidelines for contributing to our modern C++17 project. Please read through these guidelines carefully before submitting your contribution.
- Getting Started
- Development Environment
- Code Standards
- Contributing Process
- Plugin Development
- Testing Requirements
- Documentation Standards
- Pull Request Guidelines
- Miscelaneous
- Developer Certificate of Origin
Before contributing, please:
- Review existing issues and PRs to avoid duplicate work
- For significant changes, open an issue for discussion before implementation
- Familiarize yourself with our code style and project structure
- Set up your development environment according to our guidelines
- C++17 compatible compiler
- Meson build system
- Ninja build tool
- clang-format
- Python (for build scripts and testing)
- Git with DCO sign-off configured
NIXL uses Meson and Ninja for building:
# Configure the build
meson setup build
# Build the project
ninja -C build
# Run tests
ninja -C build testAll new C++ code must be formatted using the provided .clang-format configuration. Code formatting will be automatically checked for conformance in CI, and improperly formatted code will be rejected:
# Format only changed lines in staged files (recommended)
git clang-format
# Format only changed lines between commits
git clang-format HEAD~1
# Format only changed lines in specific files
git clang-format --diff path/to/file.cpp
# Alternative: Use clang-format-diff to format only changed lines
git diff -U0 --no-color HEAD^ | clang-format-diff -p1 -i
# Or format only unstaged changes
git diff -U0 --no-color | clang-format-diff -p1 -iThe project uses pre-commit hooks for Python code quality. Install them with:
pip install pre-commit
pre-commit installNIXL is a modern C++17 project. We adhere to the C++ Core Guidelines where appropriate. Key principles:
- Use modern C++ features: Prefer
auto, range-based loops, structured bindings,std::optional, etc. - RAII everywhere: Resource management through constructors/destructors
- Smart pointers for ownership: Use
std::unique_ptr,std::shared_ptrappropriately - Prefer
constcorrectness: Mark methods and variablesconstwhen appropriate - Exception handling: Exceptions are recommended for control-path code, while error codes should be used for data-path
-
Prefer STL types: Use rich STL types as the primary choice
- Standard containers:
std::vector,std::unordered_map, etc. - Modern utilities:
std::optional,std::variant,std::string_view - Algorithms from
<algorithm>and<numeric>
- Standard containers:
-
Fallback to Abseil: When STL lacks required functionality
- String formatting:
absl::StrFormat - Error handling:
absl::StatusOrfor data-path operations that return values with potential errors - High-performance containers:
absl::flat_hash_mapwhen needed - Logging utilities (integrated with NIXL logging)
- String formatting:
-
⚠️ WARNING: Never expose Abseil in public APIs- Keep Abseil types internal to implementation files
- Plugin and agent public APIs must only use STL types
- Convert between Abseil and STL types at API boundaries
All code must adhere to the style guide in docs/CodeStyle.md and be formatted with .clang-format. Key points:
- Follow the existing code style in the file/module you're modifying
- Use descriptive names for variables, functions, and classes
- Document complex logic with clear comments, but avoid redundant self-explanatory comments that don't add value
- Prefer clarity over cleverness
-
Control-path code: Use exceptions for exceptional conditions
std::runtime_errorfor runtime failuresstd::invalid_argumentfor invalid parameters- Custom exceptions when appropriate
-
Data-path code: Use error codes for performance-critical paths
- Return
nixl_status_tor similar error codes - Avoid exceptions in hot paths
- Return
-
Logging: Use NIXL logging macros
NIXL_ERROR: Critical errors that prevent normal operation- System failures, resource exhaustion, unrecoverable errors
- Failed operations that cannot continue
NIXL_WARN: Warning conditions that don't prevent operation but indicate problems- Deprecated API usage, performance degradation, recoverable errors
- Fallback behavior, suboptimal configurations
NIXL_INFO: Informational messages about normal operation- Initialization complete, configuration loaded, major state changes
- Connection established/closed, module lifecycle events
NIXL_DEBUG: Detailed debugging information for development- Function entry/exit, intermediate values, algorithm decisions
- Variable states, decision branches, detailed flow information
NIXL_TRACE: Very detailed trace information for deep debugging- Per-packet processing, memory allocations, lock acquisitions
- Low-level operations, fine-grained timing, verbose diagnostics
Contributions to the code under ./examples/device/ep (which is derived
from DeepEP and licensed under the MIT License) must be licensed under Apache
2.0.
Contributions that fix documentation errors or that make small changes to existing code can be contributed directly by following the rules below and submitting an appropriate PR.
Contributions intended to add significant new functionality must follow a more collaborative path described in the following points. Before submitting a large PR that adds a major enhancement or extension, be sure to submit a GitHub issue that describes the proposed change so that the NIXL team can provide feedback.
-
As part of the GitHub issue discussion, a design for your change will be agreed upon. An up-front design discussion is required to ensure that your enhancement is done in a manner that is consistent with NIXL's overall architecture.
-
Testing is a critical part of any NIXL enhancement. You should plan on spending significant time on creating tests for your change. The NIXL team will help you to design your testing so that it is compatible with existing testing infrastructure.
-
If your enhancement provides a user visible feature then you need to provide documentation.
We greatly appreciate all contributions to NIXL! To maintain the high quality, performance, and security standards that our users depend on, we have a thorough review process. Here's what to expect:
- Initial review typically takes 1-2 weeks depending on PR complexity and reviewer availability
- Most PRs require 2-4 rounds of review before merging
- Complex features may take longer as we ensure architectural consistency
- NIXL is used in performance-critical environments where reliability is paramount
- We maintain backward compatibility and stable APIs for our users
- Security and correctness are non-negotiable in data movement operations
- We aim for code that is maintainable by the community long-term
- Reviewers provide detailed feedback to help improve the contribution
- We're here to collaborate, not just critique - ask questions if feedback is unclear
- For significant changes, we may suggest incremental PRs to make review easier
- The team will help ensure your contribution aligns with NIXL's architecture
- Start with smaller PRs to familiarize yourself with our standards
- Engage early through issues for design discussions
- Be responsive to feedback and ask for clarification when needed
- Consider breaking large changes into logical, reviewable chunks
We recognize that our standards are high, but this ensures NIXL remains a reliable foundation for critical workloads. Your patience and collaboration through the review process is genuinely appreciated, and we're committed to helping your contribution succeed.
When contributing new plugins, follow these guidelines:
Plugins are located in src/plugins/. Your plugin should follow this structure:
src/plugins/your_plugin/
├── meson.build
├── your_plugin.cpp
├── your_plugin.h
├── your_backend.cpp
├── your_backend.h
└── README.md
Tests should be added in the GoogleTest-based test directory:
test/gtest/unit/plugins/your_plugin/
└── test_your_plugin.cpp
Create a meson.build file for your plugin. If your plugin requires external dependencies:
# Check for required dependency
your_dep = dependency('your-dependency', required: false)
if not your_dep.found()
subdir_done() # Skip building this plugin
endif
# Build the plugin
your_plugin_lib = shared_library(
'YOUR_PLUGIN',
your_sources,
dependencies: plugin_deps + [your_dep],
cpp_args: compile_defs + ['-fPIC'],
include_directories: [nixl_inc_dirs, utils_inc_dirs],
install: true,
name_prefix: 'libplugin_',
install_dir: plugin_install_dir)If your plugin requires system dependencies, update contrib/Dockerfile. See existing examples for compiling dependencies from source:
# Example: Building a dependency from source
WORKDIR /workspace
RUN git clone https://github.com/example/your-dependency.git && \
cd your-dependency && \
mkdir build && cd build && \
cmake .. && \
make -j$(nproc) && \
make install
# Or for autotools-based projects:
RUN cd /usr/local/src && \
git clone https://github.com/example/your-lib.git && \
cd your-lib && \
./autogen.sh && \
./configure --enable-feature && \
make -j && \
make install && \
ldconfigYour plugin's README.md must include:
- Overview: Basic functionality description
- Dependencies: List all external requirements
- Build Instructions: How to build with/without the plugin
- API Reference: Key classes and functions
- Example Usage: Simple, working example
- Unit tests: Test individual components in
test/gtest/unit/plugins/your_plugin/ - Integration tests: Test plugin with NIXL framework
- Example validation: Ensure examples compile and run
- New tests should use GoogleTest framework in
test/gtest/ - Legacy tests may exist in other locations
- Run tests with:
ninja -C build test
- New features must include comprehensive tests
- Bug fixes must include regression tests
- Test both success and error paths
// Example unit test
TEST(YourPlugin, HandlesValidInput) {
// Test implementation
}
TEST(YourPlugin, HandlesInvalidInput) {
// Test error handling
}Document public APIs and complex implementations:
/**
* Brief description of the function
*
* Detailed explanation if needed
*
* @param param1 Description of parameter
* @return Description of return value
*/Use the provided template in .github/pull_request_template.md:
- What?: Clear description of changes
- Why?: Justification and issue references
- How?: Technical approach for complex changes
Please review the Review Process Expectations section to understand our thorough review process and timeline.
- Code follows style guidelines (
.clang-formatapplied) - Follows conventions in
docs/CodeStyle.md - All tests pass
- New tests added for new functionality
- Documentation updated where needed
- PR template filled out completely
- Commits are signed with DCO
component: Brief description of change
Longer explanation of the change, its motivation, and impact.
Fixes #123
Signed-off-by: Your Name <your.email@example.com>
-
NIXL's default build assumes recent versions of dependencies (CUDA, PyTorch, etc.). Contributions that add compatibility with older versions of those dependencies will be considered, but NVIDIA cannot guarantee that all possible build configurations work, are not broken by future contributions, and retain highest performance.
-
Make sure that you can contribute your work to open source (no license and/or patent conflict is introduced by your code). You must certify compliance with the license terms and sign off on the Developer Certificate of Origin (DCO) described below before your pull request (PR) can be merged.
-
Thanks in advance for your patience as we review your contributions; we do appreciate them!
NIXL is an open source product released under the Apache 2.0 license (see either the Apache site or the LICENSE file). The Apache 2.0 license allows you to freely use, modify, distribute, and sell your own products that include Apache 2.0 licensed software.
We respect intellectual property rights of others and we want to make sure all incoming contributions are correctly attributed and licensed. A Developer Certificate of Origin (DCO) is a lightweight mechanism to do that.
The DCO is a declaration attached to every contribution made by
every developer. In the commit message of the contribution,
the developer simply adds a Signed-off-by statement and thereby
agrees to the DCO, which you can find below or at DeveloperCertificate.org.
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
We require that every contribution to NIXL is signed with a Developer Certificate of Origin. Additionally, please use your real name. We do not accept anonymous contributors nor those utilizing pseudonyms.
Each commit must include a DCO which looks like this
Signed-off-by: Jane Smith <jane.smith@email.com>
You may type this line on your own when writing your commit messages.
However, if your user.name and user.email are set in your git configs,
you can use -s or --signoff to add the Signed-off-by line to
the end of the commit message.