I'm writing a framework using Objective C++ and I am having trouble setting up unit tests for it.
Compiling just the framework target works fine.
But when I tell Xcode to compile and run the test bundle I get:
Ld ~/Library/Developer/Xcode/DerivedData/TestFramework-axdefcbatoubjbbfqiyxildilobl/Build/Products/Debug/TestFrameworkTests.octest/Contents/MacOS/TestFrameworkTests normal x86_64
cd "~/Projects/TestFramework"
setenv MACOSX_DEPLOYMENT_TARGET 10.7
"/Applications/Xcode 4.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++" -arch x86_64 -bundle -isysroot "/Applications/Xcode 4.5.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk" -L~/Library/Developer/Xcode/DerivedData/TestFramework-axdefcbatoubjbbfqiyxildilobl/Build/Products/Debug -L/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib -F~/Library/Developer/Xcode/DerivedData/TestFramework-axdefcbatoubjbbfqiyxildilobl/Build/Products/Debug "-F/Applications/Xcode 4.5.app/Contents/Developer/Library/Frameworks" -filelist ~/Library/Developer/Xcode/DerivedData/TestFramework-axdefcbatoubjbbfqiyxildilobl/Build/Intermediates/TestFramework.build/Debug/TestFrameworkTests.build/Objects-normal/x86_64/TestFrameworkTests.LinkFileList -mmacosx-version-min=10.7 -v -fobjc-arc -fobjc-link-runtime -fprofile-arcs -stdlib=libc++ -framework SenTestingKit -framework Cocoa -framework TestFramework -o ~/Library/Developer/Xcode/DerivedData/TestFramework-axdefcbatoubjbbfqiyxildilobl/Build/Products/Debug/TestFrameworkTests.octest/Contents/MacOS/TestFrameworkTests
Apple clang version 4.0 (tags/Apple/clang-421.10.48) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.4.0
Thread model: posix
"/Applications/Xcode 4.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -dynamic -arch x86_64 -bundle -macosx_version_min 10.7.0 -syslibroot "/Applications/Xcode 4.5.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk" -o ~/Library/Developer/Xcode/DerivedData/TestFramework-axdefcbatoubjbbfqiyxildilobl/Build/Products/Debug/TestFrameworkTests.octest/Contents/MacOS/TestFrameworkTests -L~/Library/Developer/Xcode/DerivedData/TestFramework-axdefcbatoubjbbfqiyxildilobl/Build/Products/Debug -L/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib -filelist ~/Library/Developer/Xcode/DerivedData/TestFramework-axdefcbatoubjbbfqiyxildilobl/Build/Intermediates/TestFramework.build/Debug/TestFrameworkTests.build/Objects-normal/x86_64/TestFrameworkTests.LinkFileList -framework SenTestingKit -framework Cocoa -framework TestFramework -force_load "/Applications/Xcode 4.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_macosx.a" -framework Foundation -lobjc -lc++ "/Applications/Xcode 4.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/4.0/lib/darwin/libclang_rt.profile_osx.a" -lSystem "/Applications/Xcode 4.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/4.0/lib/darwin/libclang_rt.osx.a" -F~/Library/Developer/Xcode/DerivedData/TestFramework-axdefcbatoubjbbfqiyxildilobl/Build/Products/Debug "-F/Applications/Xcode 4.5.app/Contents/Developer/Library/Frameworks"
Undefined symbols for architecture x86_64:
"Foo::Bar::Bar()", referenced from:
-[FooBar_Tests testBaz] in FooBar_Tests.o
"Foo::Bar::baz() const", referenced from:
-[FooBar_Tests testBaz] in FooBar_Tests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have:
C++ Language Dialect: c++11
C++ Standard Library: libc++
set on both build targets (framework & test bundle).
And I am of course linking against the framework in my test bundle target.
Furthermore, all framework headers are marked public.
I also tried adding the framework files to the test bundle's target and leaving them out. None of these fixed the problem.
I am a bit puzzled as to what's going wrong here, right now. Any ideas?
This is how my C++ class looks like (kind of):
//FooBar.hh
namespace Foo {
class Bar {
public:
bool baz() const;
}
}
//FooBar.mm
#import "FooBar.hh"
namespace Foo {
bool Bar::baz() const {
return true;
}
}
And this my test case:
//FooBar_Tests.hh
#import <SenTestingKit/SenTestingKit.h>
#interface FooBar_Tests : SenTestCase
#end
//FooBar_Tests.mm
#import "FooBar_Tests.hh"
#import <TestFramework/FooBar.hh>
//this one fails as well (compiles fine, fails one linkage):
//#import "FooBar.hh"
#implementation FooBar_Tests
- (void)testBaz {
Foo::Bar bar();
STAssertEquals(bar.baz(), true, nil);
}
Edit: Split code up into .hh&.mm files. Still getting the same errors though.
One possible problem is that your unit tests are in the header file. Header files do not do much in OCUnit. You can even get rid of the header file and put all your test case code in the implementation file. Add an Objective-C unit test class to your project, give it the extension .mm, and move your test case code there. Does that fix the problem?
When I unit test C++ code with OCUnit, I find I have to add the C++ files in my app to the unit test target to avoid link errors. I'm not sure if it applies to Objective-C++ code, but it's something to look into.
I eventually added a new unit test target to my project, enabled C++11 and tried compiling/running it. Success.
Somehow my original unit test target must have gone bad in regards to C++11. Had compiled just fine before.
Now it's time to migrate my test cases to the new test bundle, I guess.
…and I thought I was going mad. Oh well…
Related
I'm sure this is a total nube question but if someone could explain to me what's going wrong I'd be very grateful.
I create a new Cocoa App in XCode. Call it LinkerTest. This basic app will build and run, putting a simple blank window up.
Add a new .cpp file using the C++ File template. Call it Test.cpp. This creates Test.h too.
In Test.cpp add a simple function:
int TestMe(void)
{
return 1;
}
Declare my function in Test.h
int TestMe(void);
In my AppDelegate.m (which was created automatically when I create the app) add
#include "Test.h"
In the applicationDidFinishLaunching method add:
printf("Test = %d\n", TestMe());
Now try to build. Everything compiles ok, but it fails to link. This is the linker command:
Ld Build/Products/Debug/LinkerTest.app/Contents/MacOS/LinkerTest normal x86_64
cd /Users/chip/LinkerTest
export MACOSX_DEPLOYMENT_TARGET=10.10
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk -L/Users/chip/LinkerTest/Build/Products/Debug -F/Users/chip/LinkerTest/Build/Products/Debug -filelist /Users/chip/LinkerTest/Build/Intermediates/LinkerTest.build/Debug/LinkerTest.build/Objects-normal/x86_64/LinkerTest.LinkFileList -Xlinker -rpath -Xlinker #executable_path/../Frameworks -mmacosx-version-min=10.10 -stdlib=libc++ -fobjc-arc -fobjc-link-runtime -Xlinker -dependency_info -Xlinker /Users/chip/LinkerTest/Build/Intermediates/LinkerTest.build/Debug/LinkerTest.build/Objects-normal/x86_64/LinkerTest_dependency_info.dat -o /Users/chip/LinkerTest/Build/Products/Debug/LinkerTest.app/Contents/MacOS/LinkerTest
And this is the error I get:
Undefined symbols for architecture x86_64:
"_TestMe", referenced from:
-[AppDelegate applicationDidFinishLaunching:] in AppDelegate.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
So any idea what I've done wrong? Seems to me that adding the file it should link too, but it doesn't. I know the file Test.cpp gets compiled, if I add garbage to the file, then the compiler immediately yacks on that garbage.
EDIT: A couple more things.
1) Looking at this stackoverflow(Getting XCode to include, compile and link existing (C++) codebase in XCode 4.3(.1)) question it seems similar but not my issue. I can confirm that my test.cpp is listed in my Compile Sources under Build Phases.
2) Looking in the LinkerTest/Build/Intermediates/LinkerTest.build/Debug/LinkerTest.build/Objects-normal/x86_64 folder I find Test.o, Test.d, and Test.dia which suggests to me that Test.cpp is in fact compiling. In that folder I also find LinkerTest.LinkFileList which when opened with a text editor shows that Test.o should be linked.
The answer is that when you create a default Cocoa app the AppDelegate file is a .m file. Changing that file to be AppDelegate.mm fixes the problem. My uninformed guess is that a .m file will only handle .c files and to correctly handle .cpp files you must use .mm files. Why xcode's default files for a default Cocoa App wouldn't be .mm files is beyond my pay grade, but there it is.
I have been using a simple command line app from within Xcode (not directly via swiftc) to test code that otherwise gives Playground fits. After several months, and compiler updates, I cannot link seem to link a trivial and contrived snippet that extends a Swift Array. I have code like this in an iOS app, and it compiles just fine. I must have missed the memo at some point, but I am not sure what that was.
Here is a simple snippet (in a main.swift file) that:
protocol MyProtocol : SequenceType {
func fubar()
}
extension Array : MyProtocol {
func fubar() {}
}
println("Hello, World!")
That causes a multitude of linking errors like:
Ld /Users/Redacted/Library/Developer/Xcode/DerivedData/Hacks-Redacted/Build/Products/Debug/Hacks normal x86_64
cd /Users/Redacted/development/tests/Hacks
export MACOSX_DEPLOYMENT_TARGET=10.10
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk -L/Users/Redacted/Library/Developer/Xcode/DerivedData/Hacks-Redacted/Build/Products/Debug -F/Users/Redacted/Library/Developer/Xcode/DerivedData/Hacks-Redacted/Build/Products/Debug -filelist /Users/Redacted/Library/Developer/Xcode/DerivedData/Hacks-Redacted/Build/Intermediates/Hacks.build/Debug/Hacks.build/Objects-normal/x86_64/Hacks.LinkFileList -mmacosx-version-min=10.10 -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift_static/macosx -Xlinker -force_load_swift_libs -lswiftRuntime -lc++ -framework Foundation -lcurses -Xlinker -add_ast_path -Xlinker /Users/Redacted/Library/Developer/Xcode/DerivedData/Hacks-Redacted/Build/Intermediates/Hacks.build/Debug/Hacks.build/Objects-normal/x86_64/Hacks.swiftmodule -Xlinker -dependency_info -Xlinker /Users/Redacted/Library/Developer/Xcode/DerivedData/Hacks-Redacted/Build/Intermediates/Hacks.build/Debug/Hacks.build/Objects-normal/x86_64/Hacks_dependency_info.dat -o /Users/Redacted/Library/Developer/Xcode/DerivedData/Hacks-Redacted/Build/Products/Debug/Hacks
duplicate symbol __TTWSaSs12SequenceTypeFS_8generateUS__USs13GeneratorType___fRQPS_FT_QS1_9Generator in:
/Users/Redacted/Library/Developer/Xcode/DerivedData/Hacks-Redacted/Build/Intermediates/Hacks.build/Debug/Hacks.build/Objects-normal/x86_64/main.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift_static/macosx/libswiftCore.a(Swift.o)
duplicate symbol __TTWSaSs12SequenceTypeFS_oi2tgUS__USs13GeneratorType___fMQPS_FTS1_TVSs19_UnderestimateCountT___Si in:
/Users/Redacted/Library/Developer/Xcode/DerivedData/Hacks-Redacted/Build/Intermediates/Hacks.build/Debug/Hacks.build/Objects-normal/x86_64/main.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift_static/macosx/libswiftCore.a(Swift.o)
... <>
Could there be some new linking requirements that I missed? Seems like it must be something simple, but it is escaping me. For all it's worth, I have duplicated this on a separate machine and am using Xcode 6.1.1 (6A2008a) - latest as of the time of posting.
Edited to clarify that I am attempting to build this with Xcode, not from the command line.
I need the QtMacExtras framework to use its QMacCocoaViewContainer class.
I have been able to get the framework and compile it easily using qmake/make without issues.
However, when trying to link my binary with it I get undefined symbols errors.
The compilation of the objects works like a charm.
g++ -mmacosx-version-min=10.7 --exported_symbols_list=symbols.exp -Wl,-x -L/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/usr/lib -o myBinary *.o -bind_at_load -F/pathToMy/Frameworks -framework QtCore -framework QtMacExtras -framework QtGui -framework QtWidgets #...
Undefined symbols for architecture x86_64:
"QMacCocoaViewContainer::QMacCocoaViewContainer(objc_object*, QWidget*)", referenced from:
WbDockWidget::setContentWindowId(unsigned long long)in WbDockWidget.o
ld: symbol(s) not found for architecture x86_64
The code to instantiate the class is the following:
#include <QtMacExtras/QMacCocoaViewContainer>
// ...
NSView *view = reinterpret_cast<NSView *>(id);
QWidget *widget = new QMacCocoaViewContainer(view, this);
Commenting this code allows to compile my project.
The framework seems correctly linked, seems to include correctly the headers, and seems to contain the symbols (!):
$ nm -g Frameworks/QtMacExtras.framework/Versions/5/QtMacExtras | grep -i cocoa
0000000000009240 T __ZN22QMacCocoaViewContainer11qt_metacallEN11QMetaObject4CallEiPPv
0000000000009200 T __ZN22QMacCocoaViewContainer11qt_metacastEPKc
0000000000004c00 T __ZN22QMacCocoaViewContainer12setCocoaViewEP6NSView
0000000000011130 S __ZN22QMacCocoaViewContainer16staticMetaObjectE
0000000000004b60 T __ZN22QMacCocoaViewContainerC1EP6NSViewP7QWidget
0000000000004b70 T __ZN22QMacCocoaViewContainerC2EP6NSViewP7QWidget
0000000000004d10 T __ZN22QMacCocoaViewContainerD0Ev
0000000000004d40 T __ZN22QMacCocoaViewContainerD1Ev
0000000000004d90 T __ZN22QMacCocoaViewContainerD2Ev
00000000000091e0 T __ZNK22QMacCocoaViewContainer10metaObjectEv
0000000000004e20 T __ZNK22QMacCocoaViewContainer9cocoaViewEv
0000000000011360 S __ZTI22QMacCocoaViewContainer
000000000000ce70 S __ZTS22QMacCocoaViewContainer
0000000000011160 S __ZTV22QMacCocoaViewContainer
0000000000004d50 T __ZThn16_N22QMacCocoaViewContainerD0Ev
0000000000004e10 T __ZThn16_N22QMacCocoaViewContainerD1Ev
Any suggestion to be able to use this class would be more than welcome.
Sincerely.
This problem occurs when you build as C++.
The easiest way to fix this is to switch the extension to .mm, but if you force the toolchain to build as Objective C++ by whatever means it should fix the issue.
I want to set up a project to take my .hs code, and my main .c program, and result in a statically linked executable through the use of LLVM compiler. I can get things working via ghc command line options to build a .hs, produce the stubs, and compile and link a driver application using ghc entirely. However, I get various issues within Xcode.
My first issue was that I of course need to use 32 bit compiling environment in Xcode. That solved, I had to fiddle with paths to explicitly include the HsFFI.h. That solved, I get a linker error:
Ld "build/Debug/FFI Test.app/Contents/MacOS/FFI Test" normal i386
cd "/Users/rcl/TestXCodeProjects/FFI Test"
setenv MACOSX_DEPLOYMENT_TARGET 10.6
/Developer/usr/bin/clang -arch i386
-isysroot /Developer/SDKs/MacOSX10.6.sdk
"-L/Users/rcl/TestXCodeProjects/FFI Test/build/Debug"
"-L/Users/rcl/TestXCodeProjects/FFI Test/FFI Test"
"-F/Users/rcl/TestXCodeProjects/FFI Test/build/Debug"
-filelist "/Users/rcl/TestXCodeProjects/FFI Test/build/FFI Test.build/
Debug/FFI Test.build/Objects-normal/i386/FFI Test.LinkFileList"
-mmacosx-version-min=10.6 -framework Cocoa
"/Users/rcl/TestXCodeProjects/FFI Test/FFI Test/ForeignExportCost.a"
-o "/Users/rcl/TestXCodeProjects/FFI Test/build/Debug/FFI Test.app/
Contents/MacOS/FFI Test"
Undefined symbols for architecture i386:
"_hs_init", referenced from:
-[FFI_TestAppDelegate applicationDidFinishLaunching:] in FFI_TestAppDelegate.o
"_simpleFunction", referenced from:
-[FFI_TestAppDelegate applicationDidFinishLaunching:] in FFI_TestAppDelegate.o
"_hs_exit", referenced from:
-[FFI_TestAppDelegate applicationDidFinishLaunching:] in FFI_TestAppDelegate.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The "simpleFunction" is in "ForeignExportCost.a" library which I compile using ghc like this:
ghc -no-hs-main -fPIC -c ForeignExportCost.hs
ghc -no-hs-main -shared ForeignExportCost.o -o ForeignExportCost.a
What am I missing or doing wrong?
Ugh - it looks like the answer to my question is detailed here, telling me how to painfully add a ton of .a's to my project. And this blog post gave some helpful tips to getting on the way.
Although if someone tells me "hey wait, there's an easier way than iteratively figuring out failed deps" that would be awesome. Because I want to reuse this framework several times and this is a real pain of a way to get things up and going!
I'm in the process of porting a large'ish (~1M LOC) project from a Window/Visual Studio environment to other platforms, the first of which happens to be Mac OS X.
Originally the project was configured as Visual Studio solutions and projects, but now I'm using (the excellent) Premake (http://industriousone.com/premake) to generate project files for multiple platforms (VS, XCode, GMake).
I configured, ported and built the first few projects without any significant problems, but having ported the math lib, I ran into this weird linking error that I haven't been able to resolve: Any functions used from math.h will fail to link (causing unresolved symbols).
For reference, I'm using Premake v4.2.1 to generate projects for XCode v3.2.1, which is building using gcc v4.2 for the x86_64 architecture. (All this on 64-bit Snow Leopard) I've tried to persuade gcc to link and build everything against a 'known' SDK by adding -isysroot /Developer/SDKs/MacOSX10.6.sdk -mmacosx-version-min=10.6 to the build command line.
Now under normal circumstances, adding -lm should take care of this, however in Darwin, those math libs are included in libSystem, which, as far as I can tell, gets implicitly linked by gcc/ld.
I've tried creating a dummy project from within XCode which just runs:
float f = log2(2.0)+log2f(3.f)+log1p(1.1)+log1pf(1.2f)+sin(8.0);
std::cout << f << std::endl;
and as expected, this builds just fine. However, if I put the same thing in the code inside the Premake generated project, all those math functions end up unresolved.
Now comparing the linking command from the 'native' XCode project with my generated XCode project, they seem pretty identical (except that my generated project links other libs as well).
'Native' project:
/Developer/usr/bin/g++-4.2 -arch x86_64 -dynamiclib -isysroot /Developer/SDKs/MacOSX10.6.sdk -Lsomepath -Fsomepath -filelist somefile -install_name somename -mmacosx-version-min=10.6 -single_module -compatibility_version 1 -current_version 1 -o somename
Generated project:
/Developer/usr/bin/g++-4.2 -arch x86_64 -dynamiclib -Lsomepath -Fsomepath -filelist somefile -install_name somename -isysroot /Developer/SDKs/MacOSX10.6.sdk -mmacosx-version-min=10.6 somelib.a somelib2.a somelib.dylib somelib2.dylib -single_module -compatibility_version 1 -current_version 1 -o somename
Any help or hints about how to proceed would be most appreciated. Are there any gcc flags or other tools that can help me resolve this?
I finally managed to resolve/work-around this.
By replacing
#include <math.h>
float f = sinf(1.f);
with
#include <cmath>
float f = std::sin(1.f);
everything links as expected.
I'll accept the fact that the cmath solution is probably the code I should have written in the first place, although I'd happily accept further opinions about why my C approach failed so miserably.