module map naming in iOS for static library - ios

When I used the name module.modulemap for a framework, I got an error saying "redefinition" of module. Which turns out to be a bug from Apple:
Known Issues
When building a framework that has module maps in both the source and the install directories that define the same module, the compiler will show a redefinition message. (28638816)
Workaround: Rename the module map file in the source directory to a non-default name (the default name is
module.modulemap
or
module.map
), and set the Module Map File build setting to the renamed module map.
So after changing the name to my_module.modulemap (and updating the build settings path), it worked fine. When I build it, Xcode will generate a module.modulemap file, with the content of my_module.modulemap prepended.
However, when I tried out the static library, I can't use my_module.modulemap anymore. Even if I write non-exist files it's not complaining:
module Foo {
header "NonExistFile.h"
}
When I look at the exported header in final product, the module map file does not show up at all. How do I fix it?

Related

Xcode change dynamic framework Product Module Name

I’m trying to change the product module name of a dynamic framework.
The main reason I’m doing this is that my framework is customised for each client, so I have different targets with different names and output files that I want to keep different as they are, but I would like the framework to be imported for all the targets with the product name.
The framework is in objective C and consumed by a swift application.
In the Xcode build settings the DefinesModule is set to YES.
Let’s say the product name is CustomerSDK and I want it to be imported as ProductSDK.
For example: The framework file will be CustomerSDK.framework and the import statement import ProductSDK.
If I use the $(PRODUCT_NAME:c99extidentifier) as the module name (the default option in Xcode) by calling import CustomerSDK it works, but when I try to change the Product Module Name field in build settings to another one the code completion of Xcode in the host application project doesn’t find the module name and even if I write it I get the “No such module ProductSDK” error. Looking inside the resulting product framework I can see that no modulemap file is generated.
I tried also to create a custom module.modulemap file, in this case the code completion of Xcode in the host application project proposes the new name, but when I try to compile I still get the “No such module ProductSDK” error.
framework module ProductSDK {
umbrella header "CustomerSDK.h"
export *
module * { export * }
}

Module map location and compiler settings with mixed Objective-C/Swift frameworks

Background: I'm converting a large old mixed language codebase to a framework. I'm having problems, so I thought I'd start with a minimal test project to see how things work. I ran into more problems. This is Swift 5.0 with Xcode 10.2.1.
I created a new iOS framework project called TestFramework. TestFramework has the following source files:
OCTest.[hm], with a single private class
OCPublic.[hm], with a single public class. It calls OCTest.
STest.swift, with a single public class. It calls both OCPublic and OCTest.
I also have the following two umbrella headers, in the same folder as the source files:
TestFramework.h, which is the one Xcode created automatically. I only added #import "OCPublic.h".
TestFramework_Private.h. It has two lines:
#include "TestFramework.h"
#include "OCTest.h"
They all reside in the TestFramework folder, along with Info.plist and everything else Xcode creates automatically.
I managed to make this compile, build a framework package with carthage build --archive and use the resulting framework successfully in a test app with the following module maps and build settings:
TestFramework/module.modulemap exists and is empty.
TestFramework/module.private.modulemap exists with these lines:
module TestFramework_Private {
umbrella header "TestFramework_Private.h"
export *
}
Both MODULEMAP_FILE and MODULEMAP_PRIVATE_FILE in build settings are unset.
SWIFT_INCLUDE_PATHS is $(PROJECT_DIR)/TestFramework.
DEFINES_MODULE is true.
If I add any content (framework module TestFramework { … }) to module.modulemap or try to make MODULEMAP_FILE or MODULEMAP_PRIVATE_FILE point to their files (with the values TestFramework/module.modulemap and TestFramework/module.private.modulemap) I get various build errors (can't find TestFramework_Private, redefinition of module TestFramework, etc.)
If I remove the empty main module map, I get No such module 'TestFramework_Private' where STest.swift tries to import it.
If I try to move the private things into a separate folder and change SWIFT_INCLUDE_PATHS and MODULEMAP_PRIVATE_FILE I get more build errors.
Are there some values for the MODULEMAP* settings that should work, with or without content inside the main module map? What should I do if I wanted to move things into different folders?
It seems at least some of my problems were caused by this:
When building a framework that has module maps in both the source and the install directories that define the same module, the compiler will show a redefinition message. (28638816)
Workaround: Rename the module map file in the source directory to a non-default name (the default name is module.modulemap or module.map), and set the Module Map File build setting to the renamed module map.
Renaming my module map file to anything other than module.modulemap — the name used in, for example, all over Clang documentation — made it possible to point MODULEMAP_FILE at it, and allowed me to move the headers to a different location etc.

add module into ios framework, app get "module not found"

I have a swift framework project(let's call it Framework1), inside it use some 3rd party objective c files. I use module instead of umbrella file because of ambientlight's answer in this post
I create a subfolder(let's call it MiscModule), put module.modulemap under that folder, include all oc headers, and configure the Build Setting. The framework build fine, I can get framework build.
But after I put Framework1 in app project, build the app. It complain about "Module MisModule not found".
I saw the Framework1-swift.h file have an line of "#import MisModule". I had thought MisModule is build into binary in Framework1's bundle.
Do I miss something?
When you built it, those files that in modules did not be embedded into the framework, it would change the relative path to absolute path.
such as import YourModule change $SRCROOT/... to User/YourProject/
so, not use custom module in framework, it will change the import paths to
absolute path.
Your can build a framework for the oc files.
Sometimes cleaning Xcode, restarting both the simulator and xcode, and then trying to run again helps. If worst comes to worst, try heading into finder and doing a deep-clean. Delete ~/Library/Developer/Xcode/DerivedData/

How to make static library modular in Swift 4?

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

Socket.IO error: zlib no such module (Swift 3, Xcode 8.3)

I followed the instructions of Socket.IO's README.md of manually implementing Socket.IO. I dragged in the Source folder into my project and I double-checked to make sure 'Add to target' was selected. When I try to run my project, I get an error 'No such module' because zlib can't be found in Compression.swift. Am I supposed to add any other files or folder to my project? What am I missing here?
Okay, I managed to find the answer on my own, even though the documentation of Socket.IO is very unclear about this and doesn't mention anything about zlib. To import zlib, go to your project's Build Settings and scroll to Swift Compiler - Search Paths. There, you should create a new path by clicking the + in both Release and Debug. Then, add the folder path to the zlib folder that was included in the Github file you downloaded. You can either direct your folder path to its original location inside the Github folder you downloaded, or you can place the zlib folder inside your project folder. It doesn't matter where you leave the folder, as long as you're referring to it correctly. Now, build and run and the No such module error should disappear.
I also got this error when compiling the project after having added socket.io. I fixed it by adding libz.tbd to the Linked Frameworks and Libraries (clicked the + button in the General tab of the target, then I picked it from the list).
After doing that however, I got another error:
No such module 'CZLib'
I'm not sure which version of socket.io I added as I copied the entire folder from one of our previous projects. Anyway, the socket folder had a module.modulemap file which seemed to define the missing module. So I tried to fix the error by adding the socket.io folder containing the module map to the targets Import Paths, found in Build Settings under Swift Compiler - Search Paths.
The project would now compile without errors. At this point I tried to remove the linked libz.tbd and it would still compile. I have still not tried to establish a socket connection, but for now I'm moving forward without linking libz.tbd.

Resources