I have two dynamic libraries and one executable:
- libOtherLibrary.so
- This is an existing open-source library written by someone else.
- libMyLibrary.so
- This is my own library that depends on libOtherLibrary.so.
- exe
- This is my own executable that depends on both libraries.
As a test to see when a specific function is called, I added a print statement to an inline function of libOtherLibrary.so (code details shouldn't matter):
template<class T>
inline void className<T>::clear() const
{
Info << "Hello World!" << endl; // My message!
if (isTmp() && ptr_)
{
if (ptr_->unique())
{
delete ptr_;
ptr_ = 0;
}
else
{
ptr_->operator--();
ptr_ = 0;
}
}
}
I then recompiled libOtherLibrary.so, followed by recompiling libMyLibrary.so. Finally I relinked (so no recompilation) exe.
The result was that any call to className<T>::clear()
initiated in libMyLibrary.so used the old implementation of this inline method, whereas any call to className<T>::clear()
initiated by libOtherLibrary.so used the new implementation.
When I then decided to also recompile exe (followed by linking it), the result was that the new implementation was always used.
My question is: Can someone explain to me why exe required recompilation, rather than relinking only?
That is, the inlining of the function className<T>::clear()
of libOtherLibrary.so should occur during the compilation stage of libMyLibrary.so, doesn't it? After all, it is a function contained in libMyLibrary.so whom calls className<T>::clear()
. Then I'd expect that linking exe is sufficient, as exe does not call this particular inline function. The linker alone will take care of any changed ABI compatability.
Because, for your specific use-case, without it, you will inccur the wrath of ODR violation.
When you have a function-template say:
And it is ODR used in multiple translation units (.cpp file). It's instantiation will be defined in each one of such translation unit because function-templates are implicitly
inline
.The rules for such multiple definition are stated here basic.def.odr/6. And one of the listed requirements states that "each definition of D shall consist of the same sequence of tokens;".
Modifying that function template and recompiling some translation units making ODR use of it, and linking your program, without recompiling all the translation units making ODR-use of it violates the holy One Definition Rule of C++.
Compiler toolchains are not required to diagnose it.