четверг, 14 октября 2021 г.

Простейшее испльзования систем CMake и Meson на примере gtk+ приложения

 Напишем простое gtk приложение, которое считает sin от вводимой величины. 

//   calc_sin.c
#include <gtk/gtk.h>
#include <math.h>

GtkWidget* main_window;
GtkWidget* box1;

GtkWidget* edit1;
GtkWidget* button1;
GtkWidget* label1;
GtkWidget* button_exit;

void
calc_sin(){
    double result = sin(atof(gtk_entry_get_text(GTK_ENTRY(edit1))));
    gchar *display = g_strdup_printf("%f", result);   
    gtk_label_set_text (GTK_LABEL(label1), display);
    g_free(display); 
}

void
activate (GtkApplication *app,
          gpointer        user_data)
{
      main_window = gtk_application_window_new (app);
      gtk_window_set_title (GTK_WINDOW (main_window), "The sin");
      gtk_window_set_default_size (GTK_WINDOW (main_window), 200, 400);
      gtk_container_set_border_width (GTK_CONTAINER (main_window), 20);

      box1 = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
      gtk_box_set_homogeneous (GTK_BOX(box1), FALSE);
      gtk_container_add (GTK_CONTAINER (main_window), box1);

      edit1=gtk_entry_new();
      gtk_box_pack_start(GTK_BOX (box1), edit1, FALSE, FALSE, 10);

      button1 = gtk_button_new_with_label("Calculate!");
      g_signal_connect (button1, "clicked", G_CALLBACK (calc_sin), NULL);
      gtk_box_pack_start(GTK_BOX (box1), button1, FALSE, FALSE, 10);

      label1 = gtk_label_new("result");
      gtk_box_pack_start(GTK_BOX (box1), label1, FALSE, FALSE, 10);

      button_exit = gtk_button_new_with_label ("Exit");
      gtk_box_pack_start(GTK_BOX (box1), button_exit, FALSE, FALSE, 10);
      g_signal_connect_swapped (button_exit, "clicked", G_CALLBACK
(gtk_widget_destroy), main_window);

      gtk_widget_show_all (main_window);
}

int
main (int    argc,
      char **argv)
{
    GtkApplication *app;
    int status;
      app = gtk_application_new ("org.gtk.the_sin", 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;
}

 А теперь откомпилируем-отлинкуем этот код разными методами и выполним его. Предполагается, что cmake и meson уже установлены.

Сначала сделаем это "традиционно":

#gcc calc_sin.c `pkg-config  --cflags --libs  gtk+-3.0` -lm -o calc_sin_bin

 После выполнения полученного бинарника мы должны увидеть следующее:

В едитбокс вводим величину в радианах, нажимаем на кнопочку "Calculate!" и вместо слова "result" увидим величину синуса введенного значения.

Теперь соберем нашу программу с помощью CMake.
Создадим файл CMakeLists.txt следующего содержания:

cmake_minimum_required (VERSION 2.6)

project (calc_sin_prj)
find_package (PkgConfig REQUIRED)
pkg_check_modules (GTK3 REQUIRED gtk+-3.0)
include_directories (${GTK3_INCLUDE_DIRS})
link_directories (${GTK3_LIBRARY_DIRS})
add_executable(calc_sin_bin calc_sin.c)
add_definitions (${GTK3_CFLAGS_OTHER})
target_link_libraries (calc_sin_bin ${GTK3_LIBRARIES} m)

Этот файл в данном случае должен быть в директории с нашим исходником. Далее делаем такую последовательность команд:

#mkdir cmakebuilddir
#cd cmakebuilddir
#cmake ..
#cmake --build .

Теперь соберем нашу программу с помощью meson.
Создадим файл meson.build следующего содержания:

project('calc_sin_meson', 'c')
cc = meson.get_compiler('c')
m_dep = cc.find_library('m', required:false)
deps = [dependency('gtk+-3.0'), m_dep]
executable('calc_sin_bin', 'calc_sin.c', dependencies : deps)

 Делаем такую последовательность команд:

#meson setup mesonbuilddir
#cd mesonbuilddir
#meson compile

Во всех трех случаях получаем бинарник  calc_sin_bin с одинаковою функциональностью. Обратите внимание, что этот бинарник создается в случае meson в директории mesonbuilddir , а в случае CMake в директории  cmakebuilddir. Получается что дерево исходников находится отдельно, а все рабочие файлы каждой системной сборки (мезон и симэйк) находятся только в своей поддиректории соответственно. Аккуратно и логично.

Комментариев нет: