How to create pkgconfig file

OK, than first you should read man pkg-config

METADATA FILE SYNTAX
       To add a library to the set of packages pkg-config knows about, simply install a .pc file. You should install
       this file to libdir/pkgconfig.

       Here is an example file:
       # This is a comment
       prefix=/home/hp/unst   # this defines a variable
       exec_prefix=${prefix}  # defining another variable in terms of the first
       libdir=${exec_prefix}/lib
       includedir=${prefix}/include

       Name: GObject                            # human-readable name
       Description: Object/type system for GLib # human-readable description
       Version: 1.3.1
       URL: http://www.gtk.org
       Requires: glib-2.0 = 1.3.1
       Conflicts: foobar <= 4.5
       Libs: -L${libdir} -lgobject-1.3
       Libs.private: -lm
       Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib/include

You have add all your

  • compiler flags
  • link flags
  • link libraies
  • all dependencies,

Precisely so if my library has dependencies which have been linked like so:
target_link_libraries(my_library X11::X11 JPEG::JPEG PNG::PNG CUDA::cublas CUDA::curand MKL::MKL ...)

how do i populate Libs and Cflags in the pkg config file?
As i wrote in my original post i tried using:

get_target_property(MYTARGET_LINK_LIBRARIES my_library INTERFACE_LINK_LIBRARIES)
get_target_property(MYTARGET_INCLUDE_DIRECTORIES my_library INTERFACE_INCLUDE_DIRECTORIES)

and a few others then tried using configure_file() with

Libs: -L${libdir} -lmylib @MYTARGET_LINK_LIBRARIES@
Cflags: -I${includedir} @MYTARGET_INCLUDE_DIRECTORIES@

however, in the case of MYTARGET_LINK_LIBRARIES it populates the pkg config file with

Libs: -L${libdir} -lmylib X11::X11 JPEG::JPEG PNG::PNG CUDA::cublas CUDA::curand MKL::MKL 

which of course makes no sense for pkg config.
So i need a way to resolve all the imported targets, generator expressions etc down to explicit compiler and linker flags

At the end of the day, cmake should know how to do this because it has to generate makefiles build-ninja files etc which must use explicit compiler/linker flags. I just wish there was a way to expose this functionality at configure time.

Normally you use find_package(X11 v1.2.3) or something like that in your cmake project files.

So you have a required entry for package config like in the man page.

You have to know your direct dependencies, write it in the package config file.

That’s all.

Yeah that’s not sufficient.
I think I’m gonna have to build a complete reproducible example to prove my point.
Maybe I’m not being clear enough.

mylibrary.tgz (2.2 KB)

Unpack then run:

cd cmake_bug
cmake lib/ -B build -DCMAKE_INSTALL_PREFIX=./install
cmake --build build
cmake --install build/
cmake example/ -B build2 -DCMAKE_PREFIX_PATH=./install
cmake --build build2

You will get error:
/usr/bin/ld: cannot find PNG::PNG: No such file or directory

If you look at the contents of installed mylibrary.pc file you will see something like:

libdir=/home/pf/Downloads/repos/cmake_bug/install/lib
includedir=/home/pf/Downloads/repos/cmake_bug/install/include

Name: mylibrary
Description: PNG reader
Version: 
Libs: -L${libdir} -lmylibrary PNG::PNG
Cflags: -I${includedir} $<BUILD_INTERFACE:/home/pf/Downloads/repos/cmake_bug/lib>

This line is the culprit:

Libs: -L${libdir} -lmylibrary PNG::PNG

make sense now?

I dit understand you the whole time, but you expect that CMake is doing the work for you!

It is an usage error, not a CMake error

bash-5.2$ git diff *.in
diff --git a/lib/mylibrary.pc.in b/lib/mylibrary.pc.in
index d073438..e7fa2e2 100644
--- a/lib/mylibrary.pc.in
+++ b/lib/mylibrary.pc.in
@@ -1,8 +1,11 @@
-libdir=@CMAKE_INSTALL_FULL_LIBDIR@
-includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+# libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+# includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+libdir=${pcfiledir}/../@CMAKE_INSTALL_LIBDIR@
+includedir=${pcfiledir}/../../@CMAKE_INSTALL_INCLUDEDIR@
 
 Name: @PROJECT_NAME@
 Description: PNG reader
-Version: @VERSION@
-Libs: -L${libdir} -lmylibrary @MYLIBRARY_LINK_LIBRARIES@
-Cflags: -I${includedir} @MYLIBRARY_INCLUDE_DIRECTORIES@
+Version: @PROJECT_VERSION@
+Requires: libpng >= 1.6
+Libs: -L${libdir} -lmylibrary -lpng16 # XXX @MYLIBRARY_LINK_LIBRARIES@
+Cflags: -I${includedir} -I@PNG_INCLUDE_DIRECTORIES@ # -I/usr/local/opt/libpng/include/libpng16 # XXX @MYLIBRARY_INCLUDE_DIRECTORIES@

This works fine :slightly_smiling_face:

see too https://bugs.freedesktop.org/show_bug.cgi?id=62018
and How to generate .pc (pkg-config) file supporting --prefix of the cmake --install? - #6 by craig.scott

What if libpng is an optional dependency in my library controlled by a cmake option ? That’s my use case. So you can’t guarantee it’s always a dependency.

My actual library has something like 10 optional dependencies depending on cmake options and the return values of find_package.

Basically my first solution works provided you never use generator expressions or imported targets. But that’s not modern cmake

OK, that should also a CMake variable:
PNG_LIBRARIES

Yep. That’s the only solution I can find. Not very modern cmake though

You will have the same problems when exporting a CMake config package:

you have to write the find_dependency() calls.

see Installed module library can't find imported headers [Ubuntu 22.04 LTS, CMake 3.28.1, Ninja 1.11.1 and Clang 17.0.6] - #18 by ben.boeckel

Yep it’s pants.
But at least it’s doable.
I’m starting to believe cmake doesn’t solve anything. As in, it doesn’t actually make you productive. But anyway, it’s the best we got unfortunately

Everything is possible.

Perhaps you should try the project_options
You may write a patch to export a pgk-config files too?

Es ist nicht genug zu wissen, man muß auch anwenden; es ist nicht genug zu wollen, man muß auch tun.

Johann Wolfgang von Goethe (1749 - 1832)

To be honest, the amount of time I have to spend writing and debugging cmake it’s barely worth it. New languages put a lot of effort in their build tools to minimise the amounting of time spent writing build code.
I might have a look at Meson this weekend and see how they tackle dependencies and install scripts.
But anyway, thank you for all your help

provide some wrappers that automatically generate pkgConfig files. I haven’t tried them myself but could be a good resource.

Peter, did you find a solution, I have exactly the same problem as you - a huge number of dependencies, could be shared, could be static, could be coming from conan, could be coming form the system

No I didn’t sorry. I haven’t tried GitHub - boost-cmake/bcm: Boost cmake modules or GitHub - robotology/ycm: YCM (YCM CMake modules) is a collection of various useful CMake modules. but they seemed to suggest they provided a solution to this. They are old and unmaintained however.