# Introduction

Local nix build for xo libraries.
Intended for local development work, with source in immediate subdirectories.

## Features

- native c++
- deterministic simulation
- reflection
- python bindings

## Getting Started

(Alternatively, see `xo-umbrella2/docs/install.rst` for similar content)

### Nix shell (reproducible development environment)

If `nix` is available, can get several reproducible build environments.

Pick one for a session:

```
$ cd xo-umbrella2
$ nix-shell -A shell0  # just nix stdenv: make,gcc,bash etc.
$ nix-shell -A shell1  # stable environment
$ nix-shell -A shell2  # stable environment + emacs + lsp
$ nix-shell -A shell3  # stable environment + emacs + lsp + xorg/opengl/vulkan/imgui stack (wsl2-only)
$ nix-shell -A shell4-osx  # stable environment + emacs + lsp + imgui stack (osx-only)
$ nix-shell -A shell4  # wsl2-specific. like shell3, vkcube works (at least on WSL)
$ nix-shell -A shell5  # wsl2-specific. uses dxg driver for "hardware acceleration"
$ nix-shell -A shell   # (deprecated) bleeding edge environment
```

Run emacs (for example) from within chosen seesion.
We need this ordering because nix-shell determines vital details like location of shared libraries,
including libraries used by running IDE.

```
$ emacs
```

Can use `nix-shell` to get reproducible environment for cmake build, see `Cmake Build`.
Alternatively can use full nix build, see `Nix Build`

### Cmake build

If `nix` is available, you probably prefer the nix build, unless working on XO itself.
Otherwise continue reading..

```
$ PREFIX=/path/to/say/home/local
$ cd xo-umbrella2
$ (cd xo-cmake && cmake -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build -S . && cmake --install .build)
$ cmake -B .build -S . -DCMAKE_INSTALL_PREFIX=${PREFIX} -DXO_ENABLE_EXAMPLES=1 -DXO_ENABLE_DOCS=1 -DCMAKE_BUILD_TYPE=debug
$ cmake --build .build --verbose
$ cmake --install .build
```

or with Vulkan examples
```
$ cmake -B .build -S . -DCMAKE_INSTALL_PREFIX=${PREFIX} -DXO_ENABLE_EXAMPLES=1 -DXO_ENABLE_VULKAN=1
```

### Re-run cmake

```
$ cd xo
$ .build/reconfigure -n
cmake -B /home/roland/proj/xo-umbrella2-claude1/.build -S /home/roland/proj/xo-umbrella2-claude1 \
    -DCMAKE_BUILD_TYPE=debug \
    -DCMAKE_INSTALL_PREFIX=/home/roland/local \
    -DCMAKE_INSTALL_DOCDIR=share/doc/xo-umbrella \
    -DCMAKE_MODULE_PATH=/home/roland/proj/xo-umbrella2/xo-cmake/cmake \
    -DCMAKE_PREFIX_PATH= \
    -DCMAKE_CXX_STANDARD=20 \
    -DXO_CMAKE_CONFIG_EXECUTABLE=/home/roland/local/bin/xo-cmake-config \
    -DENABLE_TESTING=1 \
    -DXO_ENABLE_DOCS=1 \
    -DXO_ENABLE_ASM=1 \
    -DXO_ENABLE_EXAMPLES=1 \
    -DXO_ENABLE_VULKAN=1 \
    -DXO_ENABLE_OPENGL=ON
$ .build/reconfigure  # to rerun cmake
```

### Cmake build documentation

Documentation relies on doxygen, sphinx and breathe.
```
# phase 2
$ cd xo-umbrella2
$ cmake -B .build -S . -DXO_ENABLE_DOCS=1
$ cmake --build .build -- docs
```

Create Html docs in `.build/sphinx/html/index.html`

### Cmake build with coverage

Prepare build
```
# phase 2
$ cmake -B .build -S . -DCMAKE_INSTALL_PREFIX=${PREFIX} -DCMAKE_BUILD_TYPE=coverage -DENABLE_TESTING=1
$ cmake --build .build --
```

Run coverage-enabled unit tests
```
$ (cd .build && ctest)
```

Generate coverage report
```
$ .build/gen-ccov
# or:
$ cmake --build .build --target ccov
```

Html report left in ``.build/ccov/html/index.html``

### Nix Build

Nix build uses toplevel `default.nix`,
along with top-level `pkgs/xo-foo.nix` for each subproject `foo`.
It doesn't interact with toplevel `CMakeLists.txt`.

```
$ nix-build -A xo-userenv
```

This builds all xo subprojects,  assembles sandbox under `./result`.

```
$ tree -L 1 ./result
./result
├── bin
│   ├── xo-build
│   ├── xo-cmake-config
│   └── xo-cmake-lcov-harness
└── share
    ├── cmake
    │   └── xo_macros
    │       ├── code-coverage.cmake
    │       ├── xo-project-macros.cmake
    │       └── xo_cxx.cmake
    ├── etc
    │   └── xo
    │       └── subsystem-list
    └── xo-macros
        ├── Doxyfile.in
        ├── gen-ccov.in
        └── xo-bootstrap-macros.cmake
```

For completeness' sake: can also use
```
$ nix-build -A xo-userenv-slow
```

Same result as `$nix-build -A xo-userenv`, but builds each package serially
using `xo-build`.

Finally, can also individual XO packages:
```
$ nix-build -A xo.cmake
$ nix-build -A xo.indentlog
...
```

#### Nix + SDL2 + Vulkan + ImGui

Currently (Nov 2025) only affects `xo-umbrella2/xo-imgui`.

For OSX, imgui works with assistance from motlenvk.
Build `xo-imgui` with

```
$ cd xo-umbrella2
$ nix-shell -A shell4-osx   # see xo-umrbella2/default.nix for impl
```

For linux and/or wsl build need extra care:
1. must use host OS for gpu drivers.  nixpkgs has drivers, but they're setup to work from nixos.
2. want to use nixpkgs for the GPU-independent portion of graphics stack.

Complication because host gpu drivers in a "big swimming pool" such as `/usr/lib/x86_64-linux-gnu/`
that contains both libraries that must come from host OS (e.g. `libGLX_nvidia`) and libraries
that must come from nixpkgs (e.g. `libc`)

Finesse by introducing a directory-of-symlinks, see `xo-umbrella2/etc/{hostegl, hostubuntu}`.
These currently setup by hand, so likely to need manual attention on another host.

An ordinary cmake build may cheerfully use the host-provided graphics stack,
in return for higher risk of DLL hell.

To build for ubuntu with nvidia gpu:
```
$ cd xo-umbrella2
$ nix-shell -A shell4-nvidia
# then regular cmake:
$ cmake -B .build -S . -DXO_ENABLE_VULKAN=1 -DXO_ENABLE_EXAMPLES=1 -DCMAKE_INSTALL_PREFIX=$PREFIX
```

To build for wsl:
```
$ cd xo-umbrella2
$ nix-shell -A shell4-wsl
# then regular cmake:
$ cmake -B .build -S . -DXO_ENABLE_VULKAN=1 -DXO_ENABLE_EXAMPLES=1 -DCMAKE_INSTALL_PREFIX=$PREFIX
```

Currently not supporting a nix sandbox build for xo-imgui

## Directory Layout

(not in alphabetical order)

```
xo-umbrella2/
|
+- CMakeLists.txt                 top-level cmake config
+- cmake
|  \- xo-bootstrap-macros.cmake   configure xo cmake support for build
+- compile_commands.json          symlink to path/to/build/compile_commands.json for LSP
|
+- conf.py                        sphinx config for project documentation
+- index.rst                      root of xo-umbrella2 doc tree
+- Doxyfile.in                    doxygen config template; cmake will prepare Doxyfile in build dir
+- _static/                       static inputs to sphinx
|
+- etc
|  +- hostegl/                    sample video driver symlinks for WSL2
|  \- hostubuntu/                 sample video driver symlinks for ubuntu
|
+- default.nix                    top-level nix build (works w/ stock nixpkgs 25.05)
+- pkgs/                          per-satellite nix builds. see xo-umbrella2/default.nix
|  +- xo-callback.nix             nix build for xo-umbrella2/xo-callback
|  ..etc..
|  \- xo-webutil.nix
|
+- xo-alloc/                      xo-alloc subproject. independent git repo, using git subtree
+- xo-alloc2/                     xo-alloc2 subproject.
..etc..
\- xo-webutil/

```

## Build/Install

See also docs/install.rst

### cmake build

```
$ git clone https://github.com/rconybea/xo-umbrella2
$ cd xo-umbrella2
$ PREFIX=${HOME}/local  # or /usr/local or ...

# phase1 install helper scripts
$ cmake -B xo-cmake/.build -S xo-cmake -DCMAKE_INSTALL_PREFIX=$PREFIX
$ cmake --install xo-cmake/.build

# phase 2 -- configure & build XO, using helpers installed in phase 1.
# -DENABLE_TESTING=1 : builds unit tests
# -DXO_ENABLE_DOCS=1 : builds documentation; or 0 to skip
# -DXO_ENABLE_EXAMPLES=1 : builds examples; or 0 to skip
# -DXO_ENABLE_OPENGL=1 : builds opengl examples; or 0 to skip
# -DXO_ENABLE_VULKAN=1 : builds vulkan-dependent graphics pipeline for imgui; or 0 to skip
$ cmake -B .build -S . -DCMAKE_INSTALL_PREFIX=$PREFIX -DXO_ENABLE_DOCS=1 -DXO_ENABLE_EXAMPLES=1 -DXO_ENABLE_VULKAN=1
$ cmake --build .build -j

# optionally build docs
$ cmake --build .build -- docs

# install
$ cmake --install .build
```

### nix build

```
$ nix-build -A xo-userenv
```

output now in `./result`

## To view docs locally

### find local IP address

wsl:

```
$ hostname -I
```

linux
```
$ /usr/sbin/ifconfig -a
```

### run nix build

```
$ nix-build -A xo-userenv
```

### serve docs from some available port
```
$ (cd result && python3 -m http.server 3000)
```

browse to "<host-ip-address>:3000/share/doc/xo-flatstring/html"

## To add a new satellite repo / missing satellite remote

1. check clone in clean state (all local changes committed or unwound)

2. add satellite as remote

```
$ xo-build -n --add-umbrella-remote xo-foo
git remote add xo-cmake git@github.com:Rconybea/xo-cmake.git
$ xo-build --add-umbrella-remote xo-foo
```

3. fetch (for hygiene)

```
$ git fetch xo-foo main
```

4. add subtree to local sandbox

```
$ git subtree add --prefix=xo-foo xo-foo main
```

## To push changes to satellite repos

We use an explicit branch for each satellite

```
$ git branch --show-current
main

$ xo-build -n --push-umbrella-remote xo-foo
git subtree split --rejoin --prefix=xo-foo -b _demux/xo-foo
git push xo-foo _demux/xo-foo:main

$ xo-build --push-umbrella-remote xo-foo
```

## To pull changes from satellite repos

```
$ xo-build -n --pull-umbrella-remote xo-foo
git subtree pull xo-foo main --rejoin
```

```
$ xo-build --pull-umbrella-remote xo-foo
```
