Ad

Our DNA is written in Swift
Jump

Undefined Symbols

OC asks:

“I’m doing some Objective-C exercises from a Big Nerd Ranch book, and I’m getting these errors. I’m still pretty lost in terms of how to handle unexpected errors and stuff, so I would appreciate the help.”

I’m going into go into much greater depth here answering this question, because of “teaching a man to fish”, ya’know.

OC included this screen shot which depicts the error he was getting:

Undefined Symbols Linker Error
Building an app typically has 3 steps:

  1. Pre-Processing
  2. Compiling (into Object Code)
  3. Linking (Objects into a Binary)

Pre-Processing is the step where all these #define and #import are executed. The Compiler sees your source files thus preprocessed, so for example having imported a header tells it about the characteristics of the class the header of which you have imported. The compiling results in .o files which have references to classes and methods which are called symbols or symbolic links. When the Linker then joins all those object files into a binary (app or lib) it looks at those symbols and symbolic links and resolves these links to actually point to concrete classes and their methods.

The error on the screenshot comes from the linker as evidenced by the mention of “ld” (LLVM’s linker), “linker command failed” and the message “Undefined symbols for..”. This means that you got as far as step 3, because you probably have an import for the Logger class’ header so that the compiler does not complain in step 2. But you are missing the Logger.o object file from the linker step.

Most likely because it was not built during 2 because it is not a member of the target you are building. Another reason would be if you have the Logger class in an external static library (which is also just an archive of .o files) and forgot to add this to the linker build phase.

Getting “Undefined Symbols” means that you have to look for why the object code for the missing symbols was not available:

  • Do you have a Logger.m which is not part of your target? (does it have the check mark)
  • Do you have a static library which contains the Logger class? Is this missing from the Link with Libraries build phase?

Once you have provided the missing symbols the linker will be happy to to link it all together.

Next exercise, how I fix the following 82 linker errors in DTCoreText?

82 Linker Errors

If you look up “CTFont” in the documentation you find that these functions are part of the Core Text framework. So your next thought should be: “aha, the headers were found and this compiled, but the linker didn’t find the symbols.”

So, check in the frameworks group and what do you see?

CoreText.framework not part of target

Indeed, for this demonstration I removed the CoreText.framework from the Target membership of DemoApp. If we restore the checkmark there the build process finishes successfully.

Conclusion

You import a class header file so that the compiler knows which classes and method exist. You can only work with objects that it knows about and only call methods which are made public to the other code files via a header. Clang (the compiler) usually has no problem finding the header files because they are usually in your project folder.

But that does not mean however that ld (the linker) has the object code available for these classes. To have it you either need to have an implementation file (.m) as part of the compilation, as member of the target you are building.

Or – if you use static libraries – then the object file (.o) produced as part of the static library’s compilation will be contained in the library archive (.a). For the latter case this static lib needs to be part of the linker phase to have it’s objects be linked into your app.

If you understood the above then you will never be stumped by a linker error. Instead you immediately go search for the .m or lib containing the missing symbols and add that to your target.


Categories: Q&A

5 Comments »