CMake for compiling gtkmm4 : error adding symbols: DSO missing from command line

I’m trying to convert the command-line compilation and building to a CMake one for gtkmm-4 in Ubuntu 22.10

 raphy@raohy:~/gtkmm-prj$ cmake -B build
-- The CXX compiler identification is GNU 12.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "1.8.1") 
-- Checking for module 'gtkmm-4.0'
--   Found gtkmm-4.0, version 4.10.0
-- Checking for module 'giomm-2.68'
--   Found giomm-2.68, version 2.76.0
-- Configuring done (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: /home/raphy/gtkmm-prj/build

raphy@raohy:~/gtkmm-prj$ cmake --build build
[ 50%] Building CXX object CMakeFiles/basic.dir/src/basic.cc.o
[100%] Linking CXX executable basic
/usr/bin/ld: CMakeFiles/basic.dir/src/basic.cc.o: undefined reference to symbol '_ZN4Glib7ustringD1Ev'
/usr/bin/ld: /lib/x86_64-linux-gnu/libglibmm-2.68.so.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
gmake[2]: *** [CMakeFiles/basic.dir/build.make:97: basic] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/basic.dir/all] Error 2
gmake: *** [Makefile:91: all] Error 2

But the command-line compilation and building goes fine:

raphy@raohy:~/gtkmm-prj$ 
raphy@raohy:~/gtkmm-prj$ g++ src/basic.cc -o basic `pkg-config --cflags --libs gtkmm-4.0`
raphy@raohy:~/gtkmm-prj$ ./basic

This is my CMakeLists.txt file :

cmake_minimum_required(VERSION 3.24)
project(tutorial01 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)

find_package(PkgConfig REQUIRED)
pkg_check_modules(gtkmm-4.0 REQUIRED IMPORTED_TARGET  gtkmm-4.0)
pkg_check_modules(giomm-2.68 REQUIRED IMPORTED_TARGET giomm-2.68)


add_executable(basic src/basic.cc)

target_compile_options(basic PUBLIC ${gtkmm-4.0_CFLAGS_OTHER} ${giomm-2.68})
target_include_directories(basic PUBLIC ${gtkmm-4.0_INCLUDE_DIRS} ${giomm-2.68_INCLUDE_DIRS})



target_link_libraries(basic PUBLIC
    gtkmm-4.0
    giomm-2.68
)

What’s wrong with CMakeLists.txt file? How to make it work?

Two things:

  1. You’re using pkg_check_modules(... IMPORTED_TARGET), but then you’re ignoring that imported target and manually consuming output variables like ${gtkmm-4.0_CFLAGS_OTHER}.
  2. (Related) Because you’re not using the IMPORTED_TARGET (which, the FindPkgConfig module docs reveal, is named PkgConfig::<prefix>,so PkgConfig::gtkmm-4.0 in your case) in your target_link_libraries() call, you’re simply telling CMake to have the linker link with the shared library named libgtkmm-4.0.so.
    But gtkmm-4.0 has a lot of library dependencies. (The output of pkg-config --libs gtkmm-4.0 will list them all.) You’re not linking in any of those, so you have undefined symbols.

Solution: Skip all of that output variable stuff, and use the IMPORTED_TARGET the way it’s designed (which is to say, let it carry all of the necessary dependencies):

find_package(PkgConfig REQUIRED)
pkg_check_modules(gtkmm-4.0 REQUIRED IMPORTED_TARGET  gtkmm-4.0)
pkg_check_modules(giomm-2.68 REQUIRED IMPORTED_TARGET giomm-2.68)

add_executable(basic src/basic.cc)

target_link_libraries(basic PUBLIC
    PkgConfig::gtkmm-4.0
    PkgConfig::giomm-2.68
)

…That’s it.

(Also, as a suggestion, always run cmake --build build --verbose to see what commands CMake is actually running, when a compile fails.)

…In fact, giomm-2.68 is one of those library dependencies of gtkmm-4.0, so you can even leave that out – gtkmm-4.0 will pull it in automatically. So the final, most-streamlined version is just:

find_package(PkgConfig REQUIRED)
pkg_check_modules(gtkmm-4.0 REQUIRED IMPORTED_TARGET  gtkmm-4.0)

add_executable(basic src/basic.cc)
target_link_libraries(basic PUBLIC PkgConfig::gtkmm-4.0)