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

Feature Macros

Feature macros let you choose which Rix packages are mounted into the unified facade.

By default, this works:

cpp
#include <rix.hpp>

and exposes the available facade modules:

cpp
rix.auth
rix.csv
rix.debug
rix.pdf

For smaller builds, define only the modules you want before including rix.hpp.

Why feature macros exist

The unified facade is convenient because it gives one public entry point:

cpp
#include <rix.hpp>

But not every application needs every Rix package.

For example, a small authentication example may only need:

cpp
rix.auth

A CSV tool may only need:

cpp
rix.csv

A PDF generator may only need:

cpp
rix.pdf

Feature macros allow the project to keep the facade style while mounting fewer modules.

Available macros

The current facade supports these macros:

cpp
RIX_ENABLE_AUTH
RIX_ENABLE_CSV
RIX_ENABLE_DEBUG
RIX_ENABLE_PDF

Each macro enables one module inside the rix object.

MacroMounted API
RIX_ENABLE_AUTHrix.auth
RIX_ENABLE_CSVrix.csv
RIX_ENABLE_DEBUGrix.debug
RIX_ENABLE_PDFrix.pdf

Default behavior

If no RIX_ENABLE_* macro is defined, rix.hpp enables the available facade modules by default.

This keeps simple examples short:

cpp
#include <rix.hpp>

int main()
{
  auto auth = rix.auth.memory();
  auto table = rix.csv.parse("name,lang\nAda,C++\n");

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

  auto doc = rix.pdf.document();

  return 0;
}

This behavior is also useful for backward compatibility.

Existing code that includes only:

cpp
#include <rix.hpp>

continues to work without defining macros.

Enable only Auth

To mount only Auth:

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

int main()
{
  auto auth = rix.auth.memory();
  auto registered = auth.register_user({"ada@example.com","correct-password"});
  return registered.failed() ? 1 : 0;
}

In this mode, only rix.auth is available.

These will not be available:

cpp
rix.csv
rix.debug
rix.pdf

unless their macros are also defined.

Enable Auth and Debug

To mount Auth and Debug:

cpp
#define RIX_ENABLE_AUTH
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  rix.debug.print("Auth example");

  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());

  return 0;
}

This is useful for examples that need Auth plus debug output.

Enable CSV only

To mount only CSV:

cpp
#define RIX_ENABLE_CSV
#include <rix.hpp>

int main()
{
  auto table = rix.csv.parse(
      "name,language\n"
      "Ada,C++\n"
      "Gaspard,Vix.cpp\n"
  );

  auto output = rix.csv.write(table);

  return output.empty() ? 1 : 0;
}

In this mode, the facade exposes:

cpp
rix.csv

but not:

cpp
rix.auth
rix.debug
rix.pdf

Enable PDF only

To mount only PDF:

cpp
#define RIX_ENABLE_PDF
#include <rix.hpp>

int main()
{
  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, "hello.pdf");

  return saved.failed() ? 1 : 0;
}

In this mode, the facade exposes:

cpp
rix.pdf

Enable PDF and Debug

PDF examples often use Debug to print errors:

cpp
#define RIX_ENABLE_PDF
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  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, "hello.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:", "hello.pdf");

  return 0;
}

Macro order matters

Feature macros must be defined before including rix.hpp.

Correct:

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

Wrong:

cpp
#include <rix.hpp>
#define RIX_ENABLE_AUTH

Once rix.hpp has been included, the facade has already been configured.

Defining a macro after the include will not remount the module.

Use macros per translation unit

Feature macros are preprocessor settings.

They affect the current translation unit.

For clarity, define them at the top of each .cpp file that uses a restricted facade:

cpp
#define RIX_ENABLE_AUTH
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

In larger projects, prefer a small project header if multiple files need the same facade shape:

cpp
// include/app/rix.hpp
#pragma once

#define RIX_ENABLE_AUTH
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

Then application files can include:

cpp
#include <app/rix.hpp>

This keeps the selected facade modules consistent across the project.

Feature macros and vix.app

Feature macros control which modules are mounted in C++ code.

They do not install packages.

You still need to declare the package dependency in vix.app.

For the unified facade:

txt
deps = [
  "rix/rix",
]

Then install dependencies:

bash
vix install

If you use the facade package, the project can include:

cpp
#include <rix.hpp>

If you use only an independent package such as Auth, declare that package instead:

txt
deps = [
  "rix/auth",
]

But then your code should use the package-level API for that package instead of assuming the full facade package is available.

Feature macros and package dependencies

Feature macros are not the same as dependencies.

This controls C++ facade mounting:

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

This controls project dependencies:

txt
deps = [
  "rix/rix",
]

You usually need both when using a restricted facade in a project.

When to use feature macros

Use feature macros when:

  • you want the facade style
  • you want to mount only selected modules
  • you want smaller includes
  • you want clearer compile boundaries
  • you are writing examples for one package

Example for an Auth-only example:

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

Example for an Auth example with debug output:

cpp
#define RIX_ENABLE_AUTH
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

When not to use feature macros

Do not use feature macros when you want the simplest beginner path.

For documentation examples, this is often enough:

cpp
#include <rix.hpp>

This keeps the first experience simple.

Use feature macros only when the page is teaching lightweight usage or when the example intentionally needs a smaller facade.

Common mistakes

Defining macros after including rix.hpp

Wrong:

cpp
#include <rix.hpp>

#define RIX_ENABLE_AUTH

Correct:

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

Expecting a module that was not enabled

This will fail if only RIX_ENABLE_AUTH was defined:

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

int main()
{
  rix.debug.print("hello");
}

Enable Debug too:

cpp
#define RIX_ENABLE_AUTH
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

Forgetting the dependency

This is not enough by itself:

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

The project still needs the Rix dependency:

txt
deps = [
  "rix/rix",
]

Then run:

bash
vix install

What you should remember

Default usage:

cpp
#include <rix.hpp>

Restricted facade:

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

Available macros:

cpp
RIX_ENABLE_AUTH
RIX_ENABLE_CSV
RIX_ENABLE_DEBUG
RIX_ENABLE_PDF

Feature macros must be defined before including rix.hpp.

Project dependencies still belong in vix.app:

txt
deps = [
  "rix/rix",
]

Next step

Learn how to use the facade in a lightweight way.

Next: Lightweight Usage

Released under the MIT License.