Rix is the official package layer for Vix.cpp Browse packages
Skip to content

Debug Quick Start

This page shows the fastest way to use rix/debug.

The examples use the public Rix facade:

cpp
#include <rix.hpp>

and access Debug through:

cpp
rix.debug

rix/debug is useful for examples, quick tools, local diagnostics, and development-time output.

For production application logs, prefer the Vix logging system.

What you will build

You will create a small C++ file that:

txt
prints values
prints an error message
formats a string
stores printed output in a string
inspects a value
runs with vix run

Create a working folder

Create a small folder in your home directory:

bash
mkdir -p ~/rix-debug-quick-start
cd ~/rix-debug-quick-start
touch debug.cpp

Add the example

Open:

txt
debug.cpp

Add:

cpp
#include <rix.hpp>

#include <string>

int main()
{
  rix.debug.print("== rix/debug quick start ==");

  rix.debug.print("Hello", "Rix");
  rix.debug.print("rows:", 3);
  rix.debug.print("ready:", true);

  const std::string package =
      rix.debug.format("Package: {}", "rix/debug");

  rix.debug.print(package);

  const std::string line =
      rix.debug.sprint("generated line:", package);

  rix.debug.print(line);

  rix.debug.eprint("stderr example:", "this is an error-style message");

  rix.debug.inspect(package);

  return 0;
}

Run the file

Run:

bash
vix run debug.cpp

If Rix is not available yet for single-file usage:

bash
vix install -g rix/rix
vix run debug.cpp

Expected output

The output should look similar to this:

txt
== rix/debug quick start ==
Hello Rix
rows: 3
ready: true
Package: rix/debug
generated line: Package: rix/debug

The eprint output is written to stderr.

The exact inspect output depends on the inspected value.

Use:

cpp
rix.debug.print(...)

Example:

cpp
rix.debug.print("Hello", "Rix");
rix.debug.print("count:", 3);
rix.debug.print("ok:", true);

print writes values separated by spaces and adds a newline.

This is the most common rix/debug helper.

Use:

cpp
rix.debug.eprint(...)

Example:

cpp
rix.debug.eprint("error:", "something failed");

eprint writes to stderr.

Use it for examples, local diagnostics, and command-line tools.

Debug-only print

Use:

cpp
rix.debug.dprint(...)

Example:

cpp
rix.debug.dprint("debug value:", 42);

Use this when the message is only useful while debugging.

Format a string

Use:

cpp
rix.debug.format(...)

Example:

cpp
const auto message =
    rix.debug.format("Package: {}", "rix/debug");

rix.debug.print(message);

Output:

txt
Package: rix/debug

Automatic placeholders

Use {} to insert arguments in order:

cpp
const auto message =
    rix.debug.format("{} uses {}", "Rix", "C++");

Result:

txt
Rix uses C++

Explicit placeholders

Use {0}, {1}, and other indexes when you want explicit argument positions:

cpp
const auto message =
    rix.debug.format("{0} + {0} = {1}", "C++", "Vix.cpp");

Result:

txt
C++ + C++ = Vix.cpp

Do not mix automatic placeholders and explicit placeholders in the same format string.

Escape braces

Use double opening braces and double closing braces when you need literal braces:

cpp
const auto message =
    rix.debug.format("{{ package }} = {}", "rix/debug");

Result:

txt
{ package } = rix/debug

Unsupported format specifiers

rix.debug.format is intentionally small.

It does not support format specifiers such as:

txt
{:.2f}
{:>10}
{:04d}

Use simple placeholders.

For advanced formatting, use another formatting library or normal C++ formatting tools where appropriate.

Append formatted output

You can append formatted text to an existing string:

cpp
std::string out = "Rix: ";

rix.debug.format.append(
    out,
    "{}",
    "debug");

rix.debug.print(out);

Expected output:

txt
Rix: debug

Replace a string with formatted output

Use:

cpp
std::string out;

rix.debug.format.to(
    out,
    "Package: {}",
    "rix/debug");

rix.debug.print(out);

Expected output:

txt
Package: rix/debug

Sprint values into a string

Use:

cpp
rix.debug.sprint(...)

when you want the same value rendering as print, but returned as a string.

Example:

cpp
const auto line =
    rix.debug.sprint("rows:", 3);

rix.debug.print(line);

This is useful when you want to build a message before printing it.

Inspect a value

Use:

cpp
rix.debug.inspect(value);

Example:

cpp
std::string package = "rix/debug";

rix.debug.inspect(package);

Inspection is useful when you want a clearer development-time view of a value.

Complete formatting example

cpp
#include <rix.hpp>

#include <string>

int main()
{
  const auto one =
      rix.debug.format("Hello, {}", "Ada");

  const auto two =
      rix.debug.format("{0} builds on {1}", "Rix", "Vix.cpp");

  const auto three =
      rix.debug.format("{{ module }} = {}", "debug");

  rix.debug.print(one);
  rix.debug.print(two);
  rix.debug.print(three);

  return 0;
}

Run:

bash
vix run debug.cpp

Expected output:

txt
Hello, Ada
Rix builds on Vix.cpp
{ module } = debug

Use in a Vix project

Create a Vix application:

bash
vix new debug-app --app
cd debug-app

Add Rix:

bash
vix add rix/rix
vix install

In vix.app, make sure Rix is listed under deps:

txt
deps = [
  "rix/rix",
]

A small vix.app can look like this:

txt
name = "debug-app"
type = "executable"
standard = "c++20"
output_dir = "bin"

sources = [
  "src/main.cpp",
]

include_dirs = [
  "include",
  "src",
]

deps = [
  "rix/rix",
]

packages = [
  "vix",
]

links = [
  "vix::vix",
]

Then use Debug in src/main.cpp:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello", "Rix");

  const auto message =
      rix.debug.format("Package: {}", "rix/debug");

  rix.debug.print(message);

  return 0;
}

Build and run:

bash
vix build
vix run

Single-file usage

For small scripts, examples, and experiments, use:

bash
vix run debug.cpp

If Rix is installed globally for single-file usage:

bash
vix install -g rix/rix
vix run debug.cpp

For project usage, prefer:

bash
vix add rix/rix
vix install

and keep the dependency in vix.app:

txt
deps = [
  "rix/rix",
]

Use only Debug with the facade

If you want the rix.* facade style but only want Debug mounted, define the feature macro before including rix.hpp:

cpp
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello", "Rix");
  return 0;
}

When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.

This is useful for lighter builds.

Use the independent package

For independent usage, install:

bash
vix add rix/debug
vix install

In vix.app:

txt
deps = [
  "rix/debug",
]

Then include the independent package header:

cpp
#include <rix/debug.hpp>

Use this style when a project only needs Debug and does not need the full unified Rix facade.

For most application documentation, prefer:

cpp
#include <rix.hpp>

Debug with CSV

Debug is useful for printing parsed CSV data:

cpp
const auto table = rix.csv.parse(
    "name,language\n"
    "Ada,C++\n");

rix.debug.print("rows:", table.size());

for (const auto &row : table)
{
  rix.debug.print("fields:", row.size());
}

Debug with Auth

Debug is useful for examples that show Auth results:

cpp
auto auth = rix.auth.memory();

auto registered = auth.register_user({
    "ada@example.com",
    "correct-password"});

if (registered.failed())
{
  const auto &error = registered.error();

  rix.debug.eprint(
      "auth error:",
      rix.auth.error.to_string(error),
      error.message());

  return 1;
}

rix.debug.print("registered:", registered.value().email());

Do not print authentication secrets in production.

Avoid printing:

txt
plain-text passwords
password hashes
session ids
raw token values

Debug with PDF

Debug is useful for checking whether a PDF was created:

cpp
auto doc = rix.pdf.document();

auto &page = doc.add_page();

page.text(
    page.x_left(),
    page.y_top(),
    "Hello from rix.pdf");

auto saved = rix.pdf.save(doc, "example.pdf");

if (saved.failed())
{
  rix.debug.eprint(
      "pdf error:",
      rix.pdf.error.to_string(saved.error()),
      saved.error().message());

  return 1;
}

rix.debug.print("created:", "example.pdf");

Logging note

rix/debug is not the main production logging API.

Use rix.debug.print, rix.debug.eprint, rix.debug.dprint, rix.debug.format, and rix.debug.inspect for development output and documentation examples.

For real application logs, prefer the Vix logging system.

Use this rule:

txt
rix.debug -> examples, local diagnostics, quick tools
Vix logging -> production logs, service logs, request logs

Common mistakes

Using debug output as production logging

rix.debug is for simple development output.

For real application logs, use the Vix logging system.

Printing secrets

Do not print:

txt
plain-text passwords
password hashes
session ids
raw token values

This matters especially when using rix/auth.

Mixing placeholder styles

Wrong:

cpp
rix.debug.format("{} {0}", "Rix");

Use automatic placeholders:

cpp
rix.debug.format("{} {}", "Rix", "Debug");

or explicit placeholders:

cpp
rix.debug.format("{0} {1}", "Rix", "Debug");

Expecting advanced format specifiers

Wrong:

cpp
rix.debug.format("{:.2f}", 3.14159);

Use simple placeholders:

cpp
rix.debug.format("value: {}", 3.14159);

Forgetting deps

For a Vix project, do not put Rix packages in packages.

Use:

txt
deps = [
  "rix/rix",
]

packages is for CMake package discovery.

deps is for Vix Registry packages.

What you should remember

Use the facade:

cpp
#include <rix.hpp>

Print values:

cpp
rix.debug.print("Hello", "Rix");

Print to stderr:

cpp
rix.debug.eprint("error:", "message");

Format strings:

cpp
auto message = rix.debug.format("Package: {}", "rix/debug");

Build printed output as a string:

cpp
auto line = rix.debug.sprint("rows:", 3);

Inspect values:

cpp
rix.debug.inspect(message);

For a Vix project, install Rix:

bash
vix add rix/rix
vix install

and use:

txt
deps = [
  "rix/rix",
]

Use rix.debug for examples and development output.

Prefer Vix logging for real application logs.

Next step

Learn the printing helpers.

Next: Printing

Released under the MIT License.