This guide explains how to publish a Turmeric library so that C and C++ projects can import it through CMake or CPM without knowing anything about Turmeric.
The tur emit-cmake command does the heavy lifting: it reads your build.tur
and generates all of the CMake files a consumer needs.
tur init --lib <name>tur buildtur is on PATH on the machine where CMake will build the consumer projectOpen build.tur and add an :exports field listing the .tur source files
that form the public API of your library:
(defpackage my-geom
:version "0.3.0"
:description "2-D geometry primitives"
:license "MIT"
:exports [
"src/vector.tur"
"src/matrix.tur"
])
If you omit :exports, tur emit-cmake falls back to scanning every *.tur
file in src/.
Run this command from your project root (where build.tur lives):
tur emit-cmake
It creates four files:
| File | Purpose |
|---|---|
CMakeLists.txt |
Top-level CMake project that compiles your library |
<name>Config.cmake |
find_package(<name>) support |
cmake/FindTurmeric.cmake |
Locates the tur binary on the consumer's machine |
cmake/AddTurmericTarget.cmake |
Helper macros (used internally) |
All four files are auto-generated -- do not edit them by hand. Re-run
tur emit-cmake whenever you add or remove source files, or change the version.
tur emit-cmake --output-dir dist/
This writes dist/CMakeLists.txt, dist/<name>Config.cmake, and
dist/cmake/*.cmake.
git add CMakeLists.txt my-geomConfig.cmake cmake/
git commit -m "chore: regenerate cmake files for v0.3.0"
git tag v0.3.0
git push && git push --tags
CPM identifies releases by tag, so a clean tag is required.
In the consuming project's CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
project(my_app LANGUAGES C)
# CPM bootstrap (download once, cache afterwards)
include(cmake/CPM.cmake)
CPMAddPackage(
NAME my-geom
URL https://github.com/alice/my-geom/archive/refs/tags/v0.3.0.tar.gz
VERSION 0.3.0
)
add_executable(my_app src/main.c)
target_link_libraries(my_app PRIVATE my-geom::all)
CPM fetches the archive, runs the generated CMakeLists.txt, which in turn
invokes tur emit-c --output-dir to compile the .tur sources to C, then
builds the static library. The consumer never calls tur directly.
The Turmeric compiler generates one .h per source file:
/* src/main.c */
#include "vector.h" /* generated from src/vector.tur */
#include "matrix.h" /* generated from src/matrix.tur */
int main(void) {
my_geom_vector_2d v = my_geom_vector_2d_make(1.0f, 2.0f);
/* ... */
return 0;
}
target_link_libraries with my-geom::all causes CMake to add the include
directory automatically -- no manual -I flags needed.
find_package instead of CPMIf the library is installed to a standard prefix:
# in the library project
cmake -B build -DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build build
cmake --install build
Then in the consumer:
find_package(my-geom REQUIRED)
target_link_libraries(my_app PRIVATE my-geom::all)
tur emit-cmake generates a CMakeLists.txt that:
find_package(Turmeric REQUIRED) to locate the tur binary via
cmake/FindTurmeric.cmake.add_custom_command that runs
tur emit-c --output-dir <build-dir> <source files> to produce one .h
and one .c per .tur module..c files to add_library(<name> STATIC ...).<name>::all for consumers.The <name>Config.cmake file is what find_package(<name>) reads. It sets
<name>_VERSION and <name>_FOUND, then includes the install targets file.
tur build --release passes:exports lists all public .tur files in build.turtur emit-cmake runs without errorsgit tag vX.Y.Zcmake/ usage example included in README