- Anwendung verwendet Bibliothek A 1.0.
- Bibliothek B verwendet eine neuere Version der Bibliothek A 2.0 mit inkompatiblem ABI/Verhalten.
- Anwendung möchte ältere Version der Bibliothek A 1.0 und B verwenden auch mit letzterem implizit Verwendung einer neueren Version der Bibliothek A 2.0 im gleichen Anwendungskontext.
Ich habe versucht, diesen Ansatz für mein Szenario umsetzbar zu machen , und fand, dass es „fast“ funktioniert.
Bedenken Sie, dass wir eine Bibliothek A 1.0 haben wie folgt:
Code: Select all
// liba1.cpp
const char* doSomeA() { return "liba1::doSomeA()"; }
Code: Select all
// liba2.cpp
const char* doSomeA() { return "liba2::doSomeA()"; }
Code: Select all
// libb.cpp
#include
extern const char* doSomeA();
void doSomeB() { printf("libb::doSomeB(%s)\n", doSomeA()); }
Code: Select all
// app.cpp
#include
extern const char* doSomeA();
extern const char* doSomeB();
int main() {
printf("%s .. ", doSomeA());
doSomeB();
return 0;
}
Code: Select all
LIBA_1.0 {
global: *;
};
Code: Select all
LIBA_2.0 {
global: *;
};
Code: Select all
rm -f lib*.so
rm -f app00 app10 app11
# build library 'a 1.0' with (liba1v.so) and without (liba1.so) symbol versions
g++ liba1.cpp -g -fpic -shared -o liba1.so -Wl,-soname,liba1.so
g++ liba1.cpp -g -fpic -shared -o liba1v.so -Wl,-soname,liba1v.so -Wl,--version-script,liba1.map
# build library 'a 2.0' with (liba2v.so) and without (liba2.so) symbol versions
g++ liba2.cpp -g -fpic -shared -o liba2.so -Wl,-soname,liba2.so
g++ liba2.cpp -g -fpic -shared -o liba2v.so -Wl,-soname,liba2v.so -Wl,--version-script,liba2.map
# build library 'b' linked to either versioned (liba2v.so) or unversioned (liba2.so) library 'a'
g++ libb.cpp -g -fpic -shared -o libb2.so -Wl,-soname,libb2.so -Wl,--no-undefined -L. -la2
g++ libb.cpp -g -fpic -shared -o libb2v.so -Wl,-soname,libb2v.so -Wl,--no-undefined -L. -la2v
# build application linking to libraries 'b' (implicitly depending on 'a 2.0') and 'a 1.0'.
g++ app.cpp -g -o app00 -Wl,-rpath,`pwd` -L. -lb2 -la1
g++ app.cpp -g -o app10 -Wl,-rpath,`pwd` -L. -lb2v -la1
g++ app.cpp -g -o app11 -Wl,-rpath,`pwd` -L. -lb2v -la1v
LD_LIBRARY_PATH=$PWD ./app00
LD_LIBRARY_PATH=$PWD ./app10
LD_LIBRARY_PATH=$PWD ./app11
Code: Select all
liba1::doSomeA() .. libb::doSomeB(liba1::doSomeA())
liba1::doSomeA() .. libb::doSomeB(liba1::doSomeA())
liba1::doSomeA() .. libb::doSomeB(liba2::doSomeA())
Die dritte Kombination (beide Bibliotheken A 1.0 und 2.0 haben versionierte Symbole) zeigt, dass das Problem gelöst ist. Für diese Option müssen jedoch beide Versionen 1.0 und 2.0 von Bibliothek A geändert werden.
Die 2. Kombination (Bibliothek A 1.0 verwendet nicht versionierte Symbole und A 2.0 - versioniert) schlägt immer noch fehl. Es scheint, dass der Linker selbst dann, wenn die Bibliothek auf versionierte Symbole verweist, immer noch nicht versionierte Symbole akzeptiert, wenn diese bereits geladen sind.
In Anbetracht der Tatsache, dass Bibliothek A 1.0 nicht geändert werden kann (aber A 2.0 und Bibliothek B könnten geändert werden) – gibt es eine Möglichkeit, dieses Verhalten zu vermeiden?