OxL Reference

Docker images

The toolchain is also available as images on ubuntu:24.04 (glibc 2.39; the release needs 2.38+). Two flavours:

tagcontents
ghcr.io/descaldnd/oxl:1.0.0-beta, :latest (full)the toolchain in /opt/oxl-<version> (symlinks in /usr/local/bin), clang-18 as the link driver, lld-18, the runtime libraries and their -dev packages, lldb-18 and lldb-dap-18, git, the documentation and oxl-docs
ghcr.io/descaldnd/oxl:1.0.0-beta-slim, :slim (slim)the toolchain without documentation, clang-18, lld-18 and the runtime libraries; no debugger, no -dev packages, no git

Both have a user oxl (uid 1000), working directory /work, the cache OXL_HOME=/home/oxl/.oxl, a UTF-8 locale and ca-certificates. The images expose no port by default.

Run#

sh
docker run --rm -v "$PWD:/work" ghcr.io/descaldnd/oxl oxl run .
docker run --rm -v "$PWD:/work" ghcr.io/descaldnd/oxl oxl test
docker run --rm -v "$PWD:/work" -v oxl-cache:/home/oxl/.oxl ghcr.io/descaldnd/oxl:slim oxl build -o app    # a cache volume between runs
docker run --rm ghcr.io/descaldnd/oxl oxl doctor                                                          # the environment inside the container

The files are created as uid 1000; on a Linux host whose user has another id add --user "$(id -u):$(id -g)" (then set -e OXL_HOME=/tmp/oxl).

A multi-stage build of an application#

A built program is an ordinary dynamic ELF: it needs the C++ runtime and the system libraries the program reaches (--as-needed; ldd app lists them). Build in the slim image and copy the binary into a plain ubuntu:24.04:

oxl
FROM ghcr.io/descaldnd/oxl:slim AS build
WORKDIR /work
COPY --chown=oxl:oxl . .
RUN oxl build -o /tmp/app

FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends libstdc++6 liburing2 libsqlite3-0 libssl3t64 libnghttp2-14 ca-certificates \
    && rm -rf /var/lib/apt/lists/*
COPY --from=build /tmp/app /usr/local/bin/app
USER 1000
ENTRYPOINT ["app"]

Even a hello world links liburing, libsqlite3, libssl/libcrypto, libnghttp2 and libstdc++ (checked with ldd in the image); libpq5 (with its Kerberos / LDAP dependencies) is added by programs that use PostgreSQL. The runtime packages for the libraries of the runtime are liburing2, libsqlite3-0, libpq5, libssl3t64, libnghttp2-14, libpcre2-8-0, zlib1g; install what ldd of your program shows (ca-certificates for TLS clients).

Dev container#

docker/devcontainer/devcontainer.json of the repository is a template: copy it to <project>/.devcontainer/devcontainer.json and choose "Reopen in Container" in VS Code. It uses the full image, mounts the project at /work and the volume oxl-cache for the cache, passes --cap-add=SYS_PTRACE --security-opt seccomp=unconfined and asks for the extension oxwaldlink.oxl-lang. The release archive carries the extension as share/oxl/vscode/oxl-lang-<version>.vsix; the image links it to /usr/local/share/oxl/oxl-lang.vsix. Dev containers install extensions by id, so if it is not in your Marketplace, install it once in the container terminal: code --install-extension /usr/local/share/oxl/oxl-lang.vsix.

Debugging#

oxl dap is a proxy over lldb-dap-18 (the full image). lldb needs ptrace:

sh
docker run -it --rm -v "$PWD:/work" --cap-add=SYS_PTRACE --security-opt seccomp=unconfined ghcr.io/descaldnd/oxl bash

For remote debugging from VS Code on the host run the adapter on a TCP port (oxl dap --listen [host:]port, see oxl dap --help) and publish the port:

sh
docker run -it --rm -p 127.0.0.1:4711:4711 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -v "$PWD:/work" \
    ghcr.io/descaldnd/oxl oxl dap --listen 0.0.0.0:4711

The launch configuration on the host: {"type": "oxl", "request": "launch", "name": "Container", "connect": {"host": "127.0.0.1", "port": 4711}, "program": "/work/app"} ("debugServer": 4711 is the short form); program and other paths are paths inside the container. --once makes the adapter exit after the first session. See VS Code.

A debug adapter starts programs: publish the port on 127.0.0.1 or inside a trusted network only.

io_uring, seccomp, limits#

  • The runtime uses io_uring when the kernel allows it. The default seccomp profile of Docker 25+ and kernel.io_uring_disabled=1|2 make io_uring_setup fail with EPERM; the runtime then falls back to its blocking thread pool (everything works, I/O is slower). oxl doctor shows it as the warning io-uring; allow it with --security-opt seccomp=unconfined or a profile that permits io_uring_setup, io_uring_enter and io_uring_register.
  • The runtime starts one worker per CPU the process may use; it does not read the CFS quota of --cpus. On a large host with --cpus=2 use --cpuset-cpus=0-1 or -e OXL_WORKERS=2 (oxl doctor: cpu-quota).
  • Compiling needs 1-2 GiB of memory: do not run the container with -m below 1g (oxl doctor: memory-limit).
  • vm.max_map_count is a setting of the host kernel; every task stack uses two mappings (oxl doctor: max-map-count).

Build the images yourself#

The images are built from the release archive; nothing is downloaded:

sh
scripts/package_release.sh 1.0.0-beta                       # dist/oxl-1.0.0-beta-linux-x86_64.tar.xz (--no-docs --no-pdf --no-vsix: quick)
scripts/docker_build.sh dist/oxl-1.0.0-beta-linux-x86_64.tar.xz --tag-prefix ghcr.io/descaldnd/oxl

The script builds both targets of docker/Dockerfile, runs scripts/docker_test.sh (oxl --version, oxl doctor, oxl new and oxl test, a built program, a sqlite program and a service that link, lldb-dap and the oxl dap handshake) in each image and prints the sizes. Nothing is pushed.

OxL 1.0.0-beta · Documentation version 1.0.0-beta© OxwaldLink · generated from the Standard, the std sources and the guides