Link error while building a unit test target

24,121

Solution 1

Make sure that the FRRCategory source file has been added to your Compile Sources for your unit test target.

Xcode 4:

Project Navigator -> "[Project Name]" -> Under Targets select your unit test target -> Build Phases -> Expand Compile Sources -> Click + at bottom of Compile sources and add the correct source file.

Solution 2

Follow the instructions here. It doesn't require you to add any files to compile sources.

I first missed that "Symbols Hidden by Default=NO" should be for your app target, not test target.

It worked for me anyway (tm).

Solution 3

Another gotcha that you may hit is if your unit test is using C functions (or similar) that aren't used in the actual app.

This may be restricted to having a sub-project. In my case

  • App
    • Sub-project
      • A C library embedded (i.e. .c and .h files compiled directly inside)

My unit test used a few of the C functions that were not used anywhere else, and these were stripped from the app binary (NOT from the sub project's .a file).

The fix is to

  1. turn off "Dead Code Stripping" for the app's Debug build.* and
  2. make sure your unit tests are using Debug and not Release, in the Scheme settings.

(* don't do this to the release configs as it'll bloat the app with code that is never called).

Solution 4

You should only refer to a folder inside your import if your file is inside a framework. Otherwise, once you added your file to the project, simply do #import "FRRCategory.h". Well, unless you did something weird with your Header Search Paths.

Share:
24,121
cfischer
Author by

cfischer

Updated on November 10, 2021

Comments

  • cfischer
    cfischer over 2 years

    I have a XCode4 / iOS project with a regular target and unit test target. Everything works fine, except when I try to #import one of my classes in my test class and try to use it. If I try to build the unit test target, I get the following link error:

    Undefined symbols for architecture i386:
      "_OBJC_CLASS_$_FRRCategory", referenced from:
          objc-class-ref in CategoryTests.o
    ld: symbol(s) not found for architecture i386
    collect2: ld returned 1 exit status
    

    In CategoryTests.m I'm importing the header file in this way:

    #import "../todoro/FRRCategory.h"
    

    What am I doing wrong?

  • cfischer
    cfischer about 13 years
    Adding the files to the compile sources removed the error. What are those "compile sources" anyway and what's the rationale of forcing you to manually adding files from your main target?
  • cfischer
    cfischer about 13 years
    It didn't remove the error, but I had no idea it wasn't necessary to include the folder. Thanks!
  • Jano
    Jano about 13 years
    Each target uses an independent set of source files. Either you didn't create the test target as a duplicate of your main target, or during the creation of FRRCategory you didn't select both targets.
  • Jon Reid
    Jon Reid about 13 years
    It depends which unit testing framework you're using. Are you using SenTestingKit that comes with Xcode 4, or something else? …If you're using SenTestingKit, then you don't want to add the code under test to your test target.
  • Joe
    Joe about 13 years
    Compile sources are all of your implementation files that you need to have compiled for a target. When you have multiple targets each maintains there own set of compile sources and when you go to add new or existing files to the project you should see a checkbox option for which targets that new file should be included in. This includes resources such as images and interfaces as well code.
  • febeling
    febeling almost 13 years
    This the answer most people want to follow imo, not the one the questioner checked. This way the the application build product is build like for standalone use, and the tests link against it. The alternative is to replicate all build settings, linker settings, etc. to build the source separately with the unit test.
  • carlos
    carlos almost 13 years
    This is not the correct answer to this issue imo. Check answer below this one.
  • ColdLogic
    ColdLogic almost 13 years
    Lol, even after reading your comment I still messed up and needed the "Symbols Hidden by Default=NO" on my app target, not the test one. +1
  • scorpiozj
    scorpiozj almost 13 years
    it helps. And I found the sample code of Apple has the same settings.Thanks!
  • Robert Gowland
    Robert Gowland over 12 years
    This answer works, but is painful if you're testing more than a couple classes (which I hope you are). See @Martin Wickman's answer.
  • Joe
    Joe over 12 years
    @Ertai I agree the answer below is now correct and I as well have upvoted it months ago. But do note the difference in dates between to the two answers. Maybe consider convincing the OP to accept the other answer rather than continually downvote this one.
  • Tom van Zummeren
    Tom van Zummeren about 12 years
    It worked for me as well! I also think this is the only correct answer! Not the one marked as the correct one above... The one marked as correct is only a hack to get things kind of working.
  • mxcl
    mxcl over 11 years
    This is indeed the only correct answer. The other answers compile two copies of your sources into what becomes the instantiated test bundle. While generally this will be fine, if there are bugs in the build-toolchain you would get very strange and hard-to-debug side-effects.
  • Max Seelemann
    Max Seelemann over 11 years
    Thank you, this is the first thing that helped!
  • qnoid
    qnoid over 11 years
    Since the question specifically relates to Unit Testing, following the guide on the link contradicts Apple's one developer.apple.com/library/mac/#documentation/DeveloperTool‌​s/…
  • Hulvej
    Hulvej almost 11 years
    the answer below is by far the best answer, especially if you have many sources
  • vpathak
    vpathak over 9 years
    While following the list of steps here, just make sure you add a cocoa touch test target (he says cocoa test target). had some issues with architecture type before adding the cocoa touch test target instead of cocoa test target
  • phatblat
    phatblat over 9 years
    The linked post above helped me to resolve this issue in Xcode 6.2 using the Quick framework for tests. In my case, only the BUNDLE_LOADER build setting had to be set.
  • nazbot
    nazbot about 9 years
    THIS IS THE WRONG ANSWER - see below. Don't mean this as rude to the answerer, just trying to save other people any wasted time in case they miss it.
  • xySVerma
    xySVerma about 9 years
    Symbols Hidden by default = NO for debug mode solved the problem even for X-Code 6.3 for my newly added test target. Thanks.
  • amleszk
    amleszk almost 8 years
    This was this issue when trying to run unit tests on device architecture arm64. Thanks
  • yurgis
    yurgis about 7 years
    this solution does not seem to work for extension unit tests, more solutions are here: stackoverflow.com/questions/24627600
  • Amit Battan
    Amit Battan almost 7 years
    not work for me :( I have static library need to write unit test. Code compile and build successfully but test case fail unrecognized selector. It works fine when I add .m file in test target