Do I need to link libs that dependencies link? - xcode

I'm trying to write a simple game engine for iOS in Objective C and C++ using Xcode.
I've made a game project and a game engine project. The latter is added to the former as a subproject. The engine is also added as a target dependency and as a binary to be linked in the game project.
My engine uses CADisplayLink so I add QuartzCore.framework in the engine project's "Link binary with libraries list" (found in Build phases).
Now, when I try to build my game project (the project with the subproject), I get this error:
Undefined symbols for architecture i386: "_OBJC_CLASS_$_CADisplayLink", referenced from: objc-class-ref in libVoya-iOS.a
This error only happens when building from the game project - doing it from the engine project works fine. If I add QuartzCore.framework to the game project building works fine.
Can it really be true I have to specifically require frameworks that one of my target dependencies already have required? In this case: My engine (sub project) already links QuartzCore - is it really necessary to also do this in the projects using this engine? It feels like double work for no reason.
Or perhaps I've just completely misunderstood something? :)

Add QuartzCore framework to fix this issue.

I've now found the answer to my question and I'd like to share it.
Static libraries are nothing more than a grouping of the compiled versions of the library's source files. They do not include any libraries they themselves might depend on.
Fusing all dependencies together happens only when you build the actual executable in the very end. For this reason, your application should indeed link against your dependencies' dependencies.
As for the example in my question, that means that my game should link QuartzCore while my game engine should not (even though it is my GameEngine who is using it).
Learn more here:
Duplicate symbol: Include static lib A in static lib B, also include lib A and B in XCode Project
Linking static libraries, that share another static library

I believe this is because you're using a target dependency instead of linking against a precompiled library.

Related

XCode build fail: C++ lib within iOS lib within (test) consumer app

I've got three layers:
- core C++ engine
- iOS audio wrapper
- demo iOS consumer project
So I am:
1) compiling engine.a, which links against accelerate framework.
2) compiling wrapper.a, with a dependency on engine and linking against engine.a AND accelerate framework.
So far so good. I can build wrapper.a. But something looks wrong. My wrapper code is using CoreAudio calls. It is fetching real-time microphone data. It should be reporting errors, surely? It should be requiring me to link AudioToolbox or AudioUnit frameworks.
So I don't see why that library even compiles.
3) create a fresh iOS project that links against wrapper.a.
Now I'm getting a 30+ build errors:
```
Undefined symbols for architecture x86_64:
"vtable for std::exception", referenced from:
std::__1::bad_function_call::bad_function_call() in libfftDecoder.a(FFTDecoder.o)
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
"std::__1::__thread_struct::__thread_struct()", referenced from:
std::__1::thread::thread(void (DecoderThread::&&)(), DecoderThread&&) in libfftDecoder.a(FFTDecoder.o)
"std::__1::__throw_system_error(int, char const*)", referenced from:
std::__1::thread::thread(void (DecoderThread::&&)(), DecoderThread&&) in libfftDecoder.a(FFTDecoder.o)
:
```
Can anyone suggest what might be the problem? That first error kind of looks like 'failing to process a C++ construct'.
I should mention that Xcode is very disappointing in the context of this task. The items I link against in the 'build phases' tab are not consistently reflected in the project navigator's "frameworks" folder for the respective project. Also sometimes a .a appears red even when it built successfully.
First point (thanks #wiliz on #iphonedev Freenode) is that a static library has no concept of linking against something. So I should be removing all the links from my .a files and putting all of the dependencies in my consumer app.
The problem was that the library contains compiled C++ code. And the consumer app doesn't have any .mm files. So it isn't using ObjC++ anywhere. So it isn't linking against the C++ stdlib.
Simply renaming one of the .m files (say ViewController.m) to .mm fixes the problem.

Why are Frameworks Linked As Binaries In Xcode?

You call Library code and Framework code calls your code.
I've been doing a number of xcode projects which required adding external frameworks and libraries.
In the installation of these there was always one common occurance, they would always ask me to go to the Build Phases tab and "link the binary with libraries"
My question is why do both frameworks and libraries get linked this way? I (think) I understand why a library does. For libraries they can't execute themselves so you are pre-compiling them and making their functions available to your classes.
For the framework I am much less clear whats happening here. If the framework calls my code why is this being pre-compiled as a binary? If it's executing my code at runtime should it just be compiled along with the build?
A Framework is a way to bundle a static/dynamic library and it's headers (.h) together. There is also a concept of "versioning" but thats not really used anymore.
If you look into a Framework (its just a directory ), you will see the library (without the .a and "lib" prefix , headers, and a .plist.

Linking OpenCV static libraries in Xcode

(I am new at pretty much everything that I will discuss here... apologies if the question is very basic) - I used Xcode to write some C++ code using OpenCV (dynamic libraries). The algorithm runs smoothly and I created an executable file that also works. However, it only works in my computer.
I understand that I need to use static libraries instead of dynamic libraries. I have done some research and found how to do this here: http://www.shiffman.net/2011/01/23/how-to-build-opencv-static-libraries-mac-os-x/ and here: http://www.randomsequence.com/articles/opencv-snow-leopard/.
I have followed the steps and, although I had to make a couple of changes, I was able to build ".a" files such as "libopencv_highgui.a".
My code, however, doesn't work anymore when I replace the libraries. I get 200+ errors. This is one of them:
Undefined symbols for architecture x86_64:
"_gzputs", referenced from:
__ZL7icvPutsP13CvFileStoragePKc in libopencv_core.a(persistence.o)
I have searched for this question here but this is the closest I could find: Linking OpenCV libraries in Xcode (not exactly the same question).
Thanks everyone!
You need .a files from $OPENCV_BUILD_PATH/3rdparty/lib/.
The _gzputs from your question belongs to libzlib.a
To link with OpenCV static libraries you also need to add all OpenCV's dependencies to you application. The most of these dependencies comes from the opencv_highui module and the list of dependencies is dependent from your build configuration so I can't tell you the full list. But you can find it yourself: open the CMakeCache.txt from your OpenCV build directory with any text editor and search for opencv_highgui_LIB_DEPENDS line. You need all items from that line except the word general.

How to organize C source file previously compiled by GCC Make and build them into an Xcode bundle? I have a Duplicate Symbol _main Error

How to build a .bundle from source code?
This might sound like a simple problem but it has been hurdling me for a week...
Here is my problem:
I have a bunch of .c and .h files that are organized in a folder and its sub folders. The source code was written and compiled with gcc make and tested by many other make tools. The source code has some utilities and command line tools and it has more code that serve as library for those utilities and tools. It is the files that serve as libraries that I want to reuse. (By library I don't mean static library or something, I just mean that some .c and .h files in certain subfolders provide functions that can be called by some other .c files. I want to be able to call those functions, too)
Yet my problem is more complex than that: I need to build those .c and .h into a bundle to reuse it. I am not writing my application in C; I am developing in Unity and Unity can only take in .bundle files on Mac OS.
Here is my goal:
Organize the source code folder in a proper way so that I can build them into a bundle in Xcode 4.
Here is where I got stuck:
When building the project I got the following error:
Duplicate symbol _main in
/Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccndsmoketest.o
and
/Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccnd_main.o
for architecture i386
I can relate to this error because I can find lots of main entries in the source code. Most of them are test utilities.
Here is what I tried:
I tried removing all those utility .c files but with no luck. The error is still there. I delete and delete until some files cannot find the definition of the function they are calling. So I had to stop there.
Though I wasn't able to build a bundle I was able to build a C/C++ static library (with an .a extension). After I got the .a file I tried to put it into another Xcode project and tried to build it into a bundle. I could build a bundle in that way, but then I had problem accessing the content of the bundle. How do I call functions defined in a .a static library if that library is hidden in a bundle? I read about Apple's documentation which says:
Note: Some Xcode targets (such as shell tools and static libraries) do
not result in the creation of a bundle or package. This is normal and
there is no need to create bundles specifically for these target
types. The resulting binaries generated for those targets are intended
to be used as is.
(quoted from: https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/AboutBundles/AboutBundles.html#//apple_ref/doc/uid/10000123i-CH100-SW1)
Here is what I thought about:
I thought about replacing all main with something like main_sth. But the source code was not written by me so I didn't want to modify it. (It just doesn't feel like a proper way of doing things to me...)
I learnt that Xcode has gcc compiler built in. So I guess if gcc can make it, so can Xcode? It's just a wild guess - I am not familiar with Xcode and gcc.
Here is a summary of my questions:
Is there a way to properly organize a pile of code previously compiled and made by gcc make so that they can be built into an Xcode bundle?
Is it meaningful to put a .a library in an Xcode project and build it into a bundle? If it is meaningful, how do I call functions defined in .a after it is built into a bundle?
Is it proper to just replace all main() entries with something else?
Alright I think I have figured out at least one solution to the problem.
The duplicate main error was caused by a bunch of main entries in my source code. When the code was compiled by gcc make, I guess the author defined a sort of compilation order so that duplicate mains won't be an issue. (If you know how to do this, please let me know. I barely know make tools.) But when I just add the entire source code folder into my Xcode project, of course Xcode would complain during linking...
As I was unwilling to modify the source code (because the source code library is not developed by me), I decided to use another strategy to walk around this problem.
If your duplicate main error was reported from your own code, you can stop reading here. But if you are like me, with a bunch of gcc compiled source code and badly need a bundle yet don't know what to do, I may be able to help.
Okay here is what I did:
I set up an empty workspace.
I built a C/C++ static library project.
Import my entire source code folder into the static library project.
Set some header search path for the static library project.
Build the static library project. (Now I have a .a library which I could link against)
I set up another project, with a bundle target.
At the bundle project -> Build Phases -> Link Binary with Libraries, add the .a library that I just built.
At the bundle project -> edit scheme -> Build, add the static library project to the scheme and move it up the list so that it is built prior to my bundle project.
Then add .h files of my library project to my bundle project as references.
After that, add a .c file in my bundle project that basically functions as a wrapper. I picked a function that I want to call in Unity, wrote a wrapper function in the new .c file, and was able to build the bundle.
After several trial and error, I was able to import the bundle into Unity and was able to call the test function from Unity.
I was really excited about this! Though it's not completed yet I think this gives me hope and I am confident I can use the source code now! And the best thing about this solution is that I don't have to modify the library code developed by others. Whenever they update their code, I just update my .a library and that's it!
Though I have listed 11 steps I still feel that there are lots of details that I missed. So here are my references:
I followed this tutorial to build my source code into a static library: http://www.ccnx.org/?post_type=incsub_wiki&p=1315
I followed this blog to link static library against my bundle code and twist build phases and search headers: http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/
I followed this doc to import my bundle to Unity3D Pro as a plugin: http://unity3d.com/support/documentation/Manual/Plugins.html
I strongly recommend the second reference because that's what solved my problem!
Though the problem is almost solved there are still a few things that I haven't figured out:
I don't know if a wrapper function is at all necessary. I will try this out tomorrow and come back to update.
-- I am coming back to update: the wrapper function is NOT necessary. Just make sure you have all the headers in your bundle project and you will be able to use all the data structures and call functions defined in your headers.
I haven't used NSBundle class though I read a few docs about it. Previously I was thinking about using that class to access my .a library encapsulated in my bundle, but as I found the solution I wrote above, I didn't try the class out.
Lastly, if you have better solution, please don't hesitate to let me know!
I tried to follow the steps in the accepted answer, but had no luck. In the end, I realised step 10 needed to be modified slightly:
Create a dummy.c under (.bundle) project and the dummy.c can just be totally empty.
Remove the setting for the library you want to link inside Link Binary With Libraries
Instead use -Wl,-force_load,$(CONFIGURATION_BUILD_DIR)/libYourLib.a or -all_load to Other Linker Flags
PS: And also can use sub-project instead of workspace. and use Target Dependencies instead of Edit Scheme to achieve the same effect.

Including one Xcode project in another -- linker errors

I am trying to do this, and running into problems. The parent project needs to access the class SettingsViewController from the child project. I have put the child project path into my header search paths. Everything compiles OK, but I get linker errors, as follows:
Undefined symbols: "_OBJC_METACLASS_$_SettingsViewController",
referenced from:
_OBJC_METACLASS_$_StatisticsViewController in StatisticsViewController.o "_OBJC_CLASS_$_SettingsViewController",
referenced from:
objc-class-ref-to-SettingsViewController in SelectionViewController.o
_OBJC_CLASS_$_StatisticsViewController in StatisticsViewController.o ld: symbol(s) not found collect2: ld
returned 1 exit status
How can I fix this?
I assume the child project is a static library. Currently, your parent project knows how to find the header files of the child project (otherwise it wouldn't compile), but it doesn't know that it has to link to the library (.a) file of the child project.
You should probably add the library file to Targets > {your app} > Link Binary with Libraries. Furthermore, you probably need to add the linker flags -ObjC and possibly -all_load.
There are many detailed descriptions on the net, e.g. Build iPhone static library with Xcode.
Update:
If it's not a static library, then it's a rather strange project setup. The best thing you can do is to add the shared files (.h and .m) to both projects. They will then be independently compiled in both projects. That should work if you have few shared files.
But I recommend anyway to use a project setup with a static library. It nicely works if you properly set it up. I'm successfully using it. And - as I've told before - there a several good descriptions on the net how to set it up.
You may be missing a framework. Can't really tell from what you have posted here though.
I know this is very old but might be helpful for others.
You need to setup the included project in Target Dependencies in "Build Phases" to get the included projet to be compiled and you also should add the static library of the included project in the "Link Binary with Libraries".
Click on your Target->Build Phases and set these up.
Undefined symbols
Undefined symbols is a linker error
1.Check if you have added a library or framework
Project editor -> select a target -> General -> Frameworks, Libraries, and Embedded Content(Linked Frameworks and Libraries)
//or
Project editor -> select a target -> Build Phases -> Link Binary With Libraries
2.If you try to use Swift code from Objective-C
Add empty .swift file to the Objective-C project. When Xcode ask press Create Bridging Header

Resources