Linking Error: CGRectZero and CGRectOffset

I want to share another debugging tip, this something that applies to the final step of building an iPhone project, linking.

I was able to successfully compile a project that I’ve been working on, however, the build process generated an error that two symbols could not be found, CGRectZero and CGRectOffset.

The figure below shows the specific error messages (ignore the first error about .objc_class_name_BirdView for now).

Xcode Link Error

As far as the error regarding CGRectZero, here’s what I found, if you add the CoreGraphics.framework to your list of frameworks, all is well (I’ll talk more about adding frameworks in a future post as there are a few not-so-obvious things I want to point out). The Frameworks section in the Groups and Files will look similar to the figure below once the framework is in place.

There is a second option for fixing the problem is to replace the references to CGRectZero with CGRectMake(0,0,0,0). According to the CGGeometry reference, the zero rectangle is equivalent to the CGRectMake call.

As far as the error message regarding CGRectOffset, this message went away as well once the proper framework was included.

The question that I have is how did the compiler resolve the references to CGRectZero and CGRectOffset? I didn’t include any header files (other than header files that I wrote) in the implementation code. If you can share any insight on this, please post a comment.

  1. Strictly speaking the compiler didn’t resolve the reference, it is the linker’s job to resolve references to code.
    The 3 steps in compilation are
    parse
    generate
    link

    The first step creates a machine readable copy of your code and it is the only one interested in your header files. The second step takes the output of the first step and creates the machine code needed to implement your logic and the final step copies the code you need from frameworks. The third step isn’t always performed, when you create a framework for example. It is also only done once during the compilation of your program even if you have hundreds of source code files.

    The linker (ld) goes through all the object (.o) files generated in step 2 and creates a list of unresolved references that it tries to find in the frameworks, the included frameworks in turn have unresolved references that are resolved in the same way. Finally just to make things more complicated some references are resolved at run time although the linker needs to know that they can be resolved.

    /Michael

  2. Thanks Michael.

    CGRectZero is defined in CGGeometry.h and I didn’t specifically include that file. CGRectZero is listed as a global C variable in the documentation set as part of the core library, so does that explain why I don’t need to import the header in order for the compiler to understand the reference to CGRectZero in my code?

  3. The header files are used only during parsing to define stuff, they have no direct effect on the linking stage. Once the code generation is complete your object files contain a number of references to symbols that are provided by other object files. A framework is essentially a collection of object files. A symbol can be a global variable or the implementation of a method or even an old fashioned function.

    When you use a symbol defined in a framework the linker resolves that symbol by including the code block associated with it and that may include references to symbols that are as yet undefined. That is what has happened in your case, you have used a method that references CGRectZero, the underscore is added during code generation so that it’s symbols never conflict with symbols created by people.

    Frameworks are dynamically linked libraries so that the code isn’t actually included but it’s easier to understand if you ignore that fact. The fact that the code in the framework has an unresolved reference is noted by the linker which tries to resolve that symbol.

    You can use the CLI command nm to examine the symbols included in a framework. The man page refers to sections and they aren’t that obvious, the text section is read only and contains mainly code but can contain constants, the data section is initialized global variables and the bss section is unititalized global variables.

    nm /System/Library/Frameworks/AppKit.framework/AppKit
    reveals that the framework AppKit has a unresolved reference to strncpy which is provided by libc. I doubt that you include the header where strncpy is defined although it’s hard to be sure but that doesn’t affect the linker, if you use code in AppKit that uses strncpy then the linker will resolve it by including it from libc.

  4. Try a compile to the device, the simulator might not be up to it.

  5. You need to add the CoreGraphics.framework in Xcode doing this:
    Do Right-Click in the Frameworks folder and Add.. -> Existing Frameworks…
    and select this folder:

    /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.0.sdk/System/Library/Frameworks/CoreGraphics.framework

    That worked for me.

  6. Remove your Framework and exit xcode…then start xcode now import the framework and clean all targets…and dependencies and Run
    i think this can help…

Comments are closed.