Skip to content
ocx
install

Run jq in a CMake build without installing it

In this tutorial you add find_ocx to a CMake project and run jq from a build target. You never install jq on your machine.

You need CMake 3.19 or later. You also need the ocx CLI once, to write the lock file (install it). find_ocx downloads its own pinned ocx for the build.

Download Findocx.cmake and ocx.cmake from the release assets. Put both in a cmake/ directory of an empty project.

Check that cmake/ocx.cmake and cmake/Findocx.cmake exist next to where your CMakeLists.txt will be.

Create ocx.toml next to the cmake/ directory.

ocx.toml
[tools]
jq = "ocx.sh/jqlang/jq:latest"

Write the lock file and keep both files in version control.

Terminal window
ocx lock

Check that ocx.lock exists. It holds the exact digest of jq.

Create CMakeLists.txt with the project header.

CMakeLists.txt
cmake_minimum_required(VERSION 3.19)
project(ocx_example_project LANGUAGES NONE)

Add the vendored directory to the module path and include the module.

CMakeLists.txt
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(ocx)

The include is passive. It defines commands and fetches nothing yet.

Add the toolchain and a target that runs jq on every build. ocx_project reads ocx.toml and ocx.lock, and OCX_TOOLS_RUN is the command that runs a tool from that toolchain.

CMakeLists.txt
# The ocx.toml next to this file is found by the upward search; the lock
# is verified; nothing is pulled yet (lazy). NAME picks the prefix of the
# result variables: NAME TOOLS -> OCX_TOOLS_RUN, OCX_TOOLS_RUN_JQ
# (defaults to PROJECT -> OCX_PROJECT_RUN).
ocx_project(NAME TOOLS BINS jq)
# Build-time tool use, lazily materialized on first execution. Generator
# expressions compose naturally - the command is a plain CMake list.
add_custom_target(validate ALL
COMMAND ${OCX_TOOLS_RUN} jq -n -e --arg config "$<CONFIG>"
[[$config | length >= 0]]
VERBATIM
)

Configure the project.

Terminal window
cmake -S . -B build

The first configure downloads the pinned ocx into a per-machine cache and checks that ocx.lock is current. It does not download jq yet.

Build the project.

Terminal window
cmake --build build

The build runs the validate target, which materializes jq on first execution and then runs it. The build ends without an error. Run the configure command again: with unchanged inputs, no ocx process starts at all.

You have a CMake project that runs a tool nobody installed, at a version the lock file fixes. Anyone who clones the project gets the same jq.

Next steps: