Header file inclusion and visibility in static library iOS - 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.

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 path in XCode

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.

How to make XCode add the linked project headers and implementaion files to the static library and framework

I have a static library project and in that project I linked a .xcodeproj to the source code so I can update easily actually and to not copy and paste files in the static library project for easy update.
The purpose thought it's to embed this .xcodeproj with my code into the result static library or .framework that I will build using a script.
Although I can see that there is nothing added in the compile sources or the copy header files which I added. If I try to add with drag and drop files from the linked project to my static library build phases copy header section it copies the file to my project again, but I don't want this.
And if I add a header file #import to one of my public headers and try to use the static library to the client project it complains that the header is not found!
So, in the end, what I want is the whole linked project files to be copied in the resulting static library or .framework with the scripts and target I have.
Is this possible to achieve, I think I miss some project setting that I'm not aware about that will see and copy all header and implementation files to my result static library or .framework?
Is my approach overall correct? I don't think that there is no option to use a linked project in a static library and embed it when the build is happening since I am using it in my project!
I could add the .framework of the third party component too and merge to my static library. I have created this question earlier today. Is it possible to include a .framework in a .framework and how?
Regards.
Not sure if your #import-not-found issue is a linker issue, but...
Make sure to use the -ObjC flag in "Other Linker Flags" in the library's Build Settings. This gets the linker to build everything in the library.
Mentioned here:
https://developer.apple.com/library/ios/technotes/iOSStaticLibraries/Articles/configuration.html
And also make sure you link in the library in the build settings for the project that needs it.

How can I create static library and can add just .a file on any project in ios

How can I create static library and can add just .a file on any project in ios.
I tried doing this but couldn't do it.
Thanks in advance
if you want create static lib mean refer the link http://jaym2503.blogspot.in/2013/01/how-to-make-universal-static-library.html
Step 1 : Create a New Project, Named it "Logger"
Step 2 : Create Classes
You can create as many classes you wants, In our tutorial we will create one class named "Logger".
So, now two files should be in our resource.
1. Logger.h
2. Logger.m
Step 3 : Put some useful code into Classes
Step 4 : Create New Target
Create New Target from File Menu.
New Target
Select Cocoa Touch Static Library
Step 5 : Add files to Compile Resource
Select "Logger" Target of Static Library
Go to Build Phases
In Complied Sources section, Add all the .m and .mm files.
In Copy Files section, Add all the .h files and resource files.
Build Phases
Step 6 : Compile Project with Static Library Target
Compile Project for iOS Device
Compile Project for Simulator
You can find two different .a files generated in build folders.
Find .a file
Step 7: Make Static Library Universal
You can find two different library now, one is for simulator and one is for iOS devices.
Create a New Folder and name it LoggerMerge.
Copy libLogger.a file of Debug-iphoneos folder to "LoggerMerge" rename it to libLogger_device.a
Copy libLogger.a file of Debug-iphonesimulator folder to "LoggerMerge" rename it to libLogger_simulator.a
Open LoggerMerge folder with Terminal
Fire below command
lipo -create "libLogger_simulator.a" "libLogger_device.a" -output "libLogger.a"
Now, you can find libLogger.a in LoggerMerge folder, this is Universal static library file.
Now, Just one thing you need is headers, See above screenshot there is folder called include in both build folder. Just copy header file from this folder.
Step 8 : Test Static Library
Create New Project, name it TestLogger
Import libLogger.a and header files
Import header file "Logger.h" anywhere you want to use
Now, Use this Logger class as default practice.
In our case, [Logger log:#"Test String"];
Run Project in Simulator and Device both
That's it!! You have your own static Library!!
Step 1: Starting a New Static Library Project
Open XCode and start a new project. Under iOS, select Library and “Cocoa Touch Static Library” say it as "staticlibrary". This will create a nice new project for us that builds a .a file.
Step 2: Code your static library
First we need to add some files. Add a new NSObject subclass to your project and name it StaticClass.Then Write some useful code in those files.
Step 3: Building And Distributing Your Library
Once you are happy with your library, simply build it in XCode. Obviously, don’t do build and run as you can’t run it (again unless you have a test suite). Now, look under the Products group in XCode and you should see a file called lib(libraryName).a. In our case, it’s libstaticlibrary.a.
Right click on that file and select “Reveal In Finder”. Drag this file into a new folder that you create where you will be bundling all of your library files.Now, do the same with all of the .h files. In our case, just copy StaticClass.h into this new directory. Your directory structure should now look like:
FolderName
|- libstaticlibrary.a
|- StaticClass.h
Now you can zip this folder and sell it to would-be iOS developers for millions!
Step 4: Linking Your Library In A New Project
So now that you have built your shiny new static library, it’s time to test it out in another application.
Create a new View-Based project (or whatever it doesn’t really matter). Name it as Test.
Now, just drag this folder into the project and XCode will set up all of the linking automatically. When prompted to copy, I usually say yes, but you can do whatever you want depending on how you intend on using the library. Sometimes just linking and not copying is far more beneficial if you have multiple projects sharing a single library. It ensures that they all use the most up to date version.
You should now see the .a file along with the header files in the new project.
Step 5: Using The Static Library Code
Now that all of the linking is set up, you just use your library like any other class.
For Further clarifications
http://www.raywenderlich.com/41377/creating-a-static-library-in-ios-tutorial hope this tutorial helps for you.
Objective-C consumer -> Objective-C static library
Xcode version 10.2.1
1. Create Objective-C static library
Follow section 1. Create Objective-C static library
2. Objective-C consumer with Objective-C static library
Follow section 2. Swift consumer with Objective-C static library
3. Consume Objective-C static library from Objective-C
Import module to the Objective-C client code[module_name]
#import module_name;
//or umbrella or public header
#import <module_name/module_name.h>
[More examples]

Resources