QLib is a modular library for the Q programming language. It consists of:
- Q modules (
src/q): libraries written in Q, such as a command-line argument parser and a unit testing framework. See Modules. - A C interface (
src/c/cdk): a set of C headers for creating, inspecting, and managing Q objects from C or C++, wrapping the kdb+ C API (k.h). It is built into a shared library,libcdk.so. See the C interface documentation.
./build.sh -i # build and install to $QHOME/mod/qlib (or ~/.kx/mod/qlib)Then, in Q:
clap:use`qlib.clap| Requirement | Needed for |
|---|---|
| Bash | Running build.sh |
A C compiler with C23 support (-std=c2x), GCC or Clang |
Building libcdk.so |
| A C++ compiler with C++20 support | C++ tests (--ctest) |
q on the PATH |
Q tests (--qtest) |
| KX's C API library for your platform | C and documentation tests (--ctest, --doctest) |
The C interface is tested with GCC 13 and Clang 18. The compilers can be changed with the CC and CXX environment variables (see Environment Variables).
build.sh supports Linux, macOS, and Windows (MinGW, MSYS, or Cygwin) on x86-64 and ARM64.
The C and documentation tests are standalone programs, so they link against KX's C API library, which provides the kdb+ functions that the C interface calls. The library is not distributed with QLib. Download the files for your platform from the KxSystems/kdb repository (see C client for q for details). KX provides two sets of files, so choose one:
| Platform | Without SSL/TLS | With SSL/TLS (requires OpenSSL) |
|---|---|---|
| Linux, macOS | c.o |
e.o |
| Windows | c.dll and c.lib (and variants) |
e.dll and e.lib (and variants) |
Then set the QCLIB environment variable to the library to link, followed by any other linker arguments it needs. For example:
export QCLIB="$HOME/kdb/l64/c.o" # Linux, without SSL/TLS
export QCLIB="$HOME/kdb/l64/e.o -lssl -lcrypto" # Linux, with SSL/TLSQCLIB is split on spaces, so the path to the library must not contain any. On Windows, the matching DLL must also be on the PATH when the tests run.
If QCLIB is not set, or its library file does not exist, --ctest, --doctest, and -t stop with an error before running any C tests. Building, installing, and the Q tests do not need the library, and neither does code loaded into a Q process as a shared library, since the Q process provides the kdb+ functions itself.
./build.shThis clears the build directory, then builds the library into build/qlib:
| File | Description |
|---|---|
*.q |
The Q modules, copied from src/q |
libcdk.so |
The C interface, compiled from src/c/cdk/*.c |
include |
C header files |
By default, libcdk.so is a debug build (-g -O0), with assertions enabled. For an optimised build with assertions removed (-O3 -DNDEBUG), add --release:
./build.sh --release--release is ignored when running tests, as the tests rely on assertions.
To remove the contents of the build directory without building, run:
./build.sh --clean./build.sh -iThis builds the library and copies the contents of build/qlib to the install directory. By default, the install directory is:
$QHOME/mod/qlib, ifQHOMEis set, or~/.kx/mod/qlibotherwise.
These are within Q's module search path, so the modules can then be loaded with use, for example use`qlib.clap.
To install somewhere else, use -d:
./build.sh -i -d /path/to/qlibWarning: Installing deletes the existing contents of the install directory before copying the new files. Do not install into a directory that contains anything else.
Installation can be combined with tests. For example, to install only if every test passes:
./build.sh -t -iIf a C or documentation test fails, installation is skipped. If a Q test fails, build.sh stops immediately, so nothing after it runs.
Tests always use a debug build, so that assertions are enabled.
| Option | Tests run |
|---|---|
-t |
All of the tests below (except --itest) |
--qtest |
Q unit tests |
--ctest |
C and C++ unit tests, and header checks |
--doctest |
The C examples in the documentation |
--itest |
Starts a Q process with the Q tests loaded, for interactive use |
The options can be combined, for example ./build.sh --ctest --doctest. When several are given, the Q tests run first.
Runs the Q unit tests in test/q with the unit module, against the modules in build. A summary and any failures are printed. If any test fails, build.sh exits with a non-zero status straight away.
--itest instead starts a Q process listening on port 5000, with the tests registered but not run, so that they can be run and debugged interactively.
- Header checks: every header in
src/c/cdkis compiled on its own, as both C23 and C++20, to check that it includes everything it needs. The checks use-Wcast-qual, so that the headers also work in projects that enable it. - Unit tests: every
test/c/test_*.candtest/c/test_*.cppfile is built with Unity and run. The C++ tests check that the headers work from C++, and that the functions are declared with C linkage.
Every C example in doc/c/*.md that has a main function and is followed by an Output: block is extracted, built, and run. The test passes if the program exits with status 0 and prints exactly the documented output (ignoring trailing whitespace). This keeps the examples in the documentation compiling and correct.
For an example to be tested, it must be written like this:
```c
#include <stdio.h>
#include "q.h"
int main() {
...
}
```
Output:
```
...
```The C, C++, and documentation tests are built with -Wall -Wextra -Werror, and against a separate copy of libcdk.so in build/test, which is not installed. Where it is available (not on MinGW), they are also built with the undefined behaviour sanitizer, so any undefined behaviour fails the test.
When the tests finish, build.sh prints every result, followed by a summary:
Tests 251 | Passed 251 | Failed 0
A test that fails to build, crashes, or fails is listed with a message. Details are written to:
| File | Contents |
|---|---|
build/test/test_fail_output.log |
The full output of a C or C++ test that crashed |
build/doctest/<doc>_<line>.build.log |
The compiler output for a documentation example that failed to build |
build/doctest/<doc>_<line>.out |
The output of a documentation example |
build/doctest/<doc>_<line>.diff |
The difference from the documented output |
<doc>_<line> identifies the example by the documentation file and the line on which the example starts.
build.sh exits with a non-zero status if any test fails, so it can be used in CI.
| Option | Description |
|---|---|
-h, --help |
Show the usage message and exit |
-i, --install |
Install the library after building (and testing, if requested) |
-d, --dir <dir> |
Install to <dir> instead of the default install directory |
-t, --test |
Run all tests (Q, C and C++, and documentation) |
--qtest |
Run the Q unit tests |
--ctest |
Run the C and C++ unit tests and header checks |
--doctest |
Build and run the documentation examples in doc/c |
--itest |
Start a Q process on port 5000 for interactive testing |
--release |
Build an optimised libcdk.so without assertions (ignored with tests) |
--clean |
Remove the contents of the build directory and exit |
| Variable | Description | Default |
|---|---|---|
CC |
C compiler | gcc |
CXX |
C++ compiler | g++ |
QHOME |
Used for the default install directory ($QHOME/mod/qlib) |
Not set |
QCLIB |
KX's C API library (and any other linker arguments), used to link the C and documentation tests. Required by --ctest and --doctest (see KX's C API Library) |
Not set |
For example, to build and test with Clang:
CC=clang CXX=clang++ ./build.sh -t| Module | Description | Documentation | Dependencies |
|---|---|---|---|
clap |
Command-Line Argument Parser | clap.md | |
dbm |
Database Maintenance | dbm.md | fs |
fs |
File System Operations (Work in Progress) | fs.md | |
unit |
Unit Testing Framework (Work in Progress) | unit.md | fs |
The C interface is documented separately, in doc/c.
| Directory | Contents |
|---|---|
src/q |
Q modules |
src/c/cdk |
C interface headers and sources |
test/q |
Q unit tests |
test/c |
C and C++ unit tests, and the Unity test framework |
doc |
Module documentation (doc/q for Q, doc/c for the C interface) |
build |
Build output (created by build.sh) |
If you'd like to contribute a module or fix an issue, please open a pull request or start a discussion in the issues tab. Please run ./build.sh -t before submitting a pull request.