1

I'm trying to build basic GTK+ code(one of its tutorials) with CMake, but I keep getting 'undefined reference to *' where * is any GTK function that is in the code. I tried to look after guides/tutorials on this, but most of them are mostly similar to what I have.

Regular compilation from terminal works without a problem using command:

g++ ./test.cpp -o test `pkg-config --cflags --libs gtk+-3.0`

When I try using CMake my CMakeLists.txt is:

cmake_minimum_required(VERSION 3.0.2)
project(gtktest)

find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)

include_directories(${GTK3_INCLUDE_DIRS})
link_directories(${GTK3_LIBRARY_DIRS})
add_definitions(${GTK3_CFLAGS_OTHER})

add_executable(gtktest test.cpp)
target_link_libraries(gtktest ${GKT3_LIBRARIES})

Now cmake . seems to work without problems

cmake .
-- The C compiler identification is GNU 7.4.0
-- The CXX compiler identification is GNU 7.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1") 
-- Checking for module 'gtk+-3.0'
--   Found gtk+-3.0, version 3.22.30
-- Configuring done
-- Generating done
-- Build files have been written to: /home/dfdark/Desktop/gtk test

But make command after that is the problem:

make
Scanning dependencies of target gtktest
[ 50%] Building CXX object CMakeFiles/gtktest.dir/test.cpp.o
[100%] Linking CXX executable gtktest
CMakeFiles/gtktest.dir/test.cpp.o: In function `activate(_GtkApplication*, void*)':
test.cpp:(.text+0x27): undefined reference to `gtk_application_window_new'
test.cpp:(.text+0x30): undefined reference to `gtk_window_get_type'
test.cpp:(.text+0x42): undefined reference to `g_type_check_instance_cast'
test.cpp:(.text+0x51): undefined reference to `gtk_window_set_title'
test.cpp:(.text+0x56): undefined reference to `gtk_window_get_type'
test.cpp:(.text+0x68): undefined reference to `g_type_check_instance_cast'
test.cpp:(.text+0x7a): undefined reference to `gtk_window_set_default_size'
test.cpp:(.text+0x86): undefined reference to `gtk_widget_show_all'
CMakeFiles/gtktest.dir/test.cpp.o: In function `main':
test.cpp:(.text+0xcc): undefined reference to `gtk_application_new'
test.cpp:(.text+0xfb): undefined reference to `g_signal_connect_data'
test.cpp:(.text+0x100): undefined reference to `g_application_get_type'
test.cpp:(.text+0x112): undefined reference to `g_type_check_instance_cast'
test.cpp:(.text+0x126): undefined reference to `g_application_run'
test.cpp:(.text+0x135): undefined reference to `g_object_unref'
collect2: error: ld returned 1 exit status
CMakeFiles/gtktest.dir/build.make:94: recipe for target 'gtktest' failed
make[2]: *** [gtktest] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/gtktest.dir/all' failed
make[1]: *** [CMakeFiles/gtktest.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

test.cpp code (From GTK+ tutorials)

#include <gtk/gtk.h>

static void
activate (GtkApplication* app,
          gpointer        user_data)
{
  GtkWidget *window;

  window = gtk_application_window_new (app);
  gtk_window_set_title (GTK_WINDOW (window), "Window");
  gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
  gtk_widget_show_all (window);
}

int
main (int    argc,
      char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}

Is the problem messed up order of CMake's commands?

DFDark
  • 219
  • 1
  • 2
  • 14
  • As noted in [the comments](https://stackoverflow.com/questions/56387754/undefined-reference-to-when-using-gtk-with-cmake#comment99375561_56387850) to an answer, `CMakeLists.txt` contains a typo (`GKT` instead of `GTK`). With fixing the typo the code is correct and works. On Stack Overflow we tend to not have the questions which can be resolved just by fixing a typo. – Tsyvarev May 31 '19 at 08:07

2 Answers2

4

Use GTK in your CMakeLists.txt instead of GTK3:

cmake_minimum_required(VERSION 3.0.2)
project(gtktest)

find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED gtk+-3.0)

include_directories(${GTK_INCLUDE_DIRS})
link_directories(${GTK_LIBRARY_DIRS})
add_definitions(${GTK_CFLAGS_OTHER})

add_executable(gtktest test.cpp)
target_link_libraries(gtktest ${GTK_LIBRARIES})
user3147395
  • 541
  • 3
  • 7
  • When trying your answer I noticed I make mistake in `target_link_libraries(gtktest ${GKT3_LIBRARIES})` (should be GTK3_LIBRARIES) which solved my issue. Is there any difference between using GTK and GTK3? I tried both and both seem to work. – DFDark May 31 '19 at 02:25
  • Not sure if I should add my own answer with correction or mark your answer as correct. For now I marked it as correct. – DFDark May 31 '19 at 02:26
  • 1
    @DFDark I'd use `GKT_LIBRARIES` as it is found in the official cmake docs here: https://cmake.org/cmake/help/latest/module/FindGTK.html, while `GKT3_LIBRARIES` is not as far as I can find so it may be removed at a later date – user3147395 May 31 '19 at 02:55
  • 1
    The answer has the same typo - `GKT` instead of `GTK` as the question. The first parameter to `pkg_check_modules` affects only on names of variables which will be set; whether to use `GTK` or `GTK3` is a matter of choice. The module [FindGTK.cmake](cmake.org/cmake/help/latest/module/FindGTK.html) is an **alternative way** for find GTK using `find_package(GTK)` instead of `pkg_check_modules`. – Tsyvarev May 31 '19 at 08:04
0

GTK or GTK3 is a prefix and you can use any prefix you want for example.

cmake_minimum_required(VERSION 3.0.0)
project(gtktest)
find_package(PkgConfig REQUIRED)
pkg_check_modules(HI REQUIRED gtk+-3.0)
add_executable(gtktest test.cpp)
target_include_directories(gtktest PRIVATE ${HI_INCLUDE_DIRS})
target_link_libraries(gtktest PRIVATE ${HI_LIBRARIES})

However the prefix must be the same through all the CMakeLists.txt file and you are using the prefix GTK3 but later you write GKT3_LIBRARIES