Scope: This document defines conventions for C++ API boundaries, naming, and
header organization for the cudaq project and the cudaq compiler
toolchain.
- Provide definitions for the different levels of APIs developers or end users may encounter.
- Provide definitions for developer categories and how each category may interact with the above APIs.
- Make it obvious which APIs are supported for end users versus internal development.
- Do not contribute to changes to the
cudaqcodebase. - Use only the User API shipped with the product.
- Compile and link to shipped runtime libraries with
nvq++ - Must not rely on internal headers/namespaces.
- Same restrictions as users: build on top of the User API only.
- May consume the API via
nvq++or by importing public headers/libraries into their own CMake project.
- Do contribute to changes to the
cudaqcodebase. - May use:
- User API
- Internal public module APIs
- Module private APIs
We define three API layers as illustrated below:
- User API
- Internal public module APIs
- Internal private APIs
┌────────────────────────────────────────────────────────────────────┐
│ Level 1: User API │
├────────────────────────────────────────────────────────────────────┤
│ Audience: Users, external libs (e.g., cudaqx) │
│ Headers: "cudaq.h", "cudaq/<subsystem>/<header>.h" │
│ Namespace: cudaq::... │
│ cudaq::detail = explicitly NON-public │
│ Naming: snake_case │
└────────────────────────────────────────────────────────────────────┘
▲
│ may include (transitively) when needed
│
┌────────────────────────────────────────────────────────────────────┐
│ Level 2: Internal Public Module APIs |
├────────────────────────────────────────────────────────────────────┤
│ Audience: Hardware vendors + core developers │
│ (NOT for users / external libs to depend on) │
│ Headers: "cudaq_internal/<module>/<hdr>.h" (or cudaq_dev/...) │
│ Namespace: cudaq::<module>::... (module lowercase) │
│ cudaq::<module>::detail = NON-public │
│ Naming: CamelCase (or consistent module convention) │
└────────────────────────────────────────────────────────────────────┘
▲
│ internal-only use
│
┌────────────────────────────────────────────────────────────────────┐
│ Level 3: Internal Private APIs │
├────────────────────────────────────────────────────────────────────┤
│ Audience: Module implementers only │
│ Headers: module-local (e.g., <module>/src/, include-private/) │
│ Namespace: typically in cudaq::<module>::detail (recommended) │
│ Naming: unconstrained; keep consistent within module │
└────────────────────────────────────────────────────────────────────┘
Each layer has rules for:
- include paths
- shipping requirements
- naming conventions
- namespace conventions
- compatibility expectations
The User API is cudaq supported public interface. It is the only API that
users and external libraries (e.g., cudaqx) are allowed to depend on.
- Primary entry header:
#include "cudaq.h"
- Additional user headers:
#include "cudaq/<subsystem>/<header>.h"- Example:
#include "cudaq/algorithms/run.h"
- File naming:
- lowercase file names
- All user-visible declarations live in
namespace cudaq { ... }. - Nested namespaces are considered public except:
cudaq::detail
Anything in detail is explicitly non-public and may change without notice.
- User API functions and objects use snake_case.
- Examples:
sample_async,sample_results
- Examples:
- The User API must maintain backward compatibility when feasible.
- Breaking changes require:
- a documented deprecation plan (deprecation schedule),
- migration guidance,
- and appropriate versioning/release notes.
Internal public module APIs are:
- not supported for end users, but
- public to internal developers because they are exported as part of a
module interface (e.g., via CMake
PUBLICheaders/libraries).
These APIs often must be shipped because user headers may include them, and
nvq++ must be able to find them.
Internal public headers must not live under the cudaq/ include root to
avoid confusion with the User API.
Proposed convention:
#include "cudaq_internal/<module_name>/<header_name>.h"
Rationale:
- clearly signals “not for users”
- avoids collision with user include hierarchy
- These headers are shipped with the product if they are reachable from
shipped user headers as required by
nvq++compilation. - They must be discoverable by
nvq++through configured include paths.
- Declarations live under a module namespace nested in
cudaq:namespace cudaq::<module_name> { ... }where<module_name>is lowercase Examples:cudaq::compiler,cudaq::cudaq_fmt
- Nested namespaces follow the same visibility convention: they are public
except for the
detailnamespace.
- Preferred style for internal module APIs:
CamelCase. - If a specific module already has a strong existing convention, follow it consistently; avoid introducing new naming styles within the same module.
- Internal public module APIs are not user-stable.
- They may evolve as needed, but changes should still be managed responsibly
because:
- Hardware vendors and internal developers may depend on them,
- user headers may indirectly rely on them.
Internal private APIs are implementation details private to a module. They must not be consumed outside the module.
- Private headers live in a physical location separate from public headers
(e.g., a module
<module>/src/orinclude-private/tree). - They should not be in
nvq++default/public include search paths.
- Private headers are not shipped with the product with the exception of
header based implementation such as template meta-programming. In which case,
private APIs shall be in the
detailnamespace.
- Private headers are included using relative paths from within the module.
User code (supported):
#include "cudaq.h"
#include "cudaq/algorithms/run.h"Internal developer code (allowed for hardware vendors/core developers):
#include "cudaq_internal/compiler/lower.h"
#include "cudaq_internal/cudaq_fmt/Formatting.h"Module private include (module-only):
#include "LoweringPasses.h" // relative to module sourceUser API:
namespace cudaq {
void sample_async();
namespace detail {
// not public
}
}Internal module API:
namespace cudaq::compiler {
class PassPipeline;
namespace detail {
// not public
}
}