iOS: Clarify different Search Paths - ios

There are three different search paths in XCode Build Settings:
Framework Search Path
Header Search Path
Library Search Path
Could anyone clarify what those paths do and what they are used for?

Framework search path: where to search frameworks (.framework bundles) in addition to system frameworks paths. Not used very much in iOS development, officially there is no developer iOS frameworks.
In Mac development, it's set automatically if you drag a 3rd party framework into the project. Otherwise, just set it to the container directory where you saved the framework.
In xcconfig files you use this variable:
FRAMEWORK_SEARCH_PATHS = "/path/to/frameworks/container/directory"
Header search path: where to search for header files (.h files) in addition to system paths. Usually you'll need it if you are using a 3rd party library. Set it to the directory where you have the header files. If you use a directory to include the header (example: #import "mylibrary/component.h") set it to the parent directory.
In xcconfig files you use this variable:
HEADER_SEARCH_PATHS = "/path/to/headers/container/directory"
Library search path: where to search for library files in addition to system paths. Xcode will set it automatically if you drag a library (.a files) into the project. To set it manually, use the directory where the library is located.
In xcconfig files you use this variable:
LIBRARY_SEARCH_PATHS = "/path/to/libraries/container/directory"
All three can hold a list of paths, with quotes, separated by space.

These are used for searching for Frameworks, Header files, or Libraries that are not in the system search paths (like QTKit.Framework, standard C++ header files, etc).
My most common use for this is using the boost header library (*.hpp) files in my code I add the relative path "../lib/Boost/1.46.1" to the Header Search Path.
I find it better to add this at the project level instead of in each target. That way the targets inherit this and it only needs to be changed in one place if I update the version of boost.

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).

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.

Header search paths for subproject in XCode

I added a subproject (a library) to my project.
In order to be able to import the header files of the subproject, I'm adding the absolute path to the subproject directory (recursive) to the "Header Search Paths" of my main project. Is there anyway to configure XCode to automatically/ dynamically recognise the path to my subproject directory?
I feel that what I'm doing right now is very manual and prone to human errors. Also, in case I moved my subproject, I will not be able to import its header files anymore.
Note that I don't want to put the subproject directory inside the same directory with the main project as it will be reused for many different projects.
The reason why I expected this functionality of XCode are:
XCode allows me to drag and drop my library project into the main one, which is an intuitive and dynamic way of including library. It should not, therefore, require me to manually put in the path to the main project's build settings.
When we drag and drop our files and directories into an XCode project, it seems to handle the XCode's references and the filesystem paths smoothly. I don't understand how the logic differs for header search paths for subprojects?
You can use a relative directory, as opposed to an absolute directory, by using $(PROJECT_DIR), which is one of Xcode's many variables.
Assuming the sub-project is in a sibling directory to the app project (a system I use myself), then set Header Search Path to (something like):
$(PROJECT_DIR)/../libproject/include
This will allow the project to exist anywhere in the filesystem, provided the project directories maintain the same relative path to each other.

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.

Header path inside of framework

I'm working with making framwork project in iOS.
I want to change whole project to framwork and use it in other application.
I make all header files to public, but header file include other header files like this
include "subfolder/ClassName.h"
but if I use it in other application, can't find the "subfolder/ClassName.h"
maybe because of that files are in same "/Headers" folder..
How can I make it working ??
Inside your project's build settings, add the direct path for all header files under "Header Search Paths" and make it recursive in case there are any subfolders that also need inclusion.

Resources