如何为 gtkmm 应用程序创建 CMakeLists.txt?
How to create a CMakeLists.txt for a gtkmm application?
我的应用树如下:
├── build
├── CMakeLists.txt
├── example
│ ├── applicationwindow.cpp
│ ├── applicationwindow.h
│ └── Application.glade
└── main.cpp
2 directories, 5 files
而我创建的CMakeLists.txt
文件如下:
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})
在成功 cmake ..
和 make
之后,当我执行应用程序时出现以下错误:
terminate called after throwing an instance of 'Glib::FileError'
Aborted (core dumped)
我试过用 Makefile
构建它,但这似乎没有任何问题。我也尝试调查 Glib::FileError
但是,我无法提取问题的确切原因。在像这里表示的这个例子这样的更简单的实例上尝试类似的 CMakeLists:Gtkmm Example of a Application Window
然而它似乎有效。这里的确切问题可能是什么?
当你想在你的程序中有一个名为 file.glade
的文件(这个文件可以是 file.png
等任何东西),它位于资源目录中,你必须首先在程序构建目录中输入它,然后将以下代码添加到您的 CMakeList.txt
:
file(COPY resource DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
resource
是包含 file.glade
的目录,其名称可以是您想要的任何名称。在您的代码中:
auto builder = Gtk::Builder::create_from_file("resource/file.glade");
由于您似乎是 CMake 的新手,我将围绕 mohamadp91 提供的答案添加一些代码。
你的问题是,当你 运行 正在 cmake ..
时,Application.glade
文件永远不会复制到 build
目录,当你 运行 make
并执行您的软件。此时,应用程序尝试加载 build/example/Application.glade
文件,但未找到任何文件,您收到错误消息。
使用纯 Makefile 时不会发生这种情况,因为您没有在 build
中构建目录,而是直接在 example
目录旁边。然后应用程序可以找到 Glade 文件。
我做了一个小例子来重现你的问题。它具有相同的目录结构:
├── build
├── CMakeLists.txt
├── example
│ ├── CMakeLists.txt
│ └── Application.glade
└── main.cpp
它只有一个 main.cpp
文件,它试图在 example
下加载资源(在本例中为 Glade 文件,就像你一样)。这是 C++ 代码:
#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;
}
该示例显示了如何捕获 Glib::FileError
异常并避免段错误。 Glade 文件很简单,如下所示:
<?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>
在顶级目录中,我使用 add_subdirectory
命令告诉 CMake 进入 example
子目录并处理位于那里的 CMakeLists.txt
文件:
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)
在该文件中,我只是将构建目录中example
下的Application.glade
文件复制:
file(COPY Application.glade DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
我的应用树如下:
├── build
├── CMakeLists.txt
├── example
│ ├── applicationwindow.cpp
│ ├── applicationwindow.h
│ └── Application.glade
└── main.cpp
2 directories, 5 files
而我创建的CMakeLists.txt
文件如下:
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})
在成功 cmake ..
和 make
之后,当我执行应用程序时出现以下错误:
terminate called after throwing an instance of 'Glib::FileError'
Aborted (core dumped)
我试过用 Makefile
构建它,但这似乎没有任何问题。我也尝试调查 Glib::FileError
但是,我无法提取问题的确切原因。在像这里表示的这个例子这样的更简单的实例上尝试类似的 CMakeLists:Gtkmm Example of a Application Window
然而它似乎有效。这里的确切问题可能是什么?
当你想在你的程序中有一个名为 file.glade
的文件(这个文件可以是 file.png
等任何东西),它位于资源目录中,你必须首先在程序构建目录中输入它,然后将以下代码添加到您的 CMakeList.txt
:
file(COPY resource DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
resource
是包含 file.glade
的目录,其名称可以是您想要的任何名称。在您的代码中:
auto builder = Gtk::Builder::create_from_file("resource/file.glade");
由于您似乎是 CMake 的新手,我将围绕 mohamadp91 提供的答案添加一些代码。
你的问题是,当你 运行 正在 cmake ..
时,Application.glade
文件永远不会复制到 build
目录,当你 运行 make
并执行您的软件。此时,应用程序尝试加载 build/example/Application.glade
文件,但未找到任何文件,您收到错误消息。
使用纯 Makefile 时不会发生这种情况,因为您没有在 build
中构建目录,而是直接在 example
目录旁边。然后应用程序可以找到 Glade 文件。
我做了一个小例子来重现你的问题。它具有相同的目录结构:
├── build
├── CMakeLists.txt
├── example
│ ├── CMakeLists.txt
│ └── Application.glade
└── main.cpp
它只有一个 main.cpp
文件,它试图在 example
下加载资源(在本例中为 Glade 文件,就像你一样)。这是 C++ 代码:
#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;
}
该示例显示了如何捕获 Glib::FileError
异常并避免段错误。 Glade 文件很简单,如下所示:
<?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>
在顶级目录中,我使用 add_subdirectory
命令告诉 CMake 进入 example
子目录并处理位于那里的 CMakeLists.txt
文件:
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)
在该文件中,我只是将构建目录中example
下的Application.glade
文件复制:
file(COPY Application.glade DESTINATION ${CMAKE_CURRENT_BINARY_DIR})