【发布时间】:2014-07-25 18:00:55
【问题描述】:
好的,所以我一直在尝试使用 CMake 和 Gtk。经过相当多的无用文档的艰难跋涉后,我终于用 Gtk 等正确编译了它。 像往常一样,我从一个定义了一个回调函数的文件开始我的项目,只是为了测试一些基本功能。但是,我通常将我的程序拆分为多个文件,每个文件一个函数,并创建一个带有包含所有原型的包含保护的公共头。 这对我来说基本上是标准程序,过去我已经做过很多次了,没有任何问题。 但是,不知何故,我的 CMake 过程正在做一些我不明白的事情(嗯,很多事情),并且我收到以下错误:
CMakeFiles/gte.dir/src/main.c.o:在函数
gte_handler_about': main.c:(.text+0xb0): multiple definition ofgte_handler_about' CMakeFiles/gte.dir/src/gte_handler_about.c.o:gte_handler_about.c:(.text+0x0): 首先定义在这里 collect2:错误:ld 返回 1 个退出状态
main.c 文件相当简单,只需用 gtk_builder 加载一个 glade ui 文件并呈现它:
# include "gtk/gtk.h"
# include "gtksourceview/gtksourceview.h"
# include "gte.h"
int main( int argc, char* argv[] )
{
GtkWidget *wGTEMain;
GtkBuilder *bGTEMain;
GError *eGTE;
gtk_init( &argc, &argv );
bGTEMain = gtk_builder_new();
gtk_builder_add_from_file( bGTEMain, "gte.glade", &eGTE );
wGTEMain = GTK_WIDGET (gtk_builder_get_object ( bGTEMain, "GTEMain" ));
gtk_builder_connect_signals ( bGTEMain, NULL );
g_object_unref( G_OBJECT( bGTEMain));
gtk_widget_show( wGTEMain );
gtk_main();
return 0;
}
当我开始在我的界面中使用该小部件时,我已经包含了 gtksourceview.h。
glade 文件非常标准,只包含两个信号,一个用于自动的 gtk_main_quit,另一个用于 gte_handler_about。我会在最后加入。
我以通常的方式创建了 gte.h,并带有一些独特的标头保护,如下所示:
#ifndef PSKT_INCLUDE_GTE_H__
# define PSKT_INCLUDE_GTE_H__ 1
G_MODULE_EXPORT void gte_handler_about( GtkWidget *widget, gpointer data );
#endif /* PSKT_INCLUDE_GTE_H__ */
我已经使用 G_MODULE_EXPORT,因为我已经阅读过它们在 win32 平台上是必需的。我通常不会为宏指定一个明确的值,但我在测试中这样做了,看看这是否有所作为。 (它没有)。 最初我在这个文件中也有 gtk 头文件,但我想得更好,并将它们移回源文件。
然后,当然,我有我的单个函数,about 回调,它只是从 glade ui 文件中加载一个 gtk about 框:
#include "gtk/gtk.h"
#include "gte.h"
G_MODULE_EXPORT void gte_handler_about( GtkWidget *widget, gpointer data )
{
GtkWidget *wGTEAbout;
GtkBuilder *bGTEAbout;
bGTEAbout = gtk_builder_new();
gtk_builder_add_from_file( bGTEAbout, "gte.glade", NULL );
wGTEAbout = GTK_WIDGET( gtk_builder_get_object( bGTEAbout, "GTEAbout" ) );
gtk_dialog_run( GTK_DIALOG( wGTEAbout ) );
g_object_unref( G_OBJECT( bGTEAbout ) );
gtk_widget_destroy( wGTEAbout );
}
目前我并不太担心任何预加载或优化,并且该函数在 main.c 文件中时可以正常工作,并且原型位于 main 函数之上。
CMakeLists.txt 如下:
find_package(PkgConfig)
pkg_check_modules(DEPS REQUIRED
gmodule-2.0
gtk+-3.0
gtksourceview-3.0
)
SET(CFLAGS
${DEPS_CFLAGS} ${DEPS_CFLAGS_OTHER}
)
SET(LIB_PATHS
${DEPS_LIBRARY_DIRS}
)
add_definitions(${CFLAGS})
link_directories(${LIB_PATHS})
link_libraries( gte ${DEPS_LIBRARIES} )
file(GLOB_RECURSE SRC_FILES src/*.c)
ADD_EXECUTABLE( gte ${SRC_FILES} )
我应该注意到我花了 年 才达到这一点。我在使用 link_libraries 部分时遇到了问题。我应该注意,我只在最后添加了文件(GLOB_RECURSE ...),以避免在 ADD_EXECUTABLE 中单独列出文件,而且我现在并不担心秘密注入的源文件。
THEN 刚才作为健全性检查,我刚刚尝试了以下命令,但它们也失败了,让我相信我真的只是变成了一个白痴,不再知道无论如何编码,这可能根本不是 CMAKE 问题。 (反引号是正确的,但是当我引用命令时它们似乎没有出现......
gcc -c gte_handler_about.c
pkg-config --cflags gmodule-2.0 gtk+-3.0 gtksourceview-3.0gcc -c main.c
pkg-config --cflags gmodule-2.0 gtk+-3.0 gtksourceview-3.0gcc -o gte main.o gte_handler_about.o
pkg-config --libs gtk+-3.0 gtksourceview-3.0gte_handler_about.o:在函数
gte_handler_about': gte_handler_about.c:(.text+0x0): multiple definition ofgte_handler_about' main.o:main.c:(.text+0xb0): 首先定义在这里 collect2:错误:ld 返回 1 个退出状态
在过去,我似乎从 .o 文件构建档案没有问题,每个文件中都有单独的函数,所有函数都包括一个公共标题,如下所示:
# makefile
MYSRC= $(wildcard *.c)
MYOBJ= $(patsubst %c, %.o, $(MYSRC)
all: $(MYOBJ)
ar -ru mya.a $(MYOBJ)
%.o: %.c
gcc -Wall -O0 -g -c $^
然后编译没有问题:
gcc -o myut myut.c mya.a -lX11
.a 中的所有源代码均已编译,包括“mya.h”,myut.c 还包括“mya.h”,“mya.h”包括“X11/Xlib.h”。
我想我的问题真的是,我在这里做的和以前有什么不同?我只是需要睡觉,还是我编译 Gtk 的方式有什么不同?
对于 S&G,这里是 gte.glade 的 glade 文件:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<!-- interface-requires gtksourceview 3.0 -->
<object class="GtkAboutDialog" id="GTEAbout">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">About Geoff's Text Editor</property>
<property name="resizable">False</property>
<property name="modal">True</property>
<property name="window_position">center-always</property>
<property name="type_hint">dialog</property>
<property name="has_resize_grip">False</property>
<property name="program_name">Geoff's Text Editor</property>
<property name="version">0.0.1.0</property>
<property name="copyright" translatable="yes">Copyright (c) 2014, polarysekt, kb3c.uX</property>
<property name="website">[redacted]</property>
<property name="authors">polarysekt</property>
<property name="license_type">gpl-3-0</property>
<child internal-child="vbox">
<object class="GtkBox" id="aboutdialog-vbox1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="aboutdialog-action_area1">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<object class="GtkWindow" id="GTEMain">
<property name="can_focus">False</property>
<property name="title" translatable="yes">GTEr</property>
<signal name="delete-event" handler="gtk_main_quit" swapped="no"/>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem1">
<property name="label">gtk-new</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem2">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem3">
<property name="label">gtk-save</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem4">
<property name="label">gtk-save-as</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="menuitem5">
<property name="label">gtk-media-rewind</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<child type="submenu">
<object class="GtkRecentChooserMenu" id="recentchoosermenu1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="limit">10</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separatormenuitem2">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem5">
<property name="label">gtk-quit</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem6">
<property name="label">gtk-cut</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem7">
<property name="label">gtk-copy</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem8">
<property name="label">gtk-paste</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem9">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="mcAbout">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menuAbout">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="miAbout">
<property name="label">gtk-about</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="gte_handler_about" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkToolbar" id="toolbar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="toolbar_style">icons</property>
<property name="icon_size">2</property>
<child>
<object class="GtkToolButton" id="tbbNew">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="has_tooltip">True</property>
<property name="tooltip_markup" translatable="yes">New File</property>
<property name="tooltip_text" translatable="yes">New File</property>
<property name="label" translatable="yes">New</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-new</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="tbbLoad">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="has_tooltip">True</property>
<property name="tooltip_markup" translatable="yes">Open File</property>
<property name="tooltip_text" translatable="yes">Open File</property>
<property name="label" translatable="yes">Load</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-open</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkNotebook" id="notebook1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="show_tabs">False</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkSourceView" id="gtksourceview1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_tooltip">True</property>
<property name="left_margin">2</property>
<property name="right_margin">2</property>
<property name="show_line_numbers">True</property>
<property name="tab_width">4</property>
<property name="auto_indent">True</property>
<property name="show_right_margin">True</property>
<property name="right_margin_position">73</property>
<property name="highlight_current_line">True</property>
<property name="indent_on_tab">False</property>
</object>
</child>
</object>
</child>
<child type="tab">
<object class="GtkLabel" id="tab">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">untitled1</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child type="tab">
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child type="tab">
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="statusbar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
以及我用来运行 cmake 的 shell 脚本:
#! /bin/sh
mkdir -p build/
cd build/
cmake .. && make && cp ../res/gte.glade ./
cd ..
Grr,我知道这很简单和/或平凡,但我真的不能指望它......似乎每次我尝试使用某种平台工具包时都会发生类似的事情,并且我总是放弃并依赖 X/carbon/win32。
【问题讨论】:
-
你能把
gcc -E gte_handler_about.c `pkg-config --cflags gmodule-2.0 gtk+-3.0 gtksourceview-3.0`和gcc -E main.c `pkg-config --cflags gmodule-2.0 gtk+-3.0 gtksourceview-3.0`的输出上传到gist.github.com(或类似的) -
gist.github.com/polarysekt/21b9fe67bd3fa7d6ad4e 有趣...我看到 gte_handler_about 在两者中都扩展了...。不过,不完全知道这意味着什么,哈哈。感谢您的快速回复!
-
你确定在 main.c 的末尾,没有
get_handler_about的定义吗?如果我对此有误,那么您能否将 2 个原始 c 文件也添加到 gist 中? -
另外,我认为您正在编辑的 main.c 与 cmake 正在使用的 main.c 不同。也许运行
find . -name main.c来查看是否有多个具有该名称的文件。 -
OMG...我的 main.c 仍然包含该函数,我正在编辑一个不同的文件!不知何故,我开始在项目根目录中编辑 main.c,而我原来的 main.c 仍在 src 中!不过,我想我不会从你的建议中弄清楚这一点。根据您的建议阅读 gcc -E 的输出后,我自己编译了 main.c 并按规定工作。我并不像我想的那样疯狂,但很接近!而且,当我输入此内容时,您回答的正是情况!