Closed romanandreyvich closed 5 years ago
Hello!
The difficulty, in this situation, is that CocoaPods by default deletes all downloaded files. Mention of this behavior is here. Also, it says that you can protect the project putting it to this parameter.
Here is another thing that is important for your case. This command can be used to call a Gradle generateDummyFramework
task. It might be needed to make the framework visible to CocoaPods. You can also take a look at the usage here.
It works good with spec.prepare_command. Thank you so much!
My final Podspec file looks like:
Pod::Spec.new do |spec|
spec.name = 'myModule'
spec.version = '1.0'
spec.homepage = '...'
spec.source = { :git => "git@myModuleRepo.git" }
spec.authors = '...'
spec.license = '...'
spec.summary = '...'
spec.static_framework = true
spec.vendored_frameworks = "path/to/framework/#{spec.name}.framework"
spec.libraries = "c++"
spec.module_name = "#{spec.name}_umbrella"
spec.prepare_command = <<-SCRIPT
set -ev
./gradlew --no-daemon -Pframework=#{spec.name}.framework linkReleaseFrameworkIos --stacktrace --info
SCRIPT
end
@romanandreyvich Hi, How to do that? Can you describe the detail steps, I also want the same function thanks very much 😄
Follow the guide https://github.com/JetBrains/kotlin-native/blob/master/COCOAPODS.md
When ./gradlew podspec
will generate a Podspec file for you just change it from:
spec.script_phases = [
{
:name => 'Build KN',
:execution_position => :before_compile,
:shell_path => '/bin/sh',
:script => <<-SCRIPT
set -ev
REPO_ROOT="$PODS_TARGET_SRCROOT"
"$REPO_ROOT/gradlew" -p "$REPO_ROOT" :myModule:syncFramework \
-Pkotlin.native.cocoapods.target=$KOTLIN_TARGET \
-Pkotlin.native.cocoapods.configuration=DEBUG \
-Pkotlin.native.cocoapods.cflags="$OTHER_CFLAGS" \
-Pkotlin.native.cocoapods.paths.headers="$HEADER_SEARCH_PATHS" \
-Pkotlin.native.cocoapods.paths.frameworks="$FRAMEWORK_SEARCH_PATHS"
SCRIPT
}
]
to:
spec.prepare_command = <<-SCRIPT
set -ev
./gradlew --no-daemon -Pframework=#{spec.name}.framework linkReleaseFrameworkIos --stacktrace --info
SCRIPT
make sure that your spec.vendored_frameworks
looks to a right directory (where your framework is, after you build it).
Than just run pod install
in your iOS project. CocoaPods runs prepare_command
and build the framework, than the compiled framework will be copied from spec.vendored_frameworks
to your iOS project's Pods folder and it will be available to import in Xcode.
If you have any questions feel free to ask :)
@romanandreyvich Oh, I got it thanks, And what about the version(git tag), could you show me an example 😄 , I want to know how to control the version of kotlin_library pod. Also, do we need to switch linkReleaseFrameworkIos
between linkDebugFrameworkIos
according to the XCode building type?
This seems like a better solution:
spec.preserve_paths = "**/*.*"
Hi, @romanandreyvich.
I want to install kotlin/native framework as you said,
pod 'myKotlinNativeModule', :git => 'git@github.com:myRepo.git'
Can I ask you some question?
Where shoud I put gradle file?
I tried your solution with spec.prepare_command, but I had error that ./gradlew: No such file or directory
.
What are pushed in the remote repository?
I thought I can install pods if I push myKotlinNativeModule .podspec
and myModule/build/cocoapods/framework/myKotlinNativeModule.framework
, but I can't.
Please show me the tree of your remote repository.
Thank you in advance:)
Hi @romanandreyvich, thanks for the help. It works like a charm.
@robotan0921 for the beginning you need to replace your podspec at the root of the project and add a path to the framework that you build locally with a Gradle task. In my case:
path -> builds/fat-framework/release/name.framework podspec file -> spec.vendored_frameworks = "path where the framework is stored".
Also, you need to remove .framework, .podspec, and the folder where you located your framework from your .gitignore file and push it to git repo.
Than open your podfile and add next: pod 'your pod name', :git => "https://path to repo.git"
@romanandreyvich @VitaliiVasylyda How to make a fat library? What I did I basically I removed the post script from the podspec as I push to the build folder with the framework. But the issue is that this works fine when I build for iOS simulator. When I try to build on device then I get x64 architecture compilation errors
Btw do you have maybe an example how to make such setup that we have standalone GitHub repository with multi platform kotlin native framework with cocoapods support? The best if coworkers doesn't have to have java/gradle etc when the you'll like to use on iOS?
I agree with @nonameplum, I think this would be the last hurdle in adopting at many organizations. I'd love to build a framework for the iOS team without making it a hassle for them. Are there any samples to fully automate/support a fat framework and remote cocoapods?
I'm getting an error when pod lib lint'ing: building for watchOS Simulator, but linking in object file built for iOS, file shared/build/cocoapods/framework/arccosAbShared.framework/arccosAbShared' for architecture arm64
I'm running into the same roadblock myself. Creating KMM libraries for Android/JVM and pushing them to a dependency manager is super easy but I haven't found any good examples for pushing the library as a cocoapod to our internal Specs repo.
I have an alternative solution which works pretty well for us: we bundle all the KMM dependencies as one framework, this is done as part of the Xcode build using a run script build phase. Gradle takes care of retrieving all your dependencies as it would normally, so this bypasses cocoapods completely for your KMM dependencies.
Basically the procedure is as follows:
kotlin {
sourceSets {
iosMain {
dependencies {
api 'org.yourcompany:foo-model:1.0.0-SNAPSHOT'
api 'org.yourcompany:foo-module:1.0.0-SNAPSHOT'
api 'org.yourcompany:foo-foundation:1.0.0-SNAPSHOT'
}
}
}
def buildForDevice = System.getenv('SDK_NAME')?.startsWith("iphoneos")
if (buildForDevice) {
println("Building for device")
iosArm64("ios") {
binaries {
framework()
}
compilations.all {
kotlinOptions {
}
}
}
} else {
println("Building for simulator")
iosX64("ios") {
binaries {
framework()
}
compilations.all {
kotlinOptions {
}
}
}
}
kotlin.targets.ios.binaries.withType(org.jetbrains.kotlin.gradle.plugin.mpp.Framework) {
export 'org.yourcompany:foo-model:1.0.0-SNAPSHOT'
export 'org.yourcompany:foo-module:1.0.0-SNAPSHOT'
export 'org.yourcompany:foo-foundation:1.0.0-SNAPSHOT'
transitiveExport = true
isStatic = false
}
}
cd MHKit
BUILD_DIR="$BUILT_PRODUCTS_DIR/MHKit"
if [ "$CONFIGURATION" == "Debug" ]; then
echo "Building debug framework"
./gradlew -Dorg.gradle.project.buildDir="$BUILD_DIR" $DAEMON --info --offline $REFRESH linkDebugFrameworkIos || exit 1
cp -RP "$BUILD_DIR/bin/ios/debugFramework/MHKit.framework" "$CONFIGURATION_BUILD_DIR"
cp -RP "$BUILD_DIR/bin/ios/debugFramework/MHKit.framework.dSYM" "$CONFIGURATION_BUILD_DIR"
else
echo "Building release framework"
./gradlew -Dorg.gradle.project.buildDir="$BUILD_DIR" $DAEMON --info --offline $REFRESH clean linkReleaseFrameworkIos || exit 1
cp -RP "$BUILD_DIR/bin/ios/releaseFramework/MHKit.framework" "$CONFIGURATION_BUILD_DIR"
fi
The approach above has the added benefit that it only builds the framework for the required configuration/architecture as part of the Xcode build. In you KMM projects you should only have to build and deploy the klib, not the debug/release architecture dependent frameworks which significantly reduces the build time (and I mean a lot!). Gradle/Xcode will be smart enough to only rebuild the aggregate framework if anything has changed in the dependencies.
I think that would work for us. I was hoping to be able to use our KMM libraries in existing iOS apps via cocoapods, but that isn't necessarily a dealbreaker. For newer projects, we are using KMM so pulling in dependencies is handled via gradle anyway.
In my case I have an android project with a K/N submodule and for jvm it works fine (I shouldn't do anything, it just works). For iOS I want to use CocoaPods (kotlin.native.cocoapods plugin) to get the framework into my iOS project.
And it works fine too if the both projects are exists locally. I do something like that in my Podfile:
pod 'myKotlinNativeModule', :path => '/local/path/to/project/'
And it works, but its not a good idea to store the absolute path to another project in Podfile and I want to do like that:
pod 'myKotlinNativeModule', :git => 'git@github.com:myRepo.git'
My .podspec file:
I believe CocoaPods have to download my android project from the GitHub repo, store it in a cache folder and when I gonna start to build my iOS project in Xcode, the framework will be compiled via script_phases. But in the real world this isn't happening, CocoaPods create project's folder in the cache and the folder is empty. What am i do wrong?
Is it currently possible? I use Kotlin 1.3.40
Previously I did the same with https://github.com/AlecStrong/kotlin-native-cocoapods but this lib doesn't support Kotlin 1.3.40 yet (and maybe wouldn't).
Thanks in advance.