在封装SDK,对外提供API时。希望不暴露内部符号,免得产生冲突,给集成带来麻烦.本文演示了二种方法

原始工程

静态库(内部使用)

cat <<EOF | sudo tee internal_function.c
#include <stdio.h>
int internal_function()
{
    printf("%s\n",__FUNCTION__);
}
EOF
gcc -c internal_function.c -o internal_function.o
ar rcs libinternal_function.a internal_function.o
nm libinternal_function.a | grep "internal_function" | grep "T"
#0000000000000000 T internal_function

动态库(外部使用)

cat <<EOF | sudo tee public_function.c
#include <stdio.h>
extern int internal_function();
int public_function()
{
    printf("%s\n",__FUNCTION__);
    internal_function();
}
EOF
gcc -fPIC -shared -o libpublic_function.so public_function.c libinternal_function.a
nm libpublic_function.so | grep -w "T"
#0000000000001164 T internal_function
#0000000000001139 T public_function

readelf -s libpublic_function.so | grep -w  GLOBAL
#     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)
#     6: 0000000000001139    43 FUNC    GLOBAL DEFAULT   14 public_function
#     7: 0000000000001164    33 FUNC    GLOBAL DEFAULT   14 internal_function
#    48: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5
#    50: 0000000000001139    43 FUNC    GLOBAL DEFAULT   14 public_function
#    52: 0000000000001164    33 FUNC    GLOBAL DEFAULT   14 internal_function

可见 internal_function也对外暴露了,如果其它SDK中也有这样一个函数,后果很严重

方法一(-fvisibility=hidden):

静态库(内部使用)

cat <<EOF | sudo tee internal_function.c
#include <stdio.h>
int internal_function()
{
    printf("%s\n",__FUNCTION__);
}
EOF
# 编译选项增加 -fvisibility=hidden -fvisibility-inlines-hidden
gcc -fvisibility=hidden -fvisibility-inlines-hidden \
	-c internal_function.c -o internal_function.o
ar rcs libinternal_function.a internal_function.o
nm libinternal_function.a | grep -w "T"
#0000000000000000 T internal_function

动态库(外部使用)

cat <<EOF | sudo tee public_function.c
#include <stdio.h>
extern int internal_function();

# API增加 __attribute__ ((visibility ("default"))) 修饰
__attribute__ ((visibility ("default"))) int public_function()
{
    printf("%s\n",__FUNCTION__);
    internal_function();
}
EOF

#编译选项增加 -fvisibility=hidden -fvisibility-inlines-hidden
gcc -fvisibility=hidden -fvisibility-inlines-hidden \
	-fPIC -shared -o libpublic_function.so public_function.c \
	libinternal_function.a
nm libpublic_function.so | grep -w "T"
#0000000000001119 T public_function

readelf -s libpublic_function.so | grep -w  GLOBAL
#     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)
#     6: 0000000000001119    43 FUNC    GLOBAL DEFAULT   14 public_function
#    49: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5
#    51: 0000000000001119    43 FUNC    GLOBAL DEFAULT   14 public_function

方法二(-Wl,-Bsymbolic -Wl,–exclude-libs,ALL):

静态库(内部使用)[无修改]

cat <<EOF | sudo tee internal_function.c
#include <stdio.h>
int internal_function()
{
    printf("%s\n",__FUNCTION__);
}
EOF
gcc -c internal_function.c -o internal_function.o
ar rcs libinternal_function.a internal_function.o
nm libinternal_function.a | grep -w "T"
#0000000000000000 T internal_function

动态库(外部使用)

cat <<EOF | sudo tee public_function.c
#include <stdio.h>
extern int internal_function();
int public_function()
{
    printf("%s\n",__FUNCTION__);
    internal_function();
}
EOF

# 编译选项增加 -Wl,-Bsymbolic -Wl,--exclude-libs,ALL
gcc -Wl,-Bsymbolic -Wl,--exclude-libs,ALL \
	-fPIC -shared -o libpublic_function.so public_function.c \
	libinternal_function.a
nm libpublic_function.so | grep -w "T"
#0000000000001119 T public_function

readelf -s libpublic_function.so | grep -w  GLOBAL
#     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (2)
#     6: 0000000000001119    33 FUNC    GLOBAL DEFAULT   14 public_function
#    51: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@@GLIBC_2.2.5
#    53: 0000000000001119    33 FUNC    GLOBAL DEFAULT   14 public_function
03-11 10:53