Can you weak link(optional link) a static library in C++ like Objc could?

538 views Asked by At

I am developing a static library A with a mix of Objective C and C++ in Xcode, I run into the need to "weak link" another static library and Let's call it B. A calls some methods defined in B. The idea is that if B is not linked/provided, A will not throw any undefined symbols error. I know that in Objective C you can do that and in code I can rely on run time methods such as NSClassFromString or [someObject Class] to check if a certain function is present/available from another static library, but I don't know if I can achieve that in one of my .cpp source file. Please advise and thank you!

I created a very simple sample project for illustration purpose:

Library A:

Core_ObjC.h, this is the header that will be exposed

#import <Foundation/Foundation.h>

@interface Core_Objc : NSObject

-(int) calculate;

@end

Core_ObjC.mm

#import "Core_ObjC.h"
#include "Core_CPP.h"

@implementation Core_Objc

-(int) calculate{
    return calculate_Core();//Call into cpp here
}

@end

Core_CPP.cpp

#include "Core_CPP.h"
#include "NonCore_CPP.h"

int calculate_Core(){
    return calculate_NonCore();//Call into another cpp here but it's defined in Library B
}

Library B:

NonCore_CPP.cpp

#include "NonCore_CPP.h"

int calculate_NonCore(){
    return 100;
}

If I link both libraries in a sample app, the app will compile fine. However, when I link only A from the sample app, I will encounter error like:

Undefined symbols for architecture arm64:
  "calculate_NonCore()", referenced from:
      calculate_Core() in CoreFramework(Core_CPP.o)

The error does make sense to me because B will have the missing definition, but I am just looking for a solution that the compilation won't complain when there is only A.

1

There are 1 answers

0
pmdj On

So, weak linking works at the C function level as well. For details, see Apple's documentation but basically, the symbol needs to be declared using __attribute__((weak_import)), as follows

extern int MyFunction() __attribute__((weak_import));
extern int MyVariable __attribute__((weak_import));

and then you can check if its address is zero to check if it was found during link time, using e.g. if (MyFunction != NULL) or if (&MyVariable != NULL).

Your title mentions static libraries. Note that static libraries are just collections of object files, so you either link the library or you don't; there's no weak linking a static library, because by definition, it's present at build time. Or not. If you want runtime behaviour, use a dynamic library. (dylib)

The above should actually cover the example you have given: you'll just need to provide alternative code for when calculate_NonCore is unavailable, as you can't call it without crashing the program. (Makes sense, it's missing)

You mention C++ too, although your code doesn't make any obvious use of it. C++ makes this a little more complicated because of its mangled names; additionally, classes themselves don't have any linkage, so you can't test for presence of a class. The compiler seems to allow applying the weak_import attribute to member functions, static member variables, etc. but I'm not sure to what extent the NULL checks will work. Free functions should certainly not be an issue - treat them like C functions - and I'd guess that static members are probably a good candidate because you can easily take their address.

I'd probably try to avoid calling into any code that makes use of any part of a class that might not be there, and set things up such that you can simply check for the presence of a "canary" static member variable or function, which, if present, you can conclude that the whole class is present.