Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Guide: Packaging a source library

jank can package libraries which need building from source. There is no limitation on the build system used, such as CMake, Automake, GNU Make, Scons, etc. The jank build system can work with any build system, since we just invoke it externally.

Note

If you can package a library using an installed system package and pkg-config, prefer that. It’s much simpler, more efficient, and more portable than building from source.

Before continuing, please read the guide on packaging system libraries, since it teaches the foundational knowledge of how packaging works with jank’s build system.

Hello raylib

For this guide, we’re going to package raylib from source. Although raylib has a package in Nix and Homebrew, there is no Ubuntu/Debian package, which makes the pkg-config approach far less portable. Instead, we’ll build raylib from source.

A note on -sys packages

Even when we build from source, the pattern around -sys packages applies, so be sure to read about that here.

Building raylib manually

To start with, let’s make sure we can build raylib manually. Then we’ll deal with hooking that same flow into the jank build system. The first step in building raylib is to just download it. For your package, it likely makes sense to add raylib as a git submodule. You could also just clone it or download a release from Github, as long as you have a raylib-sys directory for your package with a raylib directory inside, which has the actual raylib repository.

In our raylib directory, we’ll make our own build directory, just like the jank build system’s build directory.

❯ cd raylib

❯ mkdir build
mkdir: created directory 'build'

❯ cd build

❯ cmake .. -DBUILD_EXAMPLES=off -DBUILD_SHARED_LIBS=on
<CMake configure output>

❯ make
<Make output>

# On macOS, you'll see libraylib.dylib instead!
❯ ls raylib/libraylib.*
raylib/libraylib.so

❯ cd ../../

❯ rm -r raylib/build

That wasn’t so bad! Now we just need to do the same from our jank-build.bb.

Packaging raylib

Let’s add our basic project:

(defproject org.jank-lang.guide/raylib-sys "2026.07-1"
  :description "Raw package for raylib."
  :license {:name "MPL 2.0"
            :url "https://www.mozilla.org/en-US/MPL/2.0/"}
  :plugins [[org.jank-lang/lein-jank "2026.07-1"]]
  :middleware [leiningen.jank/middleware]
  :build-dependencies [[org.jank-lang.commons/jank-build-cmake "2026.06-6"]]
  :verbatim-paths ["raylib"])

Note the jank-build-cmake helper in the :build-dependencies. This is going to do the heavy lifting for us. Also note the :verbatim-paths, which tells Leiningen that we want the entire raylib directory to be included in our raylib-sys package.

Now we just need our jank-build.bb.

;; Part 1.
(require '[babashka.fs :as fs]
         '[jank.build.cmake :as cmake])

;; Part 2.
(let [out-dir (:out-dir *input*)
      src-dir (fs/path (:src-dir *input*) "raylib")
      input   (assoc *input* :src-dir src-dir)]
  (cmake/build input {:defines {"BUILD_EXAMPLES" false}})

  ;; Part 3.
  (println (str "jank-build::include-dir=" (fs/path out-dir "include")))
  (println (str "jank-build::link-dir=" (fs/path out-dir "lib")))
  (println (str "jank-build::link-dir=" (fs/path out-dir "lib64")))
  (println (str "jank-build::link-library=" "raylib")))

We’ll go over this part by part. Firstly, we require babashka.fs so we can do some path manipulation. This namespace is available to all Babashka programs without needing to add a dependency. Then we require jank.build.cmake, which we added to our :build-dependencies above.

In part two, we invoke the jank.build.cmake helper, but we change the source directory to be the nested raylib directory. The CMake helper expects the CMakeLists.txt file to be within the source directory. The CMake helper will automatically handle building the project in the build directory and installing the final artifacts to the output directory.

In part three, we just print the necessary directives to tell the jank build system where to find headers, libraries, and which libraries to link.

That’s it! Now, if we wanted to use this package locally, we could install it with lein install and then add it as a dependency to another project.

❯ lein install
Created /home/jeaye/projects/raylib-sys/target/raylib-sys-2026.07-1.jar
Wrote /home/jeaye/projects/raylib-sys/pom.xml
Installed jar and pom into local repo.

Using the new package

Let’s create a new project and use our raylib-sys library.

❯ lein new org.jank-lang/jank hello-raylib
Generating a project called hello-raylib based on the 'jank' template.

Then we need to add our dependency to the project.clj:

  :dependencies [[org.jank-lang.guide/raylib-sys "2026.07-1"]]

Before we add any raylib code, let’s try to run our project and make sure everything builds correctly.

❯ lein run
Extracting [org.jank-lang.guide/raylib-sys 2026.07-1]
 Compiling [org.jank-lang.guide/raylib-sys 2026.07-1]
Hello, world!

Nice! Let’s take a look at the generated output directory, to see what’s inside. Note that your directory name may be different, due to the hashing, but it’ll be in the same place:

❯ ls target/debug/_cache/raylib-sys-2026.07-1-out-cv799vKey7U76tllczT0Hw/
include  jank-build-cache.txt  jank-build-fingerprint.txt  lib64

Our headers will be in the include directory and, in this case, our libraries will be in lib64. These may end up being named different things on your machine, too. That’s the flexibility of the jank build system: all of this is handled by CMake and then the jank build system just connects the dots.

Speaking of which, let’s wrap this up by writing some raylib code!

(ns hello-raylib.main
  (:include "raylib.h"))

(defn -main [& args]
  (cpp/InitWindow 200 100 "raylib demo")
  (cpp/SetTargetFPS 60)

  (while (cpp/! (cpp/WindowShouldClose))
    (let [time (cpp/GetTime)
          color (cpp/ColorFromHSV (mod (* 100.0 time) 360.0) 0.5 0.5)]
      (cpp/BeginDrawing)
      (cpp/ClearBackground cpp/RAYWHITE)
      (cpp/DrawText "Hello jank!" 50 30 20 color)
      (cpp/EndDrawing)))

  (cpp/CloseWindow))

Now you should be able to run this and see a raylib window rendering some colored text.

❯ lein run
INFO: Initializing raylib 6.1-dev
INFO: Platform backend: DESKTOP (GLFW)
<bunch of other raylib output>

Summary

Packaging a source library for jank involves answering the same four key questions as with system libraries. On top of that, we just need to utilize our source directory, build directory, and out directory with the project’s build system in order to put the files where jank can use them. Take a look at the CMake build script helper here for a peek behind the scenes of what we used for this guide.

Also, take a look at the official raylib-sys jank commons package, since it looks just like the one we made here!