如何构建使用部分程序的库';s函数? 几年前我开发了两个C++库,它们被三个C++项目使用。我将这些库编译为共享库,以便在libs更改时不必重新编译/重新链接程序。我正在将它们的编译过程移植到CMake 3.0,但在编译过程中遇到了问题

如何构建使用部分程序的库';s函数? 几年前我开发了两个C++库,它们被三个C++项目使用。我将这些库编译为共享库,以便在libs更改时不必重新编译/重新链接程序。我正在将它们的编译过程移植到CMake 3.0,但在编译过程中遇到了问题,c++,cmake,shared-libraries,osx-mavericks,C++,Cmake,Shared Libraries,Osx Mavericks,这个库不能提供一些功能;必须在主程序中定义两个函数,即使它们在库中使用。原因是这些函数的实现取决于程序的内部结构 因此,编译这些库时使用了一个标题,将所有这些函数声明为extern。下面是一个来自问题库标题的示例: extern char * Get_Name(void *b); 我使用extern关键字声明函数。在阅读了更多关于它的内容后,似乎外部可能是多余的 在x86_64 linux上,我从未遇到过任何问题,多年来一直使用这个组织 但现在,在OSX Mavericks(clang:Ap

这个库不能提供一些功能;必须在主程序中定义两个函数,即使它们在库中使用。原因是这些函数的实现取决于程序的内部结构

因此,编译这些库时使用了一个标题,将所有这些函数声明为extern。下面是一个来自问题库标题的示例:

extern char *  Get_Name(void *b);
我使用extern关键字声明函数。在阅读了更多关于它的内容后,似乎外部可能是多余的

在x86_64 linux上,我从未遇到过任何问题,多年来一直使用这个组织

但现在,在OSX Mavericks(clang:Apple LLVM版本5.1(clang-503.0.40)(基于LLVM 3.4svn))上,该库的编译失败了。这可能是我的CMake文件有问题,或者是OSX的一个怪癖。问题是在链接时(创建.dynlib文件时),它找不到函数的定义。具体错误是:

cmake VERBOSE=1
[...]
Linking CXX shared library libtiming.dylib
/Applications/CMake.app/Contents/bin/cmake -E cmake_link_script CMakeFiles/timingShared.dir/link.txt --verbose=1
/usr/bin/c++   -dynamiclib -Wl,-headerpad_max_install_names   -o libtiming.dylib -install_name @rpath/libtiming.dylib <list of .o files> /Users/me/usr/lib/libone.dylib  -Wl,-rpath,/Users/me/usr/lib
Undefined symbols for architecture x86_64:
"Function_Name(void*)", referenced from:
[...]
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
cmake VERBOSE=1
[...]
链接CXX共享库libtiming.dylib
/Applications/CMake.app/Contents/bin/CMake-E CMake_link_script CMakeFiles/timingShared.dir/link.txt--verbose=1
/usr/bin/c++-dynamiclib-Wl,-headerpad\u max\u install\u names-o libtiming.dylib-install\u name@rpath/libtiming.dylib/Users/me/usr/lib/libone.dylib-Wl,-rpath,/Users/me/usr/lib
架构x86_64的未定义符号:
“函数名称(void*)”,引用自:
[...]
ld:找不到架构x86_64的符号
叮当声:错误:链接器命令失败,退出代码为1(使用-v查看调用)
我的问题是:

< C++库有可能使用库中定义的函数吗?
  • 如果没有,那么linux编译有什么特别之处,允许我在当时编译.so动态库,即使某些符号没有在对象中定义(仅在主程序中)
  • 如果可能的话,我对CMake做了什么错事吗?上面发布的链接命令是否遗漏了什么?我应该使用不同于“链接”的东西来获取我需要的库吗
  • 谢谢。

    回答1:
    库中可能有需要解析的未解析符号。它们可以在另一个库或您的程序中解析

    但是,需要重建库才能知道程序包含哪些函数。因此,如果库需要访问程序中的特定函数,则需要使用该函数的声明重新构建该库


    通常,如果库在其库之外调用函数,则该函数将是一个未解析的符号,应在头文件中声明

    谢谢克里斯·斯塔顿;我不得不告诉链接器在链接时忽略未定义的符号

    在OSX Mavericks上,man ld指出:

     -undefined treatment
                 Specifies how undefined symbols are to
                 be treated. Options are: error, warning,
                 suppress, or dynamic_lookup.  The
                 default is error.
    
    将未定义的动态_查找传递到问题的链接过程解决了问题

    对于CMake部分,我必须在add_库()之后添加以下内容:


    你能展示一下你是如何在你的库中声明函数的吗?我想知道你的linux编译器是不是假设了
    extern
    ,而Mac OS X上的clang有点挑剔。此外,C或C++链接用于库和提供函数的翻译单元?所有的东西都是C++,图片中没有C,如果这是你所要求的。看看你的链接器是否有一个允许共享库中的未定义符号的标志。是的,库中包含一个声明所需函数的头。因为这些声明是外部的,所以在linux上,它们会导致.so文件中出现无法解析的符号。但是当程序被链接时,链接器会在程序对象中找到符号,链接成功。在OSX上,创建共享库调用找不到符号的链接器,然后退出。我对问题1感到困惑,因为它在linux上工作。
    set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")