如何构建一个使用某些程序功能的库?

时间:2014-07-31 01:07:09

标签: c++ cmake shared-libraries osx-mavericks

几年前我开发了几个C ++库,这些库被三个C ++项目使用。我将库编译为共享库,以便在libs更改时不必重新编译/重新链接程序。我正在将他们的编译过程移植到CMake 3.0,但是在编译它时遇到了麻烦。

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

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

extern char *  Get_Name(void *b);

我使用 extern 关键字声明了这些功能。在阅读了更多关于它之后,似乎 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)

我的问题是:

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

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

谢谢Chris Statton;我不得不告诉链接器在链接时忽略未定义的符号。

在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.

-undefined dynamic_lookup 传递给问题的链接过程解决了问题。

对于CMake部分,我必须在 add_library()之后添加以下

set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")