0

In my project, I have two libraries which share 99% of code, but there are two different implementations of a critical function. The code in question is from a 3rd party and I'm not supposed to touch it, so to generate the two different libraries, I just swap one file containing the critical function for another in the build system.

The code uses a trick to define functions in different "namespaces". Basically every function definition goes through a macro that is defined on the compiler command line as -DNAMESPACE(x)=some_namespace_##x. By swapping some_namespace_ for something else in that macro definition, I can have the two different versions of the library generate different symbol names.

Because I need to test both implementations to see if they give the same output, I have an executable which links with both versions of the library. When testing, I just call the functions of interest with the different "namespaces".

Although almost all functions of this 3rd party code use this namespace trick, unfortunately the author forgot to use the trick for a few functions in his code. As a result, when compiling, I'm getting duplicate symbol errors for certain functions which I don't need to call for testing, which shouldn't even have been exported because no user of the library would ever use these functions, and whose definitions are identical (I checked).

Under Linux I can fix the duplicate symbol errors by passing the option --allow-multiple-definition to the linker, but I haven't been able to find something equivalent in macOS.

I know that the correct solution is to fix the duplicate symbols in the code, e.g. by including them in the namespace trick. If it were up to me I'd do that, but I have strict orders not to touch the 3rd party code. Ultimately I may need to argue that this correct solution needs to be employed, but I need to show that I exhausted the other avenues first.

If the description above was unclear, here is a minimal example that displays the issue.

a.c:

int f() {
    return 1;
}

int g() {
    return 2 + f();
}

b.c:

int f() {
    return 1;
}

int h() {
    return 3 + f();
}

c.c:

#include <stdio.h>

int g();
int h();

int main() {
    printf("g() = %d h() = %d\n", g(), h());
    return 0;
}

CMakeLists.txt:

project(mre)

add_library(a STATIC a.c)
add_library(b STATIC b.c)
add_executable(c c.c)
target_link_libraries(c a b)
# Uncommenting the following line under Linux results in a successful compile,
# but this option doesn't exist in macOS
# target_link_options(c PRIVATE -Wl,--allow-multiple-definition)
swineone
  • 2,296
  • 1
  • 18
  • 32

0 Answers0