Question

I'm trying to solve Can Xcode tell me if I forget to include a category implementation in my target?, and I came up with the following solution:

NSObject+Foo.h

extern int volatile canary;
void canaryCage() {
  canary = 0;
}

NSObject+Foo.m

int canary = 0;

Now, if I #import "NSObject+Foo.h" in a source file, I'll get a linker error if that NSObject+Foo.m wasn't also included in my target.

However, every time I #import "NSObject+Foo.h" I generate a duplicate _canaryCage symbol. I can't use __COUNTER__ because I only #import "NSObject+Foo.h" in implementation files. I need canaryCage to be unique across my whole symbol table.

I need something like:

#define CONCAT(x, y) x##y
#define CONCAT2(x, y) CONCAT(x, y)
extern int volatile canary;
void CONCAT2(canaryCage, __RANDOM__)() {
  canary = 0;
}

This way, if I have source files like:

Bar.m

#import "NSObject+Foo.h"

Baz.m

#import "NSObject+Foo.h"

I'll get symbols like _canaryCage9572098740753234521 and _canaryCage549569815492345, which won't conflict. I also don't want to enable --allow-multiple-definition in ld because I want other duplicate symbol definitions to cause an error. I don't want to use canaryCage for anything but a marker that I forgot to link a source file whose header I #imported.

Was it helpful?

Solution 2

This answer was close, but it resulted in canaryCage being optimized away because it was dead code.

Solution:

NSObject+Foo.h

extern int canary;
__attribute__((constructor)) static void canaryCage() {
  canary = 0;
}

NSObject+Foo.m

int canary = 0;

Unfortunately, this adds some overhead every time the category is imported, but the overhead is very minimal. If anyone knows a way to prevent canaryCage from being stripped, I'll happily mark their answer as correct.

OTHER TIPS

If you make it static, each translation unit will get its own copy, and everything else should work the way you want it to - no preprocessor gymnastics required.

static void canaryCage()
{
    canary = 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top