Header search path in XCode - ios

I am refactoring the code I produced in XCode in order to have a certain number of static libraries that I can distribute to my partners.
I have no problem in using the static libraries as suggested in the Apple tutorial where they show how to use the static library as a subproject of the project using the library.
However, I have problems in using the produced object file (.a) and corresponding header files (.h) in a new project.
Let's say I have a library lib.a with header f1.h. What I do is create a new folder F inside the new project and copying into F the lib.a file and a folder include containing f1.h:
-- PROJECT
storyboard.storyboard
/project
/images.xcassets
/Supporfing Files
...
/libs
lib.a
/include
/lib
f1.h
I have these problems:
the headers files are found with #import f1.h and not with #import lib/f1.h
if I use a view controller implemented in the static library directly in a storyboard, the app fails, however if I create a new ViewController extending the one in the lib and use the latter one in the storyboard, everything works fine.
Using a static library in an app should not be this difficult so I am clearly doing something wrong. Do you have any workflow and settings to suggest?
Thank you.

When you don't have the corresponding Xcode static library projects and sources, you can use headers and a binary static archive as follows:
Your folder structure should be like this:
$(LIBRARIES)/release-iphoneos
libA.a
libF.a
/include
/A
a1.h
/F
f1.h
Your header search path for Release Configuration (or all others) should contain this path:
$(LIBRARIES)/release-iphoneos/include
Your library search path for iOS (not Simulator) should contain
$(LIBRARIES)/release-iphoneos
where libA.a and libF.a are universal binaries containing armv7, armv7s and arm64.
You can also set a library for the Simulator: just get the binaries for Simulator (i386 or possibly a universal i386 + x86_64) and setup the library and header search paths accordingly. (Note you can set header and library search path for each configuration and architecture explicitly in the Build Settings editor).
You can import the headers as follows:
#import <F/f1.h>
Otherwise
if you have the Xcode static library projects (and the sources), simply follow the instructions in the official documentation to use and build a static library.

Related

How to create a framework from a C library with nested headers

I want to create a iOS framework for a popular C library.
My Current Setup:
This is what I'm doing:
Build the library for iOS and iPhone simulator architectures
Combine the two archive .a files into a single fat library using lipo
Use libtool -static -o to get the final library
By this stage I have a binary and a bunch of header files. In xcode:
Drop the binary (from step 3) and ensure its linked under: Target > General > Framework and Libraries, and Target > Build Phases > Link Binary with Libraries
I copy all the header files from the C library and place them under dir Dependencies/myClibrary/include/. The include dir contains a master header file myClibrary.h which includes a number of header files from ./abstract/*.h.
At top level of the xcode project dir, I also create a module.map file with content:
module MyWrapperFramework [system] {
header "Dependencies/myClibrary/include/myClibrary.h"
export *
}
Add all header files to xcode and for each header file, under Target Membership change value from project to public.
Build
Testing the framework in an App
I am able to build the framework, with settings as mentioned above. However, when I want to test it in a test Objective C app, I import the framework and call functions related to the myClibrary. On building the app, I get the error:
'myClibrary/abstract/headername.h' file not found
The above error originates from myClibrary's master header file myClibrary.
Most of the tutorial that I could find deals with C libraries having a single header file. How can I create a iOS framework from a C library that contains nested header files?
In case, nested header files are not the main issue here, what am i doing wrong?
A framework's headers get installed in the Headers directory inside the .framework. The compiler knows enough magic that when you say #import <myClibrary/myClibrary.h> that it will start the search for myClibrary.h inside that Headers directory.
As a result, the default public header build rules are to copy all public .h files (no matter their position in the source tree) into that Headers directory. That directory should be set as the $PUBLIC_HEADERS_FOLDER_PATH variable during building.
It seems as though you need to install headers into different directories. You could simply set the value of the Public Headers Folder Path in build settings to be a subdirectory, which will then install all public headers there. You could then have a custom Copy Files build phase to install just the single, overall header into the original headers directory.
Or, you could just add just the headers which go into the root as public headers, then have a custom Copy Files phase for all the rest, which copy them into a custom subdirectory. I think if you choose "Wrapper" as the destination, that is the root of the framework, so if the subpath is "Headers/abstract" that should work (though I have not tested myself). If you need to have multiple subdirectories, you would need a custom Copy Files build phase for each one.
Or, of course, have a custom build script to copy the headers more manually, if that's easier than multiple build phases (say one that copies all files in the include directory to $PUBLIC_HEADERS_FOLDER_PATH but preserving the structure, if there are a lot of subdirectories).

Header file inclusion and visibility in static library iOS

When a static library is created from an iOS project, in Lib.a file, does it have all the header files also bundled into it. Or should I mark all the header files that will be used by public header as private headers which then add all private files in /usr/local/include folder once the static library target is build?
No, nothing happens automatically. The normal process for static libraries is as follows:
have a static library target in your project, so you can include the project in an app and verify functionality
create a Run Script and Aggregate target so that you build one .a for iOS and one for the simulator, then "lipo" them together into one .a
in the run script, copy the .a and all the necessary .h files into some folder you create
The folder is then what you distribute. The user links to the .a, and sets the Search Paths in their app project to point to the folder with your .a.

Import a static library as a subproject

I watch this video to know how to create a static library, I just watched until the 4:05 minute video (which have already been enough to learn how to create a static library).
But I learned that there's another way to import a static library for the project called subproject, for this I open my iphone project and add my library project (MuitosAlertas.xcodeproj), Then I added two references to my library inside the tab Target Dependencies and Link Binary with libraries as you can see below:
When I compile and run, Xcode give me the problem
Lexical or preprocessor issue 'MuitosAlertas.h' file not found
I try to put inside Other linker flags the code -ObjC but without results, how can I solve this problem
You must add Header Search Path to your target. In build setting search "Header Search Path" and add relative link to your static library project. How to add relative path read more here
You may need to search path with recursive option.
Once you have created your Library then make a build from the target added separately for the Universal support and then by right clicking on to the .a file from bundle navigate to folder and look for Universal and copy Include folder and your StaticLibrary.a file, then where you want to use it paste in that project and add reference to it and in bundle setting you need to set the HeaderSearchPath of the library where it is kept and the OtherLinkerFlag to -ObjC.
Then import the headers of your library and use your methods.

Deploying static library in Xcode 6

I want to deploy a static library that I've been writing in Xcode 6. I've already managed to compile the library into a .a file. Now I want to use it in another project. Also, note that including the library project is not an option, as this library is supposed to be distributed in binary.
I also managed to import the .a file into a new project, but I'm not sure what the best way to find the header files is. Should I copy them to a system folder? Should I just link to the framework's (downloaded) folder? Should I import the headers directly in the project? As the framework is meant for distribution, I think that ideally I would copy them to a system folder.
Finally, I've read that I need to build two different versions if I want the framework to be compatible with both iOS and the simulator. Is this true? Can it not be distributed in the same binary?
I distribute such a library for my company. I essentially put the .a file (built up with lipo) into a folder along with the headers. The client then needs to add the .a file to their project in the Build phases, Link Binary With Libraries. Then, they should add the path to the header files using a project relative path to the "User Header Search Paths". From my readme:
Process to Add the SDK to Your Project
1) Copy the xxx folder to the app folder, which contains the
".xcodeproj" project file, then add the directory to your project,
but don't add it to any targets (unselect the checkbox).
2) Add the appropriate library (iOS 6.0 or 7.0) folder, by going to your target's Build Phase tab, Link Binary with Libraries, tap
on "+", then navigate to the appropriate folder and select
libXXX.a
3) Add the following to the Project's Build Settings:
Search Paths -> Library Search Paths:
$PROJECT_DIR/xxx/ios // I have multiple folders each with a lib
Search Paths -> User Header Search Paths: $PROJECT_DIR/xxx
Linking -> Other Link Flags: -ObjC NOTE: If you fail to do this, your app will crash on launch (if it uses categories)
I use lipo to add both the Simulator .a files too - even thought this is not officially sanctioned. As others have said, Apple frowns on this yet offers no easy way for users of your library to use different .a files - the "official" solution would be for you to write a custom build script.

Adding frameworks to Xcode project

I have added a framework to xcode project. Under Build phases->Link Binary With Libraries.
The framework consists of a library file (.a file) and a folder "Headers" which includes all the necessary header files for that framework.
Now I am trying to import a header file in the framework to one of my classes.
#import <MySDK/MyHeaderFile.h>
But an error occurs "Symbol not found" while building.
My understanding was that, if we are using framework instead of library file there is no need to add the header files path in "Header Search Path".
But still, I have specified the path to my framework in header search path.
Also I have specified the framework path in Framework search and Library Search path options.
This is first time I am working with frameworks. For libraries I just added the .a files and specified full path to header files in header search path.
What configuration am I missing for adding frameworks?
If it's a static library file and a bunch of headers, it's not a framework. A framework is a specific method of packaging files. On MacOS X static and dynamic frameworks have one structure, while static frameworks on iOS have a different structure.
For a static framework using Xcode 5, your file structure would look like this:
MySDK.framework/
en.lproj/
Headers/
MyHeaderFile.h
Info.plist
MySDK
Where MySDK is the binary archive file (it should not be MySDK.a). If you have a file ending in .a , you have a static library rather than a framework. Building a static framework using Xcode 5 isn't easy but it is also not impossible. Building a static library is much, much easier and trouble free however. It sounds like you already have a static library, so you just have to tell Xcode where to find the library archive and header files using the appropriate search path settings for your project or target.
If/when you DO have a framework, adding it to "Link libraries and frameworks" OR setting "Other linker flags" to "-framework path/to/MySDK.framework" will work fine.
Newer versions of Xcode may support different functionality for building or using frameworks, however linking against them should be largely the same.
MySDK/MyHeaderFile.h : This explains that your library is inside MySDK folder. Check if it exists in same path. Otherwise you'll get "Symbol Not Found" error.

Resources