# How to correctly generate compile\_commands.json for library dependency using PkgConfig?

**URL:** https://discourse.cmake.org/t/how-to-correctly-generate-compile-commands-json-for-library-dependency-using-pkgconfig/15135
**Category:** Code
**Tags:** os:macos, comp:clang
**Created:** [August 31, 2025, 1:11am UTC](https://discourse.cmake.org/t/how-to-correctly-generate-compile-commands-json-for-library-dependency-using-pkgconfig/15135 "2025-08-31T01:11:03Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![skittishdev](https://discourse.cmake.org/user_avatar/discourse.cmake.org/skittishdev/32/5794_2.png) [@skittishdev](https://discourse.cmake.org/u/skittishdev)
#### Post date: [August 31, 2025, 1:11am UTC](https://discourse.cmake.org/t/how-to-correctly-generate-compile-commands-json-for-library-dependency-using-pkgconfig/15135/1 "2025-08-31T01:11:03Z")

</div>

Hi,

I am on MacOS, and I use nix as my package manager. I am building a C project, and I’d like to use [Criterion](https://github.com/haskell/criterion) for my tests. I am able to build my project and run the tests, but my `compile_commands.json` file is not generated as I expect it to be, and this is bugging me because my editor keeps complaining that my it’s unable to find `criterion`’s header files. Any pointers here on what I’m doing wrong will be greatly appreciated.

## ./build/compile\_commands.json

### Actual

```json
[
{
  "directory": "<path>/linked_list/build/lib",
  "command": "/nix/store/x5vj7kgmimckq45xjjfdga2ib3v6wfg9-clang-wrapper-20.1.6/bin/clang -I<path>/linked_list/include -arch arm64 -isysroot /nix/store/5gfsv5n8zhpnl9yhggjpxrxg0jyflwja-apple-sdk-11.3/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -mmacosx-version-min=11.3 -o CMakeFiles/c_linked_list.dir/linked_list.c.o -c linked_list/lib/linked_list.c",
  "file": "<path>/linked_list/lib/linked_list.c",
  "output": "lib/CMakeFiles/c_linked_list.dir/linked_list.c.o"
},
{
  "directory": "<path>/linked_list/build/tests",
  "command": "/nix/store/x5vj7kgmimckq45xjjfdga2ib3v6wfg9-clang-wrapper-20.1.6/bin/clang -I<path>/linked_list/include -arch arm64 -isysroot /nix/store/5gfsv5n8zhpnl9yhggjpxrxg0jyflwja-apple-sdk-11.3/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -mmacosx-version-min=11.3 -o CMakeFiles/test_alloc_and_free.dir/test_alloc_and_free.c.o -c <path>/linked_list/tests/test_alloc_and_free.c",
  "file": "<path>/linked_list/tests/test_alloc_and_free.c",
  "output": "tests/CMakeFiles/test_alloc_and_free.dir/test_alloc_and_free.c.o"
}
]

```

### Expected

Notice how there is only one `-I` flag for the `tests` directory command. I was expecting to see two `-I` - one for my own `include` dir, and one for `criterion`.

## Commands I’m using

```bash
$ cmake --version
cmake version 3.31.6

CMake suite maintained and supported by Kitware (kitware.com/cmake).

$ cmake -S . -B build
-- The C compiler identification is Clang 20.1.6
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /nix/store/x5vj7kgmimckq45xjjfdga2ib3v6wfg9-clang-wrapper-20.1.6/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Found PkgConfig: /nix/store/irxrmkcns1sjckx7wii2sai156827if6-pkg-config-wrapper-0.29.2/bin/pkg-config (found version "0.29.2")
-- Checking for module 'criterion'
-- Found criterion, version 2.4.2
-- Configuring done (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: <path>/linked_list/build

$ cmake --build build
[25%] Building C object lib/CMakeFiles/c_linked_list.dir/linked_list.c.o
[50%] Linking C static library libc_linked_list.a
[50%] Built target c_linked_list
[75%] Building C object tests/CMakeFiles/test_alloc_and_free.dir/test_alloc_and_free.c.o
[100%] Linking C executable test_alloc_and_free
[100%] Built target test_alloc_and_free

$ cmake --build build --target test
Running tests...
Test project <path>/linked_list/build
    Start 1: alloc_and_free
1/1 Test #1: alloc_and_free ................... Passed 0.17 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) = 0.17 sec

$ pkg-config --libs criterion
-L/nix/store/p0nnffxh9jrldxz5day2yvpvsa1pq6i3-criterion-2.4.2/lib -Wl,-rpath,/nix/store/p0nnffxh9jrldxz5day2yvpvsa1pq6i3-criterion-2.4.2/lib -lcriterion

$ pkg-config --cflags --libs criterion
-I/nix/store/i3qwlyca06xx1fgdj1pcr4bzsyvfq4by-criterion-2.4.2-dev/include -L/nix/store/p0nnffxh9jrldxz5day2yvpvsa1pq6i3-criterion-2.4.2/lib -Wl,-rpath,/nix/store/p0nnffxh9jrldxz5day2yvpvsa1pq6i3-criterion-2.4.2/lib -lcriterion

$ ls /nix/store/p0nnffxh9jrldxz5day2yvpvsa1pq6i3-criterion-2.4.2
lib share

$ ls /nix/store/p0nnffxh9jrldxz5day2yvpvsa1pq6i3-criterion-2.4.2/lib
libcriterion.3.dylib libcriterion.a libcriterion.dylib

$ ls /nix/store/i3qwlyca06xx1fgdj1pcr4bzsyvfq4by-criterion-2.4.2-dev
include lib nix-support

$ ls /nix/store/i3qwlyca06xx1fgdj1pcr4bzsyvfq4by-criterion-2.4.2-dev/lib/pkgconfig
criterion.pc

$ cat /nix/store/i3qwlyca06xx1fgdj1pcr4bzsyvfq4by-criterion-2.4.2-dev/lib/pkgconfig/criterion.pc
prefix=/nix/store/p0nnffxh9jrldxz5day2yvpvsa1pq6i3-criterion-2.4.2
includedir=/nix/store/i3qwlyca06xx1fgdj1pcr4bzsyvfq4by-criterion-2.4.2-dev/include
libdir=${prefix}/lib

Name: criterion
Description: A KISS, Cross platform unit testing framework for C and C++
URL: https://snai.pe/git/criterion
Version: 2.4.2
Requires.private: boxfort, libffi, libgit2, nanomsg
Libs: -Wl,-rpath,${libdir} -L${libdir} -lcriterion
Libs.private: -lintl /nix/store/m4k69gc780vwjha885782ipwa03qgyb2-nanopb-runtime-0.4.9.1/lib/libprotobuf-nanopb.a -lm /nix/store/m4k69gc780vwjha885782ipwa03qgyb2-nanopb-runtime-0.4.9.1/lib/libprotobuf-nanopb.a
Cflags: -I${includedir}

```

## Project structure

```bash
- flake.nix
- CMakeLists.txt
- cmake
 | - FindCriterion.cmake
- include
 | - linked_list.h
- lib
 | - CMakeLists.txt
 | - linked_list.c
- tests
 | - CMakeLists.txt
 | - test_alloc_and_free.c

```

## Files

### ./CMakeLists.txt

```cmake
cmake_minimum_required(VERSION 3.31...4.0)

project(
  c-linked-list
  VERSION 1.0
  LANGUAGES C
  DESCRIPTION "A linked list implementation in C."
)

include(FetchContent)
include(CTest)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")

enable_testing()
add_subdirectory("lib")
add_subdirectory("tests")

```

### ./cmake/FindCriterion.cmake

```cmake
find_package(PkgConfig REQUIRED)
pkg_check_modules(PC_Criterion REQUIRED IMPORTED_TARGET criterion)

```

### ./tests/CMakeLists.txt

```cmake
add_executable(test_alloc_and_free test_alloc_and_free.c)

find_package(Criterion REQUIRED)
# Tried explicitly including directorties, but that doesn't help.
# target_include_directories(test_alloc_and_free PUBLIC ${PC_Criterion_INCLUDE_DIRS})
# Tried changing from PRIVATE to PUBLIC when linking, but that doesn't help either.
# Also tried using the `FindCriterion.cmake` as specified in the Criterion examples, but that doesn't help either.
# https://github.com/Snaipe/Criterion/blob/bleeding/dev/cmake/cmake/FindCriterion.cmake
target_link_libraries(test_alloc_and_free PRIVATE c_linked_list PkgConfig::PC_Criterion)

add_test(NAME alloc_and_free COMMAND test_alloc_and_free)

```

### ./flake.nix

```auto
{
  inputs = {
    nixpkgs = {
      url = "github:NixOS/nixpkgs/release-25.05";
    };
    nixpkgs-unstable = {
      url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    };
  };
  outputs = {
    self,
    nixpkgs,
    nixpkgs-unstable,
    ...
  }@inputs: let
    inherit (self) outputs;

    forAllSystems = nixpkgs.lib.genAttrs [
      "x86_64-linux"
      "aarch64-darwin"
    ];
  in {
    devShells = forAllSystems (
      system: let
        pkgs = nixpkgs.legacyPackages.${system};
        pkgs-unstable = nixpkgs-unstable.legacyPackages.${system};
      in {
        default = pkgs.mkShell {
          nativeBuildInputs = [
            pkgs.clang_20
            pkgs.lldb
            pkgs.cmake
            pkgs.pkg-config
          ];
          buildInputs = [
            # ===== Required by Criterion ===== #
            pkgs.boxfort.dev
            pkgs.libffi.dev
            pkgs.libgit2.dev
            pkgs.pcre2.dev
            pkgs.nanomsg
            # ===== Required by Criterion ===== #
            pkgs.criterion.dev
          ];
        };
      }
    );
  };
}

```

---

<div class="post-metadata">

### Author: ![skittishdev](https://discourse.cmake.org/user_avatar/discourse.cmake.org/skittishdev/32/5794_2.png) [@skittishdev](https://discourse.cmake.org/u/skittishdev)
#### Post date: [September 3, 2025, 5:35pm UTC](https://discourse.cmake.org/t/how-to-correctly-generate-compile-commands-json-for-library-dependency-using-pkgconfig/15135/3 "2025-09-03T17:35:15Z")

</div>

Correct link to Criterion: [GitHub - Snaipe/Criterion: A cross-platform C and C++ unit testing framework for the 21st century](https://github.com/Snaipe/Criterion). The original post links to the Haskell package by mistake, and I’m unable to edit it.

---

<div class="post-metadata">

### Author: ![skittishdev](https://discourse.cmake.org/user_avatar/discourse.cmake.org/skittishdev/32/5794_2.png) [@skittishdev](https://discourse.cmake.org/u/skittishdev)
#### Post date: [September 3, 2025, 5:53pm UTC](https://discourse.cmake.org/t/how-to-correctly-generate-compile-commands-json-for-library-dependency-using-pkgconfig/15135/4 "2025-09-03T17:53:13Z")

</div>

I was able to generate the correct `-I` flags by adding this to my [./cmake/FindCriterion.cmake](https://discourse.cmake.org/t/how-to-correctly-generate-compile-commands-json-for-library-dependency-using-pkgconfig/15135#p-39121-cmakefindcriterioncmake-8)

```cmake
add_compile_options(${PC_Criterion_CFLAGS})

```

I was expecting that the cflags were also added when the `IMPORTED_TARGET` was linked (like the headers are included). But apparently not.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 19, 2026, 9:01pm UTC](https://discourse.cmake.org/t/how-to-correctly-generate-compile-commands-json-for-library-dependency-using-pkgconfig/15135/7 "2026-02-19T21:01:24Z")

</div>

That’s interesting; I’d expect them to be added. @vito.gamberini ?
