Code coverage on iOS Using Xcode 4.2 on Lion
Asked Answered
S

2

3

I'm trying to produce gcd a files from an iOS Xcode 4.2 (4D199) project called CocoaTouchHax on Lion and I'm having incredible trouble. I followed the steps here and I went as far as trying to build llvm/clang from source following steps here. However I continue to get this error:

Library not loaded: @executable_path/../lib/libprofile_rt.dylib

Where am I going wrong? I've tried to use the install_name_tool to fix the executable path to no avail. Am I over analyzing something? Am I missing something simple? I put this in as a "Run Script" phase prior to linking to ensure I've updated the @executable path and I use tool to examine the file after and the name is updated:

install_name_tool -id @executable_path/Users/cliff/dev/CocoaTouchHax/build/CocoaTouchHax/Build/Products/Debug-iphonesimulator/lib/libprofile_rt.dylib build/CocoaTouchHax/Build/Products/Debug-iphonesimulator/lib/libprofile_rt.dylib

What am I doing wrong? Help!

Update Merely adding lib profile_rt.dylib crashes my test run immediately giving the following error when anything is run: @executable_path/../lib/libprofile_rt.dylib So I am certain that something needs to happen or something needs to be done to the lib profile_rt.dylib prior to execution.

Another Update I tried creating a sum link to /Developer/usr/lib under /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/Developer/usr Which I believe is part of the base the path forming the current working directory when test runs. (Assuming it runs from the bin folder there.) This would, in theory, complete the relative lookup path of ../lib/libprofile_rt.dylib from that base path but it didn't work. I've tried running the install_name_tool command prior to copying the dylib in place but I still get this error:

Library not loaded: @executable_path/../lib/libprofile_rt.dylib

I don't know what I'm doing wrong. I somehow did manage to get test coverage files to emit using some combination of the above but I was not paying close enough attention and cannot reproduce the occurance. I know this can work, I just need a little more help figuring out how.

Saponin answered 10/12, 2011 at 19:40 Comment(0)
T
3

On Lion you can symlink the dylib into /usr/lib to avoid that error

sudo ln -s /Developer/usr/lib/libprofile_rt.dylib /usr/lib/libprofile_rt.dylib

I cant guarantee that that wont bust something the future however. Remember that you have done it.

Create a new configuration called "Coverage" (or whatever).

In the Coverage config variant you have created go to Build Settings and...

  • Add -fprofile-arcs and -ftest-coverage to Other C Flags
  • Switch on Generate Test Coverage Files
  • Switch on Instrument Program Flow
  • In Other Linker flags add -lprofile_rt

The reason to do it this way with a config is that you can keep your normal build untouched. Also only works on Simulator. So dont try running this on device.

And from http://mattrajca.com/post/8749868513/llvm-code-coverage-and-xcode-4

Finally, open up the Intermediates/$TARGET.build/$CONFIG/$TARGET.build/Objects-normal/$ARCH subfolder. Inside, you’ll find the aforementioned gcda and gcov files

You can open that folder with CoverStory.

Note that coverage is not cumulative (unlike Coverity) so each run starts afresh. There might be a way to change that.

Trinitrocresol answered 9/1, 2012 at 16:56 Comment(1)
Thank you!!! The missing link was a symlink from the /usr/lib folder! The working folder must be the "/usr/bin" folder which would explain why my earlier attempts to symlink didn't work. I was assuming the working folder would be the location of the unit test executable /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/Developer/usr. I now see my coverage files! Thanks again!!! :) :)Saponin
H
5

Update: In Xcode 4.3.2 (4E2002), just switch on Generate Test Coverage Files and Instrument Program Flow, the build system will link libprofile_rt for you. Xcode 4.3, and later, is a standard Mac app and the /Developer folder is gone. So, skip steps 5-7 below. You will also have to create a class file to workaround a bug in Apple's unix implementation as described here. You'll want it in the project under test.

For Xcode 4.2 (4C199) in Snow Leopard:

  1. Create a project, say MyProduct. Check Include Unit Tests.
  2. Once Xcode does its thing and loads the new project, you should have two targets, MyProduct and MyProductTests. Duplicate the MyProduct target.
  3. Select the MyProduct copy target.
  4. Go to Build Settings. Under Code Generation turn on Generate Test Coverage Files and Instrument Program Flow.
  5. Go to Build Phases. Expand Link Binary With Libraries. Click the +. Click Add Other.... Browse to /Developer/usr/lib. Choose libprofile_rt.dylib.
  6. Select the MyProductTests target.
  7. Repeat steps 4 and 5 for that target.
  8. Go to Build Settings again. Find Bundle Loader under Linking. Change the path to the MyProduct copy app. Something like $(BUILT_PRODUCTS_DIR)/MyProduct copy.app/MyProduct copy.
  9. Change your schemes so that the tests run under the MyProduct copy scheme and not MyProduct. If you're compiling clang on your own, you can figure out the details here.

That should work. Step 8 took me hours to figure out, it's the key. If you only see gcda files in the test build directory, that's the likely issue.

Homothallic answered 12/12, 2011 at 15:26 Comment(6)
Yes, I know about running on the sim vs. the device. I had an issue with the source-compiled llvm/clang where lib profile_rt.dylib only supported x64 architecture. So I reverted to using the lib profile_rt.dylib shipped w/ Xcode instead. My question is 2 fold. Is it necessary to build clang from source or did Apple fix this in the latest Xcode 4.2 (4D199)? Also, is there something wrong with the relative @executable path in libprofile_rt.dylib?Saponin
I just went through and carefully tried to follow you instructions. I still get: dyld: Library not loaded: @executable_path/../lib/libprofile_rt.dylib I think there must be a change between Xcode 4.2 (4C199) and Xcode 4.2 (4D199) that's introducing this.Saponin
Wow, bummer. I'm on Snow Leopard. I think that might explain the disparity with version numbers. It's entirely possible, experience has taught me, that what Apple shipped is a buggy mess. I'm surprised it actually works at all, actually.Homothallic
+1 for your thorough explanation for SnowLeopard users. I'm still working to resolve on Lion... :( :(Saponin
What does "otool -L /Developer/usr/lib/libprofile_rt.dylib" print for you? I'm interested in what the @executable_path looks like for you.Saponin
One thing that I had to do was setting the same compiler type (Apple LLVM Compiler 3.0) for both app and tests targets. Otherwise, .gcda and .gcno files won't get generated for app target's files. I didn't create the copy of the app target though.Cubicle
T
3

On Lion you can symlink the dylib into /usr/lib to avoid that error

sudo ln -s /Developer/usr/lib/libprofile_rt.dylib /usr/lib/libprofile_rt.dylib

I cant guarantee that that wont bust something the future however. Remember that you have done it.

Create a new configuration called "Coverage" (or whatever).

In the Coverage config variant you have created go to Build Settings and...

  • Add -fprofile-arcs and -ftest-coverage to Other C Flags
  • Switch on Generate Test Coverage Files
  • Switch on Instrument Program Flow
  • In Other Linker flags add -lprofile_rt

The reason to do it this way with a config is that you can keep your normal build untouched. Also only works on Simulator. So dont try running this on device.

And from http://mattrajca.com/post/8749868513/llvm-code-coverage-and-xcode-4

Finally, open up the Intermediates/$TARGET.build/$CONFIG/$TARGET.build/Objects-normal/$ARCH subfolder. Inside, you’ll find the aforementioned gcda and gcov files

You can open that folder with CoverStory.

Note that coverage is not cumulative (unlike Coverity) so each run starts afresh. There might be a way to change that.

Trinitrocresol answered 9/1, 2012 at 16:56 Comment(1)
Thank you!!! The missing link was a symlink from the /usr/lib folder! The working folder must be the "/usr/bin" folder which would explain why my earlier attempts to symlink didn't work. I was assuming the working folder would be the location of the unit test executable /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/Developer/usr. I now see my coverage files! Thanks again!!! :) :)Saponin

© 2022 - 2024 — McMap. All rights reserved.