Mixing dynamic and static linking with gcc - gcc

ALL,
I know static linking is frown upon in *nix world, but...
I made a static library that exports a class and will be used by other (dynamic) libraries.
So, as an example I have foo.a, bar.so and baz.so.
bar.so use the class from foo.a and functions from baz.so. baz.so is not written by me and so does not use anything from those 2 libraries. foo.a exported class is not using anything from bar or Baz libraries.
Generally speaking, foo.a is an interface which contains a class with a bunch of pure virtual functions that are implemented inside bar.so
So, now my question is - how do I properly link them?
TIA!!
EDIT:
I tried basic -L/path/to/library -lfoo -L/path/to/library -lbar, but am getting ld error during the run-time that class from foo is not there.

Related

Why do not symbol conflict when contain same static library?

There is static library name libstatic1.a, another static library named libstatic2.a test app named testapp
libstatic1.a has a method testcmethds
libstatic2.a linked libstatic1.a, and called testcmethds in method samecalltest
testapp linked libstatic1.a and libstatic2.a
testapp will complie successfully and normal running.
Why there didn't have symbol conflict, i use nm -a to check two .a lib, it have same method symbol.
//in libstatic1.a
//...
0000000000000000 T _testcmethds
//...
//in libstatic2.a
//...
0000000000000000 T _testcmethds
//...
Why there didn't have symbol conflict
There isn't a conflict because the linker never pulls in the object containing _testcmethds from libstatic2.a into the link.
To understand this better, read this or this.
Note: the design in which the same global symbol(s) appear in multiple libraries is exceedingly fragile. A day will come when you'll regret designing things that way.

How to pass unique_ptr object as argument to a class that is a library

I read all the questions and answers related to passing unique_ptr as argument to a class constructor and those answers worked for classes within the exe. But here im trying to pass an unique_ptr object to a class constructor that is pre-compiled as static library.
This class in the library looks something like this,
// Class declaration (in a header file)
class TScreen
{
private:
std::unique_ptr<TProcess> m_process;
public:
__fastcall TScreen(int a, std::unique_ptr<TProcess> i_process);
};
// The constructor definition (in a separate .cpp file)
__fastcall TScreen::TScreen(int a, std::unique_ptr<TProcess> i_process):
m_process(std::move(i_process))
{
}
I will be trying to instantiate the class TScreen in the exe like this,
void TScreen_Main::CallScreen()
{
std::unique_ptr<TProcess> objprocess (new TProcess());
std::unique_ptr<TScreen> objscreen (new TScreen(0, std::move(objprocess)));
}
I compiled the library and imported it to the exe. When i compile the exe, it gives me a link error like this,
[ilink32 Error] Error: Unresolved external '__fastcall TScreen::TScreen(int, std::unique_ptr<TProcess, std::default_delete<TProcess> >)' referenced from TSCREEN_MAIN.OBJ
[ilink32 Error] Error: Unable to perform link
I tried the same with boost::shared_ptr as well and it gives me the same error. But it works fine with raw pointers, but not with smart pointers and i cannot figure out why?
Thanks in advance.
Your problem here is a linking issue. Now, exactly what's going on is difficult for me to say because I never work in a Windows environment, and linking is something that (while very similar) has some distinct differences between a Unix/Linux and a Windows environment.
My guess is that if you explicitly declare your constructor to be inline, and declare that the definition is inline, it will work correctly.
This presumes that the fact that you put the declaration of the class and definition together indicates that the definition is in the header file with the class.
When the compiler sees that it's declared inline it will emit a definition into every compilation unit where it's needed. The linker should then eliminate all the duplicate definitions.
If you really are defining the constructor in some .cpp file separate from the .hpp file that the class is in, and you compiler that .cpp file into .obj file that eventually makes it into a .lib or .dll that you link against when creating the executable, then I don't know what the problem is. If this is the case, you should use the tools that should come with your development environment to see what symbols are actually in the library or the dll because somehow the symbol for the constructor definition isn't there.

gcc symbol resolution shadowing

I'm trying to add some custom code to our internal libc related to atexit handling.
In our libc we define this because we link to custom CRT files and don't use GCC's which defines this.
void *__dso_handle __attribute__((__visibility__("hidden"),__weak__)) = &__dso_handle;
GCC also adds this to binaries when linking them.
In the libc is the function atexit which just calls
int atexit(void (*func)(void))
{
return __cxa_atexit((void (*)(void*))func, NULL, __dso_handle);
}
The issue I'm facing is that the _dso_handle value used is the local one from libc when I'd like to make it dynamically fetch the one from the module that calls atexit() at runtime so that the proper dso is registered with the atexit function.
I checked attributes and I found nothing that could help there.
Note that unlike glibc, atexit is kept in the dynamic version of libc to preserve backwards compatibility with older binaries.
The issue I'm facing is that the _dso_handle value used is the local one from libc when I'd like to make it dynamically fetch the one from the module that calls atexit() at runtime
Your module can call __cxa_atexit instead, and pass in whatever dso_handle you desire.

Weak symbols and dlopen() with clang vs. gcc

I've got a library that defines something like this:
//singleton.hpp
class Singleton
{
public:
static Singleton* getInstance()
{
static Singleton* mInstance=0;
if (!mInstance)
{
mInstance=new Singleton();
}
return mInstance;
}
};
I include this header when building a couple of shared object libraries. When I build these shared object libraries with gcc (Ubuntu), the static gets marked as unique:
(nm output)
0000000000045780 u Singleton::mInstance
When I build the shared libraries with clang the same symbol gets marked as weak:
0000000000045780 V Singleton::mInstance
When I dlopen(..., RT_NOW) the gcc-built shared objects, the dynamic linker fixes everything up and seems to make a single mInstance symbol. However, when I dlopen(..., RT_NOW) the clang-built shared objects, I get a separate symbol for each library, which makes the singleton not a singleton. Is this expected behavior? Is there some way I can force the dynamic linker to behave as if the symbols were marked as unique, as they are with the gcc compilation?
Looks like https://llvm.org/bugs/show_bug.cgi?id=22281
However it is not marked as resolved and doesn't provide workarounds.

Instantiate inline class method

I write a library, this library includes a function void f() this function is a one line function and when I compile the library to shared object with -O3 gcc optimization flag it is inlined. I call it in a critical place in the code (must be as fast as possible) and I don't want to call it not inlined (hits performance substantially). The problem is that this function is part of the API that my library exposes so when library users link with my library and call this function they get undefined reference linkage error. Is there a way for my code to use the function inlined but still instantiate it in the object file so library users will be able to link and use it? (When I say "instantiate it in the object file" I mean I'd like to see it when I run objdump -t on the shared object). Just to make it clear, I'm not interested in a solution to wrap it with a function
void F() __attribute__((noinline)) { f(); }
Because I have many functions like that and I don't want to keep a copy for every function due to the enormous amount of overhead. I'm looking for a way to tell the compiler to use it inline when the definition is available to it, but still instantiate the function in the object file, so library users can link to with it too.
Check out this How can I tell gcc not to inline a function?
I found this solution the most appropriate. I'd like to note the main thing is that the code inside the library is still inlined so there is no performance penalty but users can still use the API as all functions have instantiation
Also another possible solution in the compilation level is to use -fkeep-inline-functions gcc switch which also instantiates inline functions and and uses them inlined where possible (unlike -fno-inline switch). The main problem with this switch is that if your code is heavily templated compilation time is much longer and the binary product becomes much bigger

Resources