My Application tree is as follows:
├── build
├── CMakeLists.txt
├── example
│ ├── applicationwindow.cpp
│ ├── applicationwindow.h
│ └── Application.glade
└── main.cpp
2 directories, 5 files
And the CMakeLists.txt
file I created is as follows:
cmake_minimum_required(VERSION 3.1.0)
project(Example_App)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
find_package(PkgConfig)
pkg_check_modules(GTKMM gtkmm-3.0)
include_directories(${GTKMM_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS})
set(SOURCE_FILES main.cpp)
add_executable(${CMAKE_PROJECT_NAME} ${SOURCE_FILES} example/applicationwindow.cpp)
target_link_libraries(${CMAKE_PROJECT_NAME} ${GTKMM_LIBRARIES})
After a successful cmake ..
and make
when I execute the application I get the following error:
terminate called after throwing an instance of 'Glib::FileError'
Aborted (core dumped)
I have tried building this with a Makefile
but that doesn't seem to give any issues. I have also tried to look into Glib::FileError
however, I am unable to extract the exact cause of the problem. On trying the similar CMakeLists on a simpler instance like this example as denoted here: Gtkmm Example of a Application Window
It however seems to work. What might be the exact problem here?
Since you seem to be new to CMake, I will add some code around the answer provided by mohamadp91.
Your problem is that when you are running cmake ..
, the Application.glade
file is never copied into the build
directory, when you run make
and execute your software. At this point, the application tries to load a build/example/Application.glade
file, but does not find any and you get your error.
This does not happen when using plain Makefiles because you do not build you directory in build
, but directly alongside the example
directory. The application can then find the Glade file.
I made a small example to reproduce your problem. It has the same directory structure:
├── build
├── CMakeLists.txt
├── example
│ ├── CMakeLists.txt
│ └── Application.glade
└── main.cpp
It only has a main.cpp
file, which tries to load a ressource (Glade file in this case, like you), under example
. Here is the C++ code:
#include <iostream>
#include <gtkmm.h>
constexpr int FILE_ERROR = 1;
constexpr int MARKUP_ERROR = 2;
constexpr int BUILDER_ERROR = 3;
Gtk::ApplicationWindow* window = nullptr;
int main(int argc, char **argv)
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
auto builder = Gtk::Builder::create();
try
{
// Try to use Application.glade:
builder->add_from_file("example/Application.glade");
}
catch(const Glib::FileError& ex)
{
// This was your case, because the Application.glade file could
// not be located:
std::cout << "File error :" << ex.what() << std::endl;
return FILE_ERROR;
}
catch(const Glib::MarkupError& ex)
{
std::cout << "Markup error :" << ex.what() << std::endl;
return MARKUP_ERROR;
}
catch(const Gtk::BuilderError& ex)
{
std::cout << "Builder error :" << ex.what() << std::endl;
return BUILDER_ERROR;
}
//Get the GtkBuilder-instantiated Dialog:
builder->get_widget("MainWindow", window);
if(window)
{
app->run(*window);
}
delete window;
return 0;
}
The example shows how you could catch the Glib::FileError
exception and avoid a segfault. The Glade file is simple and looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkApplicationWindow" id="MainWindow">
<property name="can_focus">False</property>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkButton" id="MainButton">
<property name="label" translatable="yes">Hello World</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
</child>
</object>
</interface>
In the top level directory, I use the add_subdirectory
command to tell CMake to go inside the example
subdirectory and process the CMakeLists.txt
file located there:
cmake_minimum_required(VERSION 3.1.0)
project(Example_App)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
find_package(PkgConfig)
pkg_check_modules(GTKMM gtkmm-3.0)
include_directories(${GTKMM_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS})
set(SOURCE_FILES main.cpp)
add_executable(${CMAKE_PROJECT_NAME} ${SOURCE_FILES} main.cpp)
target_link_libraries(${CMAKE_PROJECT_NAME} ${GTKMM_LIBRARIES})
# CMake is gonna read the 'CMakeLists.txt' file located under 'example':
add_subdirectory(example)
In in that file, I simply copy the Application.glade
file under example
in the build directory:
file(COPY Application.glade DESTINATION ${CMAKE_CURRENT_BINARY_DIR})