Linux上的共享库和链接(elf)

时间:2011-12-07 07:09:39

标签: c++ c compilation linker abi

我已阅读Creating Library with backward compatible ABI that uses Boost上的帖子,我现在正试图了解如何链接我的共享库以保持稳定的ABI,并避免干扰符号的问题。

我创建了以下简单的测试项目:

cat <<EOF > a.c
#define ABI __attribute__((visibility("default")))

int common();
int ABI a() { return common() + 1; }
EOF

cat <<EOF > b.c
#define ABI __attribute__((visibility("default")))

int common();
int ABI b() { return common() + 2; }
EOF

cat <<EOF > common_v1.c
int common() { return 1; }
EOF

cat <<EOF > common_v2.c
int common() { return 2; }
EOF

cat <<EOF > test.c
#include <assert.h>

int a();
int b();

int main(int argc, const char *argv[])
{
    assert( a() + b() == 6 );
    return 0;
}
EOF

cat <<EOF > CMakeLists.txt
cmake_minimum_required(VERSION 2.8)

project(TEST)

add_library(common_v1 STATIC common_v1.c)
add_library(common_v2 STATIC common_v2.c)

SET_SOURCE_FILES_PROPERTIES( a.c b.c COMPILE_FLAGS -fvisibility=hidden )
add_library(a SHARED a.c)
target_link_libraries(a common_v1)

add_library(b SHARED b.c)
target_link_libraries(b common_v2)

add_executable(test test.c)
target_link_libraries(test a b)
EOF

库common_v1和common_v2应模拟库a和b的外部依赖关系(如Boost)。因为common_v1和common_v2被认为是外部库,所以我宁愿不改变它们的构建系统(并且不改变它们编译的标志)。

上面的项目,编译很好,但它不起作用!执行测试应用程序时,它会跳转到assert语句。

这让我相信在liba和libb中都使用了相同的common定义。为什么会这样,我做错了什么?

1 个答案:

答案 0 :(得分:0)

您可以在创建--retain-symbols-filea库时使用ld b选项修复测试计划,并仅保留a()和{{1 }}符号,因此这些库不会导出b()符号(因此一个库不会尝试使用另一个库中的common()符号):

  --retain-symbols-file filename
        Retain only the symbols listed in the file filename, discarding all
        others. filename is simply a flat file, with one symbol name per line.

您也可以使用common()选项:

  --version-script=version-scriptfile
        Specify the name of a version script to the linker.

--version-script如下:

  FOO {
    global: a; b; # symbols to be exported
    local: *;     # hide others
  };

相关主题: