Las bibliotecas compartidas y la vinculación en Linux (elf)
-
29-10-2019 - |
Pregunta
He leído el hilo de rosca en La creación de la Biblioteca con compatible ABI que utiliza el Boost y ahora estoy tratando de entender cómo debo enlace de mi las bibliotecas compartidas para mantener estable el ABI, y evitar problemas con la interferencia de los símbolos.
He creado el siguiente proyecto de prueba:
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
Las bibliotecas common_v1 y common_v2 debe emular a una dependencia externa de las bibliotecas a y b (como Boost).Porque common_v1 y common_v2 es considerado como bibliotecas externas, prefiero no cambiar su sistema de construcción (y no por no cambiar las banderas están compilados con).
El proyecto anterior, compila bien, pero no funciona!Cuando la aplicación de la prueba se ejecuta saltos en la instrucción assert.
Esto me hace creer que la misma definición de común se utiliza en ambos liba y la libb.¿Por qué es este el caso, y lo que estoy haciendo mal?
Solución
Usted puede arreglar su programa de pruebas mediante el uso de --retain-symbols-file
opción de ld cuando la creación de su a
y b
las bibliotecas y sólo conservan a()
y b()
símbolos, de modo que common()
símbolo de no ser exportados por estas bibliotecas (y, por tanto, una biblioteca no intente utilizar common()
símbolo de otra):
--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.
También puede utilizar --version-script
opción:
--version-script=version-scriptfile Specify the name of a version script to the linker.
donde el version-scriptfile
es la siguiente:
FOO { global: a; b; # symbols to be exported local: *; # hide others };
Temas relacionados con: