CMake - C - 多个源文件忽略Header Guard

时间:2014-07-25 18:00:55

标签: c gcc linker cmake

好的,所以我一直在尝试使用CMake和Gtk。在通过无用的文档进行相当多的跋涉之后,我终于用Gtk等编译了它。 像往常一样,我用一个文件开始我的项目,定义了一个回调函数,只是为了测试一些基本功能。但是,我通常将我的程序分成多个文件,每个文件一个函数,并创建一个包含所有原型的包含保护的公共头。 这对我来说基本上都是标准程序,过去我做过很多次没有任何问题。 但是,不知怎的,我的CMake过程正在做一些事情(好吧,很多事情)我不明白,而且我收到以下错误:

  

CMakeFiles / gte.dir / src / main.c.o:在函数gte_handler_about': main.c:(.text+0xb0): multiple definition of gte_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,因为我开始在界面中使用该小部件。

林间空地文件非常标准,只包含两个信号,一个用于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标题,但我认为它更好并将它们移回源文件。

然后,当然,我有我的单个函数,即关于回调,它只是从glade ui文件加载关于框的gtk:

#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单独列出文件,我不担心此时秘密注入源文件。

那么刚刚作为一个完整性检查,我只是尝试了以下命令,他们也失败了,让我相信我真的只是变成了一个白痴而不再知道如何编写任何代码,这可能根本不是CMAKE问题。 (反对是正确的,但是当我引用命令时它们似乎没有出现......

  

gcc -c gte_handler_about.c pkg-config --cflags gmodule-2.0 gtk+-3.0 gtksourceview-3.0

     

gcc -c main.c pkg-config --cflags gmodule-2.0 gtk+-3.0 gtksourceview-3.0

     

gcc -o gte main.o gte_handler_about.o pkg-config --libs gtk+-3.0 gtksourceview-3.0

     

gte_handler_about.o:在函数gte_handler_about': gte_handler_about.c:(.text+0x0): multiple definition of gte_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:

<?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。

1 个答案:

答案 0 :(得分:0)

正如用户sharth指出的那样,问题出在main.c文件中。

当我最初开始使用这个简单的测试应用时,我只是将我的main.c和我的gte.glade文件放在项目的根文件夹中,然后慢慢向外扩展。 一旦我正确加载了初始GtkBuilder对象 - 请参见下文 - 我开始使用cmake进行搜索,因为这是进行此次测试的另一个原因。

我立即注意到cmake因为我越来越接近工作而真正混乱了我的文件夹,所以我遵循了一个我注意到的其他类似项目的设计范例:lmms,{{1等等...并自动创建构建文件夹的过程,并从该文件夹中运行simon

一旦我更加了解cmake,最后让cmake ..--cflags正常工作,就像之前我在命令行或makefile中只使用--libs一样。 / p>

要做到最难的部分是pkg-config...函数,我最初认为它是link_libraries( ... )然后试图找出要指定的参数。我最初尝试target_link_libraries(...),但这似乎不够具体 - 然后是$(GTK_LIBRARIES}函数的各种展示位置。

一旦我开始工作,我想开始扩展我的小测试应用程序,我将源文件移动到target_link_libraries(...)目录并进入它。然而,这不是我第一次犯这个错误,我吹过各种文本编辑器......我有时会发现自己很快就会从命令行使用src/,而nano有时会与命令行区分开来gedit我正在移植代码,或者并排比较不同的源代码。

在这种情况下,我之前在kate中打开了kate,但是继续将文件移动到main.c目录中,同时src仍然指向原始文件。我在文件中来回移动,我必须忽略kate并将我的新更改保存到原始文件中。同时我从这个原始文件中删除了附加函数file has been changed on disk warning,并创建了两个新文件:gte_handler_about()gte_handler_about.c(带有标题保护),因为我更喜欢每个文件方法一个函数。 [类似地,当使用C ++时,我发现自己很快就会在头文件中使用内联函数来破解类直到它们成熟,然后将它们移动到单独的源文件中...这个过程有明显的错误,如此处所示。]

无论如何,我得到gte.h文件来支持两个源文件,我开始收到链接器错误。在寻找可能的解决方案的同时,我遇到了CMakeLists.txt函数,并用通配符变量替换了文件列表......在黑暗中拍摄,因为它基本上做了同样的事情......

无论如何,正如解决方案一样,我来到这里寻找一双新鲜的眼睛。在团队编码时,我经常发现看着你肩膀的家伙(或gal)可以提供对错误和错误的新见解,尤其是在我的视力模糊甚至咖啡失去效果的深夜。

说实话,我并不是那么先进,因为我知道file()的所有细节,因为我最近才开始弄乱gcc选项在汇编程序步骤之前停止。< / p>

所以最后,我谦卑自己并进入了这个网站(只有在我的搜索引擎用尽所有可能的关键字组合并且发布后)。

sharth快速回复约5分钟,并建议(根据他的评论)-E参数,我提供给gcc并输出到一个文件,然后我上传到gist,注意到,但不知道该怎么做,-S的输出中的冗余。

但是,他指出我发布的代码可能存在差异,实际编译的内容可能存在差异,而事实证明,这是确切的问题。尽管我的评论和他的评论之间有一些小的延迟(这是一个非常小的时间框架),问题得到了解决,并且我的大部分头发完好无损。

回想起来,随着许多变数发挥作用,几乎可笑的是最平凡的事情是多么令人沮丧。

本周早些时候,我选择了一个旋转空间(我以前在代码中动态生成所有gtk小部件,特别是菜单,这非常繁琐) - 我很快就遇到了问题归因于我使用树莓派的事实[我为了我的低级编码而改用它,因为我喜欢无风扇系统的舒适性,而且对于大多数应用我不需要重击机器......)但是我是得到虚假的运行时错误,我后来认为这已经剔除了我系统的一大块,以便在我的8GB闪存上释放一点空间。

在任何情况下,它都不是main.cGtk,而是普通的旧操作员错误。我喜欢pi的另一个原因是因为我通常不会使用正在运行的应用程序,这就是我在这里使用的特定机器的情况。