OCMock 3.0.2 linker error with .mm test file

断了今生、忘了曾经 提交于 2019-12-22 08:23:51

问题


I am using OCMock 3.0.2, which I've installed through cocoapods for my test target:

platform :ios, '7.0'
xcodeproj 'myProject.xcodeproj'

target :myTestTarget do
  pod 'OCMock', '~> 3.0.2'
end

link_with "myTestTarget"

In my test file (myTest.mm), I've included OCMock and want to try out the new verify-in-place strategy, like so:

- (void) test_myTest
{
    MyObject *obj = [MyObject new];
    id robotMock = OCMPartialMock(obj);

    [obj testMethod];

    // some asserts
    OCMVerify([obj _internalMethodToBeCalled]);
}

So far seems normal. However, when I tried to run this specific test case, I am getting linker error:

Undefined symbols for architecture i386:
  "OCMMakeLocation(objc_object*, char const*, int)", referenced from:
      -[MyTests test_myTest] in MyTests.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I verified that OCMock was pulled in correctly and OCMLocation.h/m files are referenced too. I see that OCMMakeLocation seems to be an extern function but the .m file is there as a dependent project in my pods build target, but somehow it is not being linked. I have to make my test to be .mm since I am including some c++ files. Why would this be the problem for OCMock?


回答1:


OCMMakeLocation is declared like this

OCMLocation.h:

extern OCMLocation *OCMMakeLocation(id testCase, const char *file, int line);

OCMLocation.m:

OCMLocation *OCMMakeLocation(id testCase, const char *fileCString, int line)
{
    return [OCMLocation locationWithTestCase:testCase file:[NSString stringWithUTF8String:fileCString] line:line];
}

It's a straight C function defined outside of the Objective-C interface. I'm not knowledgeable enough about what the complier is actually doing (maybe someone else can explain it better), but to the best of my understanding, this is what's going on: Your test file is an Objective-C++ file, so it's getting complied with C++ linkage, which does name mangling (see this about name mangling). However, OCMLocation is compiled as a Objective-C file, so it gets C linkage, not C++ linkage, so no name mangling. Because your test is complied with C++ linkage, it pulls in OCMock.h and assumes it's also a C++ header, so it assumes the result of compiling it's source will be the same, which it's not going to be.

Long story short, to fix this, all you need to do is tell the compiler that OCMock.h is a C header in your test file:

#ifdef __cplusplus
extern "C" {
#endif
#import <OCMock/OCMock.h>
#ifdef __cplusplus
}
#endif



回答2:


It looks like you are building OCMock from source, you're building it for x86_64 (64-bit) only, and then try to use the binary in a project that is i386 (32-bit). Using the pre-built binaries available from the downloads page should fix your issue because these binaries are fat, they contain i386 and x86_64.

It could be the case that Cocoapods is trying to do a Debug build, which has "only active args" set to true. I don't know enough about Cocoapods to say how to force it to do a Release build, which should create fat binaries.



来源:https://stackoverflow.com/questions/24928605/ocmock-3-0-2-linker-error-with-mm-test-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!