【问题标题】:Getting undefined references when linking against a static library链接静态库时获取未定义的引用
【发布时间】:2011-03-14 05:31:51
【问题描述】:

我用 GCC 制作了一个静态库。图书馆的建设还可以。

当我使用它时,链接器会在某些函数上抛出未定义的引用错误。但是nm 说函数是在静态库中定义和导出的(标有 T)。我知道我需要将库放在需要它们的模块之后的链接顺序,所以这不是问题。

静态库是由 3 个 C 文件构建的。 A.c B.c 和 D.c D 模块依赖于 A 和 B(包括它们的标头)。

当我使用 A 和 B 中的函数时没有问题,但是当我尝试使用 D 中的任何函数时,我得到未定义的引用错误。

如果我在 A 或 B 中移动这些函数,它会起作用。但如果它们在 D 模块中,则不会。

我完全不知道发生了什么或我忽略了什么。

我正在使用 Code::Blocks 并使用纯 C 文件。

【问题讨论】:

  • 请提供更多信息,说明哪些函数在哪个 C 文件中,哪些函数获得未定义的引用(以及您是从该库中的另一个对象文件还是另一个对象调用它们)。

标签: c gcc static-libraries linker-errors undefined-reference


【解决方案1】:

也许您应该使用ranlib 或适当的ar 选项来为您的.a 文件提供索引。

【讨论】:

    【解决方案2】:

    一个多次有效的老技巧:在链接阶段列出每个静态库两次。

    即,在您的 makefile(或您正在使用的任何文件)中,输入:

    gcc -o <outfile> <liba> <libb> <libc> <liba> <libb> <libc>
    

    无论如何,我希望你能明白。

    【讨论】:

      【解决方案3】:

      我发现我在我的项目中添加了一个 .cpp 文件,我只是将它重命名为 .c。我在创建项目时选择了 C 语言而不是 C++。我不认为这会导致问题

      我认为文件扩展名决定了 IDE 何时在 gcc 和 g++ 之间进行选择。但不是。在 Code::Blocks 中,如果您添加扩展名为 .cpp 的文件,它将使用 g++。如果添加扩展名为 .c 的文件,它将使用 gcc。但是,如果您重命名文件,它将使用相同的编译器。您必须在项目选项中明确更改它。

      那个 D 模块是使用 g++ 而不是 gcc 构建的。

      当我将 IDE 设置为在构建时显示整个命令行而不仅仅是“编译 foo.c”时,我意识到了这一点。

      【讨论】:

        【解决方案4】:

        在我为简化应用程序/库构建而编写的主 make 文件中,我使用的解决方案是运行链接步骤两次。使用 -u 链接器选项在第二个链接上指定未定义的符号。

        在我的 make 文件中,我有一个这样的目标:

        undefined.txt:
            @$(generate-undefined-syms)
        

        调用此宏...第一次尝试链接...

        define generate-undefined-syms
            $(PRINTF) "$(this_makefile): Generating undefined symbols ... \n"
            $(CC) -o rubbish $(LDFLAGS) $(objects) $(LDLIBS) 2>&1 | $(GREP) 'undefined reference' > tmp.txt; \
            $(SED) 's/^.*`/-Wl,-u/g' < tmp.txt > undefined.txt; \
            rm -f tmp.txt rubbish
        endef
        

        由于我的 sed/regexp 技能不好(而且我写这些东西很仓促),我最终得到了 undefined.txt,其中包含:

        -uSomeSym'
        -uSomeOtherSym'
        

        即尾随'

        然后我使用这个 make 语法去除 's,并删除重复项

        undefined_references = $(filter-out follow, $(sort $(subst ',,$(shell cat undefined.txt))))
        

        'follow' 过滤器是因为如果一个未定义的符号被多次引用,输出中会出现“more references to XXX follow”的消息,这会导致 undefined.txt 文件中出现虚假的“follow”,例如

        -Wl, uXXXX' follow
        

        最后我第二次链接(注意对undefined.txt的依赖)

        $(application): $(library_dependencies) $(objects) undefined.txt
            $(CC) -o $@ $(LDFLAGS) $(undefined_references) $(objects) $(LDLIBS)
        

        顺便说一句,我完全推荐以下这本书,因为我能够在几天内从头开始编写一个简单的构建系统。

        使用 GNU Make 管理项目,第三版 作者:罗伯特·梅克伦堡

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-24
          • 1970-01-01
          • 1970-01-01
          • 2014-12-11
          • 1970-01-01
          相关资源
          最近更新 更多