How to make static library modular in Swift 4? - ios

As after release of Swift 4, Swift is supporting Static library. But when I am trying to make use of Static binary inside application, it showing error with undefined module.
We are creating SDK with modular structure with 15 framework one for each module, but as Apple suggest it is not good to add more than 6 dynamic framework(As dynamic linking slow down app launch time.).
So after support of static lib in Swift, we decided to convert it to static library and then create one dynamic framework which provide facade interface for all 15 frameworks.
I created one Static lib named StaticA an try to add it in Dynamic Framework, but it shows below error.
No such module 'StaticA'
I also set Defines Modules to Yes but it does not helping.
Is it possible to make Static library modular using Swift ?
If Yes, then suggest way.
Thanks

There's a few build settings you need to enable:
MODULEMAP_FILE = $(PRODUCT_NAME)/module.modulemap
SWIFT_INCLUDE_PATHS = $(PRODUCT_NAME)
DEFINES_MODULE = YES
The other option which works (without modifying the build settings) is to copy the modulemap file to the products directory under include/$(PRODUCT_NAME)
Note:
I generally put the modulemap in the top level of the module directory
i.e. one level down from the xcodeproj file:
StaticA.xcodeproj then I would have at StaticA/module.modulemap
What this allow's you to do is define a module.modulemap for your library:
module StaticA {
header "StaticA-Swift.h"
}
Typically StaticA-Swift.h isn't available and won't be generated, you "might" be able to get away with not specifying it ... but I've not had any luck and have needed to do it manually.
You can use a script which will copy the generated *-Swift.h to the include folder so that you are able to reference it from your modulemap file.
#!/usr/bin/env sh
target_dir=${BUILT_PRODUCTS_DIR}/include/${PRODUCT_MODULE_NAME}/
# Ensure the target include path exists
mkdir -p "${target_dir}"
# Copy any file that looks like a Swift generated header to the include path
cp "${DERIVED_SOURCES_DIR}/"*-Swift.h "${target_dir}"

Go to your Project's Build Phases
and
Click on the "+" under "Link Binary With Libraries" to add a new library. Then click on the "Add Other" button.
and pls also ensure you have the lib path to Library Search Paths under Build Settings

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

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.

How to use third party lib in embedded dynamic framework for iOS with swift

Now I have a project, like testApp, using some third party lib like alamofire and some others libs in objective-c.
Now I want to add a today widget. According to some tutorial, I created a new target "testAppKit" as a shared dynamic framework, and target "testAppWidget" as today extension. The common code will be in testAppKit for reuse.
Now I need to use third party libs in testAppKit. And added lib and header in build phases of testAppKit. Then I add #import <theLib/TheHeader.h> in testAppKit.h. But there is an error:
Include of non-modular header inside framework module 'testAppKit'
So, I want to know how to use third party libs (maybe in Swift or Objective-C) in this kind of embedded dynamic framework.
I use Dropbox Datastore API in my app and I finally made it working for embedded Cocoa Touch framework to share code for Containing App and Today Extension.
I figured out that in my Swift file in the embedded framework I can import any 3rd party framework I had in the Project (i.e. Farbic.framework, Crashlytics etc.) but not Dropbox.
What was the difference? The "Modules" folder! Dropbox.framework doesn't provide module map file. So I created it based on what I found in Fabric.framework:
Go to the Dropbox.framework folder in your project direcotry.
Create new folder "Modules" and go inside
Create a file called: "module.modulemap"
The content of the file:
framework module Dropbox {
umbrella header "Dropbox.h"
export *
module * { export * }
}
After doing that I needed to add import path.
Go to your Project file
Select your embedded framework target
Go to the "Build Settings" and find "Swift Compiler - Search Paths"
Add path to your Dropbox.framerowk and set "recursive" option.
I wanted to put a screenshot here but I can't do that yet - because of my "reputation" ;)
Now I'm able to do "import Dropbox" in my swift files :)
Hope this can help you :)

Creating a Static Library in Xcode 5

Hi guys I'm having a bit of trouble creating a static library in xcode 5. Most of the tutorials out there are done in xcode 4 and thanks to apples incredibly easy to use gui, that makes it so easy for users to transition from one program to another, so I haven't been able to make one and use it.
So I get that the first step is to make the cocoa ios static library project and then to add the header and implementation files (.h and .m) that you want in your library.
Next you supposed to set the header files that you want to be accessible by the user. Is it possible to set up the library in such a way that importing one header file also imports all of the other header files? Do the other header files need to be public to do this?
My main problem is how do I actually set the classes which I want to be public/private and finally how do I implement this library into one of my applications?
A HelloWorldLibrary example would be great!
After using the link: github.com/jverkoey/iOS-Framework
I am now having a problem with the locating of the Framework:
ld: warning: directory not found for option '-L/Users/Harry/Library/Developer/Xcode/DerivedData/SampleFramework-efznryzmlxnimoaaazjfbqjirzxq/Build/Products/Debug-iphoneos'
ld: framework not found SampleSubproject
There are steps to create static library.
I have not created in xCode 5, but have created in 4.x..
Create new project and select Cocoa touch static library under iOS.
Add Class files/Resources to your created project.
Set Installation Build Products Location to $(BUILT_PRODUCTS_DIR)
Copy headers in Build Phases
Set headers to Public in Target Membership
Build for Archiving/Profiling
got it from derived data (Release iphonesimulator, Release-iphoneos)
now merge both .a files using
lipo command from terminal like lipo -create libForDevice.a
libForSimulator.a -output UniversalLib.a
Now copy this lib to your main xCode project and include your perticular class.
You can find more details from here
Regards.

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