# cudaq C++ API Code Development Guidelines

**Scope:** This document defines conventions for C++ API boundaries, naming, and
header organization for the `cudaq` project and the `cudaq` compiler
toolchain.

## 1. Goals

1. Provide definitions for the different levels of APIs developers or end users
may encounter.
2. Provide definitions for developer categories and how each category may
interact with the above APIs.
3. Make it obvious which APIs are supported for end users versus internal
development.

---

## 2. Developer Categories (and what they may use)

### 2.1 Users (e.g, Quantum algorithm developers)

- Do not contribute to changes to the `cudaq` codebase.
- 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.

### 2.2 Library developers (e.g., `cudaqx`)

- 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.

### 2.3 Hardware vendors and core developers

- Do contribute to changes to the `cudaq` codebase.
- May use:
  - **User API**
  - **Internal public module APIs**
  - **Module private APIs**

---

## 3. API Layers and Rules

We define three API layers as illustrated below:

1. **User API**
2. **Internal public module APIs**
3. **Internal private APIs**

```text
┌────────────────────────────────────────────────────────────────────┐
│ 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_internal::<module>::...  (module lowercase)      │
│             cudaq_internal::<module>::detail = private             │
│ 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_internal::<module>::detail          │
│ Naming:     unconstrained; keep consistent within module           │
└────────────────────────────────────────────────────────────────────┘
```

Each layer has rules for:

- include paths
- shipping requirements
- naming conventions
- namespace conventions
- compatibility expectations

### 3.1 User API (Public API)

#### 3.1.1 Definition

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.

#### 3.1.2 Headers and includes

- 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

#### 3.1.3 Namespaces

- 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.

#### 3.1.4 Naming style

- User API functions and objects use **snake_case**.
  - Examples: `sample_async`, `sample_results`

#### 3.1.5 Compatibility policy

- 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.

---

### 3.2 Internal Public Module APIs (Exported, not user-supported)

#### 3.2.1 Definition

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 `PUBLIC` headers/libraries).

These APIs often must be shipped because **user headers may include them**, and
`nvq++` must be able to find them.

#### 3.2.2 Header location and include prefix (recommendation)

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

#### 3.2.3 Shipping and visibility

- 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.

#### 3.2.4 Namespaces

- Declarations live under a module namespace nested in `cudaq_internal`:
  - `namespace cudaq_internal::<module_name> { ... }` where `<module_name>` is lowercase
    Examples: `cudaq_internal::compiler`, `cudaq_internal::device_code`
- Nested namespaces follow the same visibility convention: they are public
except for the `detail` namespace.

#### 3.2.5 Naming style

- 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.

#### 3.2.6 Compatibility expectations

- 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.

---

### 3.3 Internal Private APIs (Module-only)

#### 3.3.1 Definition

Internal private APIs are implementation details private to a module. They must
not be consumed outside the module.

#### 3.3.2 Header location and visibility

- Private headers live in a physical location separate from public headers
(e.g., a module `<module>/src/` or `include-private/` tree).
- They should **not** be in `nvq++` default/public include search paths.

#### 3.3.3 Shipping

- 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 `detail` namespace.

#### 3.3.4 Include rules

- Private headers are included using **relative paths** from within the module.

---

## 4. Practical Conventions and Examples

### 4.1 Include examples

**User code (supported):**

```cpp
#include "cudaq.h"
#include "cudaq/algorithms/run.h"
```

Internal developer code (allowed for hardware vendors/core developers):

```cpp
#include "cudaq_internal/compiler/lower.h"
#include "cudaq_internal/cudaq_fmt/Formatting.h"
```

Module private include (module-only):

```cpp
#include "LoweringPasses.h"   // relative to module source
```

### 4.2 Namespace examples

User API:

```cpp

namespace cudaq {
  void sample_async();

  namespace detail {
    // not public
  }
}
```

Internal module API:

```cpp
namespace cudaq_internal::compiler {
  class PassPipeline;

  namespace detail {
    // not public
  }
}
```

---

## 5. Physical file layout

### 5.1 Internal modules

Internal modules shall be laid out according to the following structure:

```text
runtime
   ├── internal
        ├── compiler
        │      ├── CMakeLists.txt
        │      ├── *.cpp
        │      ├── include/cudaq_internal/compiler/*.h
        ├── device_code
        │      ├── CMakeLists.txt
        │      ├── *.cpp
        │      ├── include/cudaq_internal/device_code/*.h
```

Most noticeably, header files shall not be under a common include root.
This is so that adding a dependency to a given module, using CMake `target_link_libraries`,
only gives visibility to the public headers of that module.

The concern for `nvq++` users is different. The expectation is that `nvq++` finds
automatically all the required headers, even those from internal modules
included transitively. We do not know ahead of time which headers will be used,
and we do not expect users to provide this information, so we have to assume
that all headers could be used.

CMake's `INSTALL_INTERFACE` and `BUILD_INTERFACE` will be leveraged to meet these
requirements. They allow for a different header file layout for build and install
environment.

Example:

```cmake
target_include_directories(cudaq-mlir-runtime
  PUBLIC
    $<INSTALL_INTERFACE:include>
    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/runtime/internal/compiler/include>
  PRIVATE .)
```

---

## 6. Additional conventions

This documented primarily aims at defining conventions on APIs and modules.
Of particular relevance are the following rules from the LLVM coding standard
that we shall strive to follow.

- [Use Namespace Qualifiers to Define Previously Declared Symbols](https://llvm.org/docs/CodingStandards.html#use-namespace-qualifiers-to-define-previously-declared-symbols)
- [Restrict Visibility](https://llvm.org/docs/CodingStandards.html#restrict-visibility)
