PDA

View Full Version : Static Library Dependency Issues



while_e
16th May 2017, 01:30
So I use a static library as a "toolbox" of reusable code for most of my projects. I recently added something that extended the QSerialPort class. Now whenever I link to this static library, despite not using this new class, it's required that I add:

QT += serialport

or something similar if using cmake (I think this is correct):

target_link_libraries(${APP_NAME} Qt5::SerialPort)



So to clarify, here's pseudo Lib.a:

MyReceipt.h:


class MyReceipt {
... junk ...
}


MyPort.h:


#import <QSerialPort>

class MyPort: public QSerialPort {
... junk ...
}


My pseudo App:


#import <MyReceipt>

..junk...


This would result in me having to add one of the initial statements to either .pro or CMakeLists.txt even though I'm not referencing QSerialPort at all. So is there a way to avoid this? I was thinking maybe not extending QSerialPort and simply having a private object of that type, and possibly just using a forward declaration so the include could be in the implementation file instead of the interface, but would like to avoid the rewrite if possible.

Any help or insight is welcome! Thanks.

d_stranz
16th May 2017, 04:37
Does your library declare any instance of this derived class? A static variable, for example?

At worst, you could always subdivide your static library into more than one library with compartmentalized functionality so you won't need to include unused dependencies. As you probably realize, this dependency also means you may have to deploy the Qt library as well because it has been linked to, even if you use nothing in it. In the Windows world, that's likely how it would come down.

while_e
16th May 2017, 14:51
No instance of derived class within the library itself.

I've thought about dividing the library, but would really like to find a way to avoid this. For now I'll just use some pre-processor directives to exclude these classes until actually needed, but that doesn't really solve my problem, merely a band-aid.

Do you know if going the route of forward declaration in interface, and only including the header in the implementation would work? I will probably test this today if I get time.

high_flyer
16th May 2017, 16:03
The question is, why static?
If you are using it more than for one project I don't see the benefit, only disadvantages.

Be as it may, the problem you have is that your static lib depends on a dynamic lib, so any code depending on your static lib also needs to link to the dynamic lib.
If you really must use static linking, then you can build QSerialPort as a static lib as well, of if simply add the full QSerialPort code to your static lib.


Do you know if going the route of forward declaration in interface, and only including the header in the implementation would work? I will probably test this today if I get time.
This might compile but it wont link.
You need the implementation symbols.
Either add them to your static lib, or link to the dynamic lib.

This all makes little sense to me (based on the little you posted)
Qt IS a toolbox.
And its broken down to modules so you don't need to link against things you don't need.
Why you would want to statically link against a toolbox out of which you only use some things and in addition some which are part of Qt, is beyond me.
But, each to his own! :-)

while_e
16th May 2017, 17:09
The decision to static link was not entirely my own. We were dynamically linking, but because of various versioning issues (if app version == this, then library version must >= this) had popped up in production, and caused headaches like a bricked piece of hardware in the field due to an updated app but not library, it was just easier at the time to say "screw it, let's just link statically". The toolbox contains code that is re-used by all of our projects, so there's a good chunk of it that just isn't required for any given project, which yes, sounds stupid to link to statically.

Basically if some of our team members had a better grasp on versioning, and repository management, we would just dynamically link everything.

Thanks for the input!

d_stranz
16th May 2017, 18:55
Well, as I said earlier, adding the QSerialPort dependency to your toolbox translates into a configuration and deployment dependency - because of the decision to add a rarely-used Qt class to your static library, you're now required to link to and deploy that Qt library with -all- of your apps. That seems to me to be a bigger headache than splitting the code into independent static libraries.

In our development, the only static libraries we use are those that depend only on the C++ runtimes and no other third-party DLLs. Everything else goes out as DLLs which are deployed side-by-side with whatever third-party DLLs dependencies they have.

while_e
16th May 2017, 20:31
Long story short, answer to my actual question "So is there a way to avoid this?" is: No, not with the current way the library is being utilized.

Thanks for the good input.

I'll obviously be giving this some thought to figure out what would fit better in our environment. Like I said, dynamically linking caused some headaches when someone made changes to the library, pushed it to stable, and a customer checked for update and got the new library, but the application built/tested against the new library hadn't been pushed to stable yet. If the interface changes to any degree, this will cause application failure when the old app tries to use the new library. This was what initially was being avoided with static linking, not the best choice by any means, simply the easiest/quickest at the time. Best choice is obviously dynamic linking, with better version control by the engineering team.