adnan kamili
adnan kamili

Reputation: 9465

Suggestions for static library to avoid name collision

We have two libraries - lib1 and lib2. Both the libs use a third lib say lib3. If our customer uses lib1 and lib2 in the same application using static linking, the customer faces linking issues due to symbol collision as functions from lib3 are common in lib1 and lib2.

We have access to lib1, lib2, lib3 source codes. What changes should we do to avoid naming collisions?

After reading some posts, namespacing in C++ seems to solve the problem? But will it work in our case as lib3 will still be loaded twice?

Upvotes: 0

Views: 556

Answers (2)

icebp
icebp

Reputation: 1709

I'll leave an answer because this won't fit inside a comment.

As I understand you deploy some kind of software development kit for lib1 and lib2. Each SDK contains some public headers and the lib1 and lib2 static libs. Both of these libraries are statically linked with lib3, which is an internal library.

So the SDKs could look something like this:

lib1 SDK
├── lib
│   ├── lib1.lib
├── headers
│   └── lib1.h

lib2 SDK
├── lib
│   ├── lib2.lib
├── headers
│   └── lib2.h

This works great except in the cases in which a customer needs both lib1, and lib2. Our suggestion was: don't statically link lib3, but deploy it inside the lib1 and lib2 SDKs. In this case your customers will simply have to update their build scripts to also link the already included lib3. So lib1 customers will now link with lib1 and lib3; lib2 customers will now link with lib2 and lib3. You already deploy lib3 to the customers, only not as a stand-alone file, but included in the lib1 and lib2 libraries, so there's no big change here.

This means that customers who use both can pick one of the lib3s you provided and link against it.

Your SDKs now look like this:

lib2 SDK
├── lib
│   ├── lib2.lib
├── headers
│   └── lib2.h
├── dependencies
│   └── lib3.lib

(same for lib1)

There is now the risk that the customer will use lib1 1.0 which depends on lib3 1.0 and lib2 2.0 which depends on lib3 2.0, with the two lib3 versions being binary compatible (linking will succeed for both lib1 and lib2 regardless of the lib3 version), but there are API changes between the two lib3 versions that will generate runtime errors.

In this case you have to either be able to verify compatibility at build time (harder to do when you don't control the build process), or at run time (easy to do as long as the lib3 API for doing this does not change).

You could also try to accommodate these customers by providing a common SDK for lib1 and lib2 which always includes a lib3 version that is guaranteed to be compatible with both. However, this might not be a cost effective strategy for you.

EDIT: As @lalala mentioned, there are multi-threaded concerns that can make this unfeasible. For example, if lib3 is not thread safe, making lib1 and lib2 use the same lib3 will lead to race conditions, deadlocks, etc.

Upvotes: 3

adnan kamili
adnan kamili

Reputation: 9465

We finally fixed our problem using dynamic namespacing

First, define a macro for the namespace

#ifndef LIB_NAMESPACE
#define LIB_NAMESPACE SomeNameSpace
#endif

then add namespace around every class.

On compilation override the macro from the compiler command line e.g.

g++ -DMY_LIB_NAMESPACE=Lib1Namespace ...
g++ -DMY_LIB_NAMESPACE=Lib2Namespace ...

The only disadvantage is the size of the final executable will be slightly larger due to duplicate code.

Upvotes: 1

Related Questions