Building a KFR C API package¶
kfr_capi is the shared library that implements the C ABI described in the C API overview. It is built from the KFR source tree and contains the complex and real DFT, DCT, FIR, FFT convolution, and IIR implementations; C callers link kfr_capi alone and never the static C++ module libraries.
Configure and install¶
The C API is optional and requires the DFT module:
cmake -S . -B build-capi -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/path/to/kfr-prefix \
-DKFR_ENABLE_CAPI_BUILD=ON \
-DKFR_ENABLE_DFT=ON \
-DKFR_ENABLE_MULTIARCH=ON \
-DCMAKE_CXX_COMPILER=clang++
cmake --build build-capi --target kfr_capi
cmake --install build-capi
KFR_ENABLE_CAPI_BUILD=ON is rejected when KFR_ENABLE_DFT=OFF. kfr_capi also links kfr_dsp and kfr_audio, so KFR_ENABLE_DSP, KFR_ENABLE_IO, and KFR_ENABLE_AUDIO must stay enabled. The implementation is C++ even though its declarations are C-compatible, so a supported C++ compiler is required: use clang-cl or MSVC on Windows, and add -DCMAKE_POSITION_INDEPENDENT_CODE=ON where a shared library needs position-independent objects.
KFR_MANAGED_ALLOCATION is the only other option that changes the exported C API; see Managed allocation mode. All of these options are described in Configuration.
CPU baseline¶
KFR_ENABLE_MULTIARCH=ON builds the KFR_ARCHS variants and selects the best supported ISA at runtime, which is normally what a redistributable package wants. A single-architecture build is smaller, but its KFR_ARCH must be available on every machine that loads the library — an avx2 build cannot run on an SSE2-only CPU. See Select a CPU architecture for the supported values on x86, ARM, and RISC-V, and use the cross-compilation toolchain of the intended target rather than the build host's defaults.
Install layout and CMake target¶
With default GNU install directories, installation produces:
<kfr-prefix>/
├── include/kfr/capi.h # C ABI declarations
├── include/kfr/config.h # generated build configuration
├── lib/ # libkfr_capi.so or libkfr_capi.dylib
│ └── cmake/kfr/ # KFRConfig.cmake and exported targets
└── bin/ # kfr_capi.dll on Windows
Debug artifacts are installed under the KFR_DEBUG_INSTALL_SUFFIX subdirectory (lib/debug by default), so one prefix can hold both configurations.
An installed package exports kfr_capi alongside the usual KFR targets, which supplies the include directory and the configuration-appropriate link artifact:
cmake_minimum_required(VERSION 3.16)
project(capi_smoke C)
find_package(KFR CONFIG REQUIRED)
add_executable(capi_smoke main.c)
target_link_libraries(capi_smoke PRIVATE kfr_capi)
When integrating the source tree with add_subdirectory, set all KFR options before adding it, then link the same target.
ABI boundary¶
A C ABI is not a promise that arbitrary KFR builds are interchangeable. The library must match the process operating system, CPU architecture, pointer width, calling convention, and available ISA baseline, and any C++ runtime it depends on must be present. Do not load a 64-bit library into a 32-bit process or ship a library whose baseline ISA is missing on a target machine.
Only kfr_-prefixed entry points declared in <kfr/capi.h> are part of the ABI. Plan and filter pointers are opaque and may be released only by their matching kfr_*_delete_* function. Nothing else — C++ containers, templates, exceptions, callbacks, object layouts — crosses the boundary.
Verify a package before shipping¶
Run these checks on a clean, deployment-like environment. A successful KFR build only proves that the library compiled; a C smoke test proves that the installed header, exported target, link artifact, loader search path, and ABI work together.
- Confirm that
capi.h, the generatedconfig.h, and the shared library are present in the installed prefix. On Windows the DLL is installed inbin, elsewhere inlib. - Configure, build, and run a small C executable with
find_package(KFR CONFIG REQUIRED)andkfr_capi, with the shared library discoverable by the loader. - At startup, check ::kfr_version against
KFR_HEADERS_VERSIONand log ::kfr_version_string. For a dispatch build, also log ::kfr_enabled_archs and ::kfr_current_arch. - Create, execute, and delete a DFT or filter handle, and check one allocation for
NULL. - Inspect runtime dependencies with
dumpbin /dependents,ldd, orotool -L, then confirm the application can locate all of them.