Как устранить ошибку линкера?

Многоуровневый cmake-проект

  • main.cpp
  • CMakeLists.txt
  • /Main
  • --CmakeLists.txt
  • --mainwindow.cpp
  • --main.h

CmakeLists.txt:

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)    
set(PROJECT_NAME r21)    
project(${PROJECT_NAME} VERSION 0.0.1)
    
...

message(${RESOURCE_LIST})

compile_gresources(
    RESOURCE_FILE
    XML_OUT
    TYPE EMBED_C
    RESOURCES ${RESOURCE_LIST}
    PREFIX /r21
    )

add_custom_target(
    gladeGeneratedResource
    ALL
    DEPENDS ${RESOURCE_FILE}
    )   
    
set(sources main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/build/resources.c)
set(headers Main/main.h)

message("use ${CMAKE_CURRENT_SOURCE_DIR}resources.c")

add_executable(retom21 WIN32 ${sources} ${headers})

message("Coping necessary mingw DLLs")
set(dlls_file "dlls.txt")

set(MINGW_DLL_DIR "C:/msys64/mingw64/bin")
set(BIN_DIR, "/build/bin")

find_package(PkgConfig)
pkg_check_modules(GTKMM gtkmm-3.0 REQUIRED)

add_subdirectory(Main)

target_include_directories(retom21 PRIVATE ${GTKMM_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/Main)    
target_link_libraries(retom21 PRIVATE ${GTKMM_LIBRARIES} Main)

main.cpp:

#include <gtkmm.h>
#include <iostream>
#include <string>
#include "Main/main.h"
   
int add_glade_res(Glib::RefPtr<Gtk::Builder> refBuilder, char* gxml_path)
{
    try{
        refBuilder->add_from_resource(gxml_path);
    } catch (...){
        std::cerr << "Error loading glade map resource" << gxml_path << std::endl;
        return 0;
    }
    return 1;
}

int on_cmd(const Glib::RefPtr<Gio::ApplicationCommandLine> &,
  Glib::RefPtr<Gtk::Application> &app) {
    app->activate(); // <----
    return 0;
}

int main(int argc, char **argv){

    auto app = Gtk::Application::create(argc, argv, "r21", Gio::APPLICATION_HANDLES_COMMAND_LINE);
    app->signal_command_line().connect(sigc::bind(sigc::ptr_fun(on_cmd), app), false);

    // Load the GtkBuilder file and instantiate its widgets:
    auto refBuilder = Gtk::Builder::create();

    if(!add_glade_res(refBuilder, "/r21/glade/main.glade")) return 1;
    
    MainWindow *wnd = nullptr;
    refBuilder->get_widget_derived("main_window", wnd); 
    
    if (wnd){
        app->run(*wnd);         
    }

    delete wnd;
    return 0;
}

Main/main.h:

#include <gtkmm.h>
#include <iostream>
#include <string>

class MainWindow : public Gtk::ApplicationWindow  {
    public:
        MainWindow(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& builder);
        MainWindow(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& builder, char *gladefile);
        virtual ~MainWindow();
    private:
            
        Glib::RefPtr<Gtk::Builder> builder;
        Glib::RefPtr<Gio::SimpleActionGroup> ActionsGroup;

        ...
        Gtk::Button btn1;   
};

Main/mainwindow.cpp:

#include <gtkmm.h>
#include <iostream>
#include <string>

class MainWindow : public Gtk::ApplicationWindow {
    public:
        MainWindow(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& builder)
        : Gtk::ApplicationWindow(obj)
        , builder{builder}
            {
                ...

            }
        MainWindow(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& builder, char *gladefile): Gtk::ApplicationWindow(obj)
        {

        }
    private:
        ... 
};

Main/CMakeLists.txt:

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)

set(PROJECT_NAME Main) # Название проекта

project(${PROJECT_NAME} VERSION 0.0.1)

set(SOURCE_LIB mainwindow.cpp main.h)    # Установка переменной со списком исходников
add_library(${PROJECT_NAME} STATIC ${SOURCE_LIB})# Создание статической библиотеки

target_include_directories(${PROJECT_NAME} PUBLIC ${GTKMM_INCLUDE_DIRS})

target_link_libraries(${PROJECT_NAME} PUBLIC ${GTKMM_LIBRARIES})

На этапе линковки выдает ошибку:

undefined reference to `MainWindow::MainWindow(_GtkApplicationWindow*, Glib::RefPtrGtk::Builder const&)

Причем, когда все было в одном файле ошибок не было. Когда попробовал разделить на подпроекты пошли ерроры.


Ответы (1 шт):

Автор решения: Anton Kuzmich

Я сделал лишнее описание класса. Надо было:

#include <gtkmm.h>
#include <iostream>
#include <string>
#include "main.h"
 
MainWindow::MainWindow(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& builder)
        : Gtk::ApplicationWindow(obj)
        , builder{builder}
            {
                ...
 
            }
MainWindow::MainWindow(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& builder, char *gladefile): Gtk::ApplicationWindow(obj)
        {
 
        }
→ Ссылка