HenryRootTwo
HenryRootTwo

Reputation: 2612

Duplicate Symbols when removing Preprocessor code

Noob build question.

When I change this;

#define NOTIFICATION_PLAYBACK_STATE_CHANGED @"SC_NOTIFICATION_PLAYBACK_STATE_CHANGED"

to this;

NSString * const NOTIFICATION_PLAYBACK_STATE_CHANGED = @"SC_NOTIFICATION_PLAYBACK_STATE_CHANGED";

I get this:

ld: 752 duplicate symbols for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Sample of the 752 duplicates:

duplicate symbol _NOTIFICATION_PLAYBACK_STATE_CHANGED in:
    /Users/myname/Library/Developer/Xcode/DerivedData/MyApp-hazegevzmypmbtbnalpiwebrhaea/Build/Intermediates/MyApp.build/Debug-iphoneos/MyApp.build/Objects-normal/armv7/SCRemoteRecordManager.o
    /Users/myname/Library/Developer/Xcode/DerivedData/MyApp-hazegevzmypmbtbnalpiwebrhaea/Build/Intermediates/MyApp.build/Debug-iphoneos/MyApp.build/Objects-normal/armv7/SCRegisterAcceptTermsViewController.o
duplicate symbol _NOTIFICATION_PLAYBACK_STATE_CHANGED in:
    /Users/myname/Library/Developer/Xcode/DerivedData/MyApp-hazegevzmypmbtbnalpiwebrhaea/Build/Intermediates/MyApp.build/Debug-iphoneos/MyApp.build/Objects-normal/armv7/SCRemoteRecordManager.o
    /Users/myname/Library/Developer/Xcode/DerivedData/MyApp-hazegevzmypmbtbnalpiwebrhaea/Build/Intermediates/MyApp.build/Debug-iphoneos/MyApp.build/Objects-normal/armv7/SCStreamingVideoViewController.o

(A search for this particular duplicate symbol returns nothing outside of the class's own .h and .m files.)

There are many other places in the code where I have replaced such a #define with a constant without objections during the build.

Can someone take a guess at what's happening here (or advise me what information I would need to post for a guess to be possible)?

Is trawling through the code replacing #defines where they have been used to create constants (leaving stuff like debug/release defs untouched) a dumb thing to do, i.e. should I be doing this differently (if at all)?

Upvotes: 1

Views: 70

Answers (1)

jscs
jscs

Reputation: 64022

You seem to have these constants defined in a header file. The header file is imported into multiple other files; the definition is thus repeated across all those files. Multiple definitions using the same name are not allowed.

What you want to do instead is to declare the constant in the header:

extern NSString * const NOTIFICATION_PLAYBACK_STATE_CHANGED;

extern indicates to the compiler "this is a name I'm going to use, but the storage and definition for it is elsewhere; let the linker handle that".

Then, in a file that imports the header, but is not itself imported anywhere, you define the string:

NSString * const NOTIFICATION_PLAYBACK_STATE_CHANGED = @"SC_NOTIFICATION_PLAYBACK_STATE_CHANGED";

The linker will find this definition, and all the copies of the extern declarations, and tie them together to be the same thing.

(It may interest you to see what errors you get if you omit each of these pieces in turn. You'll get a compiler error in one case, and a linker error in the other.)

Upvotes: 3

Related Questions