Build static library - xcode

I am trying to build a .a static library for my iPhone project.
So, I have created a new project, and I used the template Cocoa Touch Static Library.
Then, in XCode 4.0, I add my .m and .h files.
i have successfully build the project, but no .a file is created In XCode, I see .a file in Products category but displayed in red; so it doesn't exist.
I don't understand why my build button don't create .a file, any help?

I see that you accepted the answer, but I thought I'd leave a note for future library developers. After upgrading an Xcode 3.x based static library project to 4.x, the library will not always upgrade and begin doing universal library builds. When this happens, the project build will be successful and apps linked against the target dependency will run fine, but you'll get red static library files showing in the projects you pull in. This is very annoying and the only fix I have found is to recreate the project files -- I tried auditing the build settings but was unable to figure out the confounding factors.
Hope this helps save somebody the 2 hours I just lost :-P

Related

How to add library in Xcode

I want to add library to my iOS application in Xcode 8.3.
I've read a tutorial and so, I created a target 'DEST', after add this item in Target Dependencies and libDEST.a in Link Binary With Libraries. Also, I moved all forked library in project. Now, I'm trying to use this library as in example from git, but code doesn't work. What am I doing wrong?

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.

Adding OCHamcrest to an IOS Project

The documentation for the project says just add the framework and the linker flags and you are good to go. Hours and hours of wasted time later, I have figured out that that's not true. If you do that, the project does not see the header files. You have to put the framework somewhere were the compiler will find the headers. In my case, that worked when I dropped the framework into /Developer/Library/Frameworks and then told it to recurse in searching that framework directory (do not fiddle around with the headers search directories).
Then the problem I get is that the link fails with the message:
ld: framework not found OCHamcrestIOS
I noticed that the documentation for the project says that it was updated for Xcode 4. I pulled down the binary of the framework after checking out the code and wasting a ton of time unable to build the IOS version of the framework.
The documentation is here.
I also noticed in that documentation that the cocoa instructions tell you to put a copy files phase into the build. I tried that. Didn't change the outcome.
The last time I fell into a sink hole it was because the library was C++ code. Maybe that's still the problem.
Barring a rapid solution here, I am going to go back to using STAsserts, as sickening as that prospect is, this is far, far worse.
Update: reinstalled Xcode. Still doesn't work. There are cheap ways to make this work, like add the header files to the project. Did a blog post about this that brought out a person with the same experience.
I use a number of frameworks in my projects. Some from other people and some are mine. Looking at the documentation I would suggest that the copy phase stuff is not for iOS development. So I would not do that. I downloaded the latest zip from https://github.com/jonreid/OCHamcrest and it appears to contain a ready to go iOS static library. (Not on my mac so I cannot test to confirm).
Anyway, the way I include static libs is to
Select the project (XCode 4).
Select the target I want to add the library to.
Select the Build phases tab.
Expand Link binary with Libraries.
Click the [+] button to add a framework.
Click the [Add Other ...] button and navigate to the directory containing the <lib>.framework directory and select that.
Thats all. The targets search paths will be updated to include the framework directory and the framework will be listed on the left under the project. Expanding it will show the headers.
The problem you mention sound like a couple of things. Firstly the framework not found sounds like the framework has not been included in the target. When you select the framework in the project list on the left, you should be able to see it's Target Membership displayed on the right. Check it's on for the target you are compiling.
Secondly building frameworks is not a trivial task so don't attempt it unless you have the scripts to do it. I say this because building a iOS static framework means compiling for both simulator and devices, combining the compiled lib files into a universal one, and then storing it and the header in a specific directory strucuture.
The downloaded zip from OCHamcrest though, appears to have the correct OCHamcrestiOS.framework in it. So if you store that directory somewhere and link to it using the steps I've outlined above it should work just fine.
So the solution I adopted for now, after much thrashing around, was to include the framework in the project.
Create a group inside the Xcode project called Third Party.
Link it to a folder called thirdparty.
Go to the Add Files in Xcode and pick the framework.
Drag it over to the dependencies.
Run the tests, they pass!
This is maybe preferable anyway because referencing it in /System/Library/Frameworks would present some versioning issues, and this can be setup very quickly. Furthermore, we have a continuous integration server, and having to get in there and sync versions whenever something changes is not so great.
Thanks for checking it out, Derek.

What is the correct way to set build configurations in an ios project using static libraries for creating an archive in xcode 4?

I have a working application which relies on several static libraries, which I've added as dependencies to the application and added to the link with static libraries bit in build phases. Everything builds and runs fine in the simulator and on my attached iPad.
I wanted to create an .ipa for use with test flight so I followed the instructions on test flight's site (http://support.testflightapp.com/kb/tutorials/how-to-create-an-ipa-xcode-4) and some other tutorials relating to creating an archive with an app that uses static libraries (http://diaryofacodemonkey.ruprect.com/2011/03/18/ad-hoc-app-distribution-with-xcode-4/, http://www.musicalgeometry.com/?p=1237).
Following these tutorials, when I create an archive I get linker errors about not being able to find various libraries, for example:
ld: library not found for -lOAuthTouch
(I've also tried using a new project and a new static library project to make sure it's not some setting I've changed and I get the same problem).
This seems to be because I added a build configuration called "Ad Hoc" to my app for creating an archive, and based on the linker command and the fact that adding an "Ad Hoc" configuration to all the static libraries I use allows the archive to be created I'm assuming that the static libraries are being built to a different directory.
I'd rather not have to add a new build configuration to all the libraries I use, so my question is, what should I do to create an archive of my app without tinkering with every library I use?
A second related question: all the tutorials I mentioned say to set the "Skip install" build setting to yes for static libraries, but the Apple documentation (http://developer.apple.com/library/mac/#documentation/ToolsLanguages/Conceptual/Xcode4UserGuide/DistApps/DistApps.html) seems to indicate setting it for the application, rather than the libraries. Anyone know which is right?
It will work, you must simply get the paths correct and make sure you have set Skip install to NO on each of the static libraries in the workspace. I recently went through this and ended up deleting the existing Ad hoc distribution configuration from both my main target and each of the static library targets. The I created a new ad hoc configuration on the main project and each static library project and verified all of the settings in each of them.
See this link, this, and this all of which helped with sort through this.

Share an Xcode project as a static library for other people to use in emulator. How do you use an AppDelegate from a .a static library file in Xcode?

I want to share my Xcode project as a static library for other people to use in the xcode emulator (giving them as little raw source code as possible). How do you use an AppDelegate from a .a library file in Xcode or UIBuilder?
I copied the main Window.xib file to a new project and included all of the other source files in a static .a library that I thought I would be able to invoke somehow. What do I have to do to launch my main product that is compiled into the .a library from a brand new Xcode project that is including that library?
You'll have to link to the static library. Include it in your new Xcode project, and then in the target for the application, go to the General tab and set the library as linked. You'll probably want to copy it into your new project's bundle (in the Frameworks directory), using a Copy Files build phase. You'll also need to reference the header files for the static library for avoid warnings.
This is a much better solution found in someone else's question:
iOS Question. Can I distribute the Xcode simulator versions of my app?

Resources