Skip to content

Fix pkg-config paths when install dirs are absolute - #295

Merged
ibireme merged 1 commit into
ibireme:masterfrom
domenkozar:fix-pkgconfig-absolute-install-dirs
Aug 19, 2026
Merged

Fix pkg-config paths when install dirs are absolute#295
ibireme merged 1 commit into
ibireme:masterfrom
domenkozar:fix-pkgconfig-absolute-install-dirs

Conversation

@domenkozar

Copy link
Copy Markdown
Contributor

Problem

yyjson.pc.in composes libdir and includedir by concatenating the prefix with the install dirs:

libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@
includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@

That is correct only when CMAKE_INSTALL_LIBDIR and CMAKE_INSTALL_INCLUDEDIR are relative. GNUInstallDirs explicitly allows them to be absolute, and distributions do pass absolute values. Nixpkgs passes them so a package can split headers and libraries into separate outputs.

When that happens the prefix is applied twice:

includedir=/nix/store/...-yyjson-0.12.0//nix/store/...-yyjson-0.12.0/include

pkg-config --cflags yyjson then reports a directory that does not exist, and any consumer discovering yyjson through pkg-config fails with fatal error: yyjson.h: No such file or directory. I hit this integrating yyjson into a C library via Meson's dependency('yyjson').

Fix

GNUInstallDirs provides CMAKE_INSTALL_FULL_LIBDIR and CMAKE_INSTALL_FULL_INCLUDEDIR for exactly this case. They return the value unchanged when it is absolute, and prepend the prefix when it is relative.

include(GNUInstallDirs) already runs before configure_file(yyjson.pc.in ...), so the variables are available with no other change.

Verification

Both cases tested against current master (9365ddc):

Absolute install dirs (-DCMAKE_INSTALL_LIBDIR=$PFX/lib -DCMAKE_INSTALL_INCLUDEDIR=$PFX/include)

Before:

libdir=/tmp/.../inst-abs//tmp/.../inst-abs/lib
includedir=/tmp/.../inst-abs//tmp/.../inst-abs/include

After:

libdir=/tmp/.../inst-abs/lib
includedir=/tmp/.../inst-abs/include
header resolves: YES

Default relative install dirs (regression check, resolved to lib64 on this machine)

prefix=/tmp/.../inst-rel
libdir=/tmp/.../inst-rel/lib64
includedir=/tmp/.../inst-rel/include
header resolves: YES

End to end, a Meson project using plain dependency('yyjson') fails to compile against an absolute-install-dir build before this change and builds and runs after it.


🤖 Generated with Claude Code

This PR was created by Claude Code. See cli/cli#13904 for context on why this note exists.

`yyjson.pc.in` builds `libdir` and `includedir` by concatenating
`CMAKE_INSTALL_PREFIX` with `CMAKE_INSTALL_LIBDIR` / `CMAKE_INSTALL_INCLUDEDIR`.
That is only correct when those variables are relative.

GNUInstallDirs explicitly allows them to be absolute, and distributions do pass
absolute values. Nixpkgs, for example, passes them so a package can split its
headers and libraries into separate outputs. When that happens the prefix is
applied twice and the generated file contains paths like:

    includedir=/nix/store/...-yyjson-0.12.0//nix/store/...-yyjson-0.12.0/include

`pkg-config --cflags yyjson` then reports a directory that does not exist, and
any consumer that discovers yyjson through pkg-config fails to compile with
"yyjson.h: No such file or directory".

GNUInstallDirs provides `CMAKE_INSTALL_FULL_LIBDIR` and
`CMAKE_INSTALL_FULL_INCLUDEDIR` for exactly this: they return the value as-is
when it is absolute and prepend the prefix when it is relative.

Verified both ways on the current master:

* absolute install dirs: paths are no longer doubled and `pkg-config` now
  resolves `yyjson.h` correctly
* default relative install dirs: unchanged, including the `lib64` case

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@domenkozar

Copy link
Copy Markdown
Contributor Author

Some extra context on why this went unnoticed for so long, in case it is useful.

Nixpkgs actually has a guard for exactly this class of bug. Its CMake setup hook runs a cmakePcfileCheckPhase that is meant to fail the build when a generated .pc contains a doubled prefix, and it even prints the fix:

Broken paths found in a .pc file!
It is very likely that paths are being joined improperly.
ex: "${prefix}/@CMAKE_INSTALL_LIBDIR@" should be "@CMAKE_INSTALL_FULL_LIBDIR@"
Please see https://github.com/NixOS/nixpkgs/issues/144170 for more details.

The guard greps for the literal string }//nix/store, which assumes the template is written as ${prefix}/@CMAKE_INSTALL_LIBDIR@, so the broken output contains a } immediately before the doubled path.

yyjson.pc.in instead expands @CMAKE_INSTALL_PREFIX@ directly, so the generated file contains /nix/store/...//nix/store/... with no } in front of it. Checking the shipped file:

guard pattern '}//nix/store' -> 0 matches
actual doubled path          -> 2 matches

So the detector silently passes and a broken yyjson.pc ships. That is a nixpkgs bug too and I will report it separately, but it means the yyjson side has had no early warning from that direction.

Nothing here changes the patch, just explaining why a fairly visible packaging bug stayed quiet.

@ibireme
ibireme merged commit db37a64 into ibireme:master Aug 19, 2026
48 checks passed
@ibireme

ibireme commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Thanks! Merged.

@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.47%. Comparing base (9365ddc) to head (bef00cb).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #295   +/-   ##
=======================================
  Coverage   98.47%   98.47%           
=======================================
  Files           2        2           
  Lines        7743     7743           
=======================================
  Hits         7625     7625           
  Misses        118      118           
Flag Coverage Δ
unittests 98.47% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@domenkozar

Copy link
Copy Markdown
Contributor Author

Would appreciate a release so I can cleanup!

@ibireme

ibireme commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Would appreciate a release so I can cleanup!

I have a few more things to merge first, should have a new release out in a week or two.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants