代码之家  ›  专栏  ›  技术社区  ›  Calmarius

在链接静态库时获取未定义的引用

  •  2
  • Calmarius  · 技术社区  · 15 年前

    我用gcc创建了一个静态库。图书馆的建设还可以。

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

    静态库是从3个C文件构建的。A.C.B.C和D.C D模块取决于A和B(包括其标题)。

    当我使用来自a和b的函数时没有问题,但是当我尝试使用来自d的任何函数时,我会在它们上得到未定义的引用错误。

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

    我完全不知道发生了什么,或者我被忽视了什么。

    我正在使用code::blocks并使用普通的C文件。

    4 回复  |  直到 13 年前
        1
  •  2
  •   adamk    15 年前

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

    也就是说,在你的makefile(或你正在使用的任何东西)中,放:

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

    不管怎样,我希望你能明白。

        2
  •  1
  •   Calmarius    15 年前

    我发现我把一个.CPP文件添加到我的项目中,我刚刚把它重命名为.c。我不认为这会引起问题

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

    D模块是用G++而不是GCC构建的。

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

        3
  •  1
  •   Matthew Mckay-Davies    13 年前

    在我为简化应用程序/库构建而编写的master 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语法删除的,并删除重复的

    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管理项目,第三版 作者:罗伯特·梅克伦堡

        4
  •  0
  •   Jens Gustedt    15 年前

    也许你应该用 ranlib 或者合适的 ar 为.a文件提供索引的选项。