Skip to content

[build/docs] Define the supported build configuration model #1183

Description

@pcchen

[build/docs] Define the supported build configuration model

Summary

Recent work on the Pixi development environment has made Cytnx's build
architecture substantially clearer:

  • pixi.toml / pixi.lock provision a reproducible development toolchain and
    dependency environment;
  • Pixi tasks select configurations from CMakePresets.json rather than
    restating CMake build flags;
  • one Pixi environment can build multiple presets;
  • bare cmake --preset ... remains usable independently of Pixi.

In particular, #1140 proposed that CMakePresets.json remain the single source
of truth for build configuration, and merged PR #1150 implemented the
cross-platform Pixi development environment around that model.

What is still not stated explicitly is the support contract for those
configurations.

For example, it is currently unclear whether:

  1. some or all configurations represented by CMakePresets.json are the
    configurations Cytnx officially intends to support and maintain; or
  2. arbitrary combinations of individual CMake options such as USE_CUDA,
    USE_CUTENSOR, USE_CUQUANTUM, USE_MKL, and USE_HPTT are also part of
    the supported public build interface.

This issue proposes to define that policy explicitly before making a larger
revision of the installation documentation.

This is not a proposal to redesign the Pixi development environment.
Rather, it is intended to formalize the configuration-policy layer that the
recent Pixi/preset workflow now makes possible.


Motivation

1. The Pixi migration has converged on a clearer architecture

Before the Pixi work, development dependencies and build invocation were spread
across local setup instructions, CI workflows, packaging scripts, and manually
constructed CMake command lines.

Issue #1140 proposed a different separation of responsibilities:

  • Pixi provisions the development environment;
  • CMakePresets.json defines build configurations;
  • Pixi tasks invoke those presets without duplicating their CMake flags.

Merged PR #1150 implemented the cross-platform development environment using
this approach. The current contributor workflow now looks like:

pixi run test-cpp                     # openblas-cpu
pixi run test-cpp debug-mkl-cpu       # debug MKL
pixi run build openblas-cuda          # CUDA compile-check

The preset is a task argument, not a property of the Pixi environment. This is
important: Pixi answers which toolchain/dependencies are available, while the
preset answers which Cytnx build configuration is selected.

The remaining unanswered question is what the project means by a supported
configuration.

2. PR #1130 exposed the missing support policy

PR #1130 attempted to synchronize the installation guide with the then-current
CMake behavior, including CUDA, cuTENSOR, cuQuantum, dependency roots, and
installation-prefix information.

During review, @IvanaGyro raised a more fundamental concern:

I feel we should not teach users to manipulate CMAKE flags manually because
we don't guarantee that configuration will work. Maintaining so many
configurations cost too much time and resources, and it is easy to miss some
combinations.

She also noted that some settings in CMakeLists.txt exist for backward
compatibility, rather than necessarily defining the preferred user-facing
configuration interface.

Related discussion suggested that dependency discovery should preferably use
standard CMake mechanisms such as CMAKE_PREFIX_PATH, rather than making
project-specific root variables the normal installation interface.

PR #1130 was subsequently reverted in #1134.

The important lesson is that updating docs/source/adv_install.rst is not just
a matter of correcting stale option names or version numbers. We first need
agreement on what build configurations Cytnx intends to support and
document
.

3. CI still needs to validate the Pixi path

The Pixi migration also exposes a related verification gap.

Issue #1158 points out that no CI job currently exercises pixi.toml /
pixi.lock, so the development environment can become stale while the existing
CI remains green. Its proposed smoke path includes:

pixi lock --check
pixi install
pixi run test-cpp

This is related to, but distinct from, the policy proposed here:


Current configuration layers

The repository now has several layers with different responsibilities.

CMakePresets.json — build configuration definitions

The repository currently defines configurations such as:

  • openblas-cpu
  • mkl-cpu
  • openblas-cuda
  • mkl-cuda
  • Windows-specific CUDA presets
  • corresponding debug-* presets

For example, normal CUDA presets enable a coherent combination including:

USE_CUDA=ON
USE_CUTENSOR=ON
USE_CUQUANTUM=ON

while Windows CUDA presets intentionally modify that combination because of
platform-specific dependency availability.

This strongly suggests that presets encode combinations the project has chosen
deliberately. It does not, by itself, answer whether every public preset is
formally supported or what guarantee applies to configurations constructed
outside the presets.

pixi.toml / pixi.lock — reproducible development environment

Pixi now provisions the toolchain and native dependencies used for development
across the supported development platforms.

A single environment can build different CMake presets. pixi.toml therefore
should not become a second copy of the build configuration matrix; its role is
to provision dependencies and expose reproducible task entry points.

CONTRIBUTING.md — contributor workflow

The contributor workflow is already preset-oriented. Its "Choosing a preset"
section describes development builds in terms of CMakePresets.json, and Pixi
tasks accept a preset as their first argument.

AGENTS.md — operational build instructions

The build instructions use:

cmake --preset openblas-cpu
cmake --build --preset openblas-cpu

and describe individual CMake toggles as settings that are set by presets.

tests/README.md — test configuration

The test documentation explicitly recommends using a preset rather than a
manual -S/-B configuration because presets are what CI uses and keep the
configuration consistent.

docs/source/adv_install.rst — user installation documentation

In contrast, the user installation guide still presents many individual
-D... CMake options as if users are expected to construct build
configurations manually.

This is where the missing policy becomes user-visible: the documentation cannot
say which manual combinations are recommended or supported until that contract
is defined.


Proposed architecture

The intended separation could be expressed as:

                     BUILDING.md
                  support policy
                         |
                         v
                 CMakePresets.json
             build configuration set
                         |
              +----------+----------+
              |                     |
              v                     v
          pixi.toml             manual CMake
   reproducible dev env        cmake --preset
        + task entry                 |
              |                     |
              +----------+----------+
                         |
                         v
                        CI
                  verification

In this model:

  • BUILDING.md answers what Cytnx promises to support;
  • CMakePresets.json answers what coherent build configurations are
    defined
    ;
  • pixi.toml / pixi.lock answer what reproducible development environment
    is used to build them
    ;
  • CI answers which parts of that contract are continuously verified;
  • docs/source/adv_install.rst explains how users build/install using the
    supported model
    .

Questions to decide

1. What defines a supported build configuration?

Should supported source-build configurations be represented by named presets in
CMakePresets.json?

Possible policy:

A supported Cytnx source-build configuration should have an intentional CMake
preset describing the coherent combination of backend, accelerator,
dependency, and build options.

A separate question is whether every public preset is supported. For
example, some debug presets may be primarily developer/test configurations
rather than user-facing installation targets. We should state that distinction
rather than assume it.

2. What is the status of individual USE_* options?

For example:

  • USE_CUDA
  • USE_CUTENSOR
  • USE_CUQUANTUM
  • USE_MKL
  • USE_HPTT

Possible interpretations include:

A. Public supported interface

Any meaningful combination of these options is expected to work.

B. Advanced interface

The options remain usable, but preset-defined combinations are the
configurations the project routinely maintains and verifies.

C. Internal/backward-compatibility interface

Some options exist mainly because the implementation or older workflows depend
on them, and users should normally not construct arbitrary combinations
manually.

We should document which model applies, and it need not be identical for every
option.

3. What is Pixi's role in the support contract?

The recent development-environment work suggests the following division:

  • Pixi is the recommended, reproducible contributor/developer environment;
  • Pixi tasks call CMake presets and should not redefine their option sets;
  • bare cmake --preset ... remains a valid path for users or developers who
    provide dependencies themselves.

We should decide whether this is the intended long-term contract and document
it explicitly.

In particular, using Pixi and using a supported build configuration should
not be treated as the same concept
. A preset may be the supported
configuration definition even when the caller supplies its dependencies without
Pixi.

4. How should custom dependency locations be configured?

Should the preferred user-facing mechanism be standard CMake discovery, for
example:

cmake --preset openblas-cuda \
  -DCMAKE_PREFIX_PATH=/path/to/dependencies

rather than project-specific configuration such as:

-DCUTENSOR_ROOT=...
-DCUQUANTUM_ROOT=...

The latter may still need to exist for compatibility while the build system is
being cleaned up, but that does not necessarily mean they should be the
recommended installation interface.

This is related to #1129 and #1136.

5. What does "supported" mean?

It would be useful to define this explicitly.

For example, a supported configuration might mean that:

  • it has an intentional named CMake preset;
  • its dependency combination is intentionally maintained;
  • its relevant build/runtime path is covered by CI, compile-check, packaging,
    or release verification appropriate to that configuration;
  • documentation may recommend it to users;
  • regressions in that configuration are treated as project bugs.

This should not require every configuration to run in every CI workflow. CUDA,
platform-specific, packaging, and debug configurations may need different forms
of verification.

The purpose is to distinguish:

CMake happens to accept this combination

from:

Cytnx intends to maintain this configuration.

6. Where should the policy live?

Proposal: create a top-level BUILDING.md as the canonical
build/configuration contract.

Suggested documentation hierarchy:

BUILDING.md
  -> canonical build/configuration policy

CMakePresets.json
  -> executable configuration definitions

pixi.toml / pixi.lock
  -> reproducible development environment and task entry points

CONTRIBUTING.md
  -> contributor workflow, linking to BUILDING.md

docs/source/adv_install.rst
  -> user-facing installation instructions derived from the policy

CI / packaging workflows
  -> verification of supported configurations/workflows

BUILDING.md could contain:

# Building Cytnx

## Supported configuration model
## Supported presets
## Development environment and Pixi
## Platform support
## Dependency discovery
## Advanced/custom configurations
## CI and verification coverage
## Adding a new supported configuration

Proposed initial policy for discussion

The following wording could serve as a starting point, but this issue is meant
to reach agreement rather than assume the answer:

Cytnx defines coherent source-build configurations through
CMakePresets.json. Users and contributors should normally select an
appropriate preset rather than construct arbitrary combinations of low-level
CMake options. Individual USE_* options may remain available for
implementation, development, advanced use, or backward compatibility, but
combinations outside the configurations the project explicitly supports are
not necessarily tested or maintained.

Pixi provides the reproducible development toolchain and task entry points;
it does not independently define the build configuration matrix. Pixi tasks
should invoke the same CMake presets that can also be used by a manual
cmake --preset ... workflow.

We still need to decide which presets are considered supported user
configurations, developer/test configurations, or platform-specific internal
variants.

If this policy is too restrictive, we should define a broader contract
explicitly instead.


Relationship to existing issues / PRs

This issue is intended to define policy, not replace existing implementation
issues.

Related work includes:

The outcome of this issue should guide documentation changes associated with
those items, while #1158 and other focused implementation issues can improve
verification independently.


Proposed next steps

  1. Agree on the supported configuration model in this issue.
  2. Decide which presets are user-supported, developer/test-only, or
    platform-specific variants.
  3. Add a small top-level BUILDING.md recording the agreed policy and the
    separation between presets, Pixi, and manual CMake use.
  4. Link to BUILDING.md from CONTRIBUTING.md rather than duplicating the
    policy there.
  5. Update docs/source/adv_install.rst so user installation instructions are
    preset-oriented and follow the agreed support contract.
  6. Continue No CI job exercises pixi.toml, so the development environment can rot silently #1158 (or equivalent CI work) so the Pixi development path cannot
    silently drift from the repository configuration.
  7. Where current CMake behavior conflicts with the agreed model, track those
    discrepancies as separate, focused build-system issues/PRs.

The goal is to avoid having documentation, Pixi tasks, or individual CMake
flags independently define build policy. They should all reflect one explicit
configuration contract agreed by the maintainers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions