How to Use static libraries in Flutter iOS? - xcode

I'm trying to add a static library to my Flutter project, it doesn't matter whether it's a plugin or a script, as long as it can be referenced as a module in AppDelegate.swift.
I have tried adding a static library in the plugin project. Specifying the source file in the .podspec file. but it not working. So.. What are the steps to add a static library to a flutter plugin project?
Because the plugin project can only verify the result in the Example project. How should I confirm whether the static library of the plug-in project has been added successfully? Where to reference the header files of a static library?
Pod::Spec.new do |s|
s.name = 'hello'
s.version = '0.0.1'
s.summary = 'A new Flutter plugin project.'
s.description = <<-DESC
A new Flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email#example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.vendored_libraries = 'Classes/**/*.a'
s.dependency 'Flutter'
s.platform = :ios, '11.0'
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
s.swift_version = '5.0'
end

Related

How can I write a settings plugin as Gradle script

I have some code in my settings.gradle file to dynamically create references to version catalogs:
// list of catalogs is actually loaded from a file
def catalogs = [ "com.example:mycatalog:1.0" ]
dependencyResolutionManagement {
versionCatalogs {
catalogs.each { String catalog ->
def catalogName = catalog.split(":")[1] + "Libs"
logger.info "Add version catalog ${catalogName} = ${catalog}"
create(catalogName, { from(catalog) })
}
}
}
And now I want to share that as a Gradle plugin.
I know that I can write a project plugin as a precompiled script plugin with *.gradle files in src/main/groovy directory.
But then Gradle always builds a Plugin<Project> plugin.
How can I declare that I want to a have Plugin<Settings> plugin? Or is this not even possible?

How to set the repository my library depends into the artifact?

I've a Android library that generates an artifact. This library have some dependencies in itself that are resolved from jitpack, but currently, if the user of the library don't add jitpack to their dependency repoisitories my library will fail to resolve.
How can I add to my artifact the repositories it depends so the user that uses my library don't have to add jitpack to their dependencies?
This is the current code I use for publishing:
afterEvaluate {
publishing {
repositories {
maven {
Properties properties = new Properties()
if (project.rootProject.file('local.properties').canRead()) {
properties.load(project.rootProject.file("local.properties").newDataInputStream())
}
name = "GitHub"
description = "PROJECT NAME"
url = uri("PROJECT PRIVATE REPO URL")
credentials {
username = properties.getProperty("REPO_PACKAGES_USERNAME") ?: System.getenv("REPO_PACKAGES_USERNAME")
password = properties.getProperty("REPO_PACKAGES_TOKEN") ?: System.getenv("REPO_PACKAGES_TOKEN")
}
}
}
components.all((component) -> {
def componentName = component.getName()
println("componentName: ${componentName}")
def isDebug = componentName == "debug"
publishing.publications.create("publication-$componentName", MavenPublication) {
from component
groupId = "com.foo.bar"
version = "${android.defaultConfig.versionName}${isDebug ? '-DEBUG' : ''}"
}
})
}
}
You can't control the repositories of your consumers, as this would be a security vulnerability.
The best thing to do would be to publish your library to maven central, as this repository is almost universally used for Java dependencies.

Share dependency versions across multiple Version Catalogs

I'm trying to find a way to share a dependency's version across multiple Version Catalog toml files.
For example, say I have the following two Version Catalog toml files:
libs.versions.toml
[versions]
dagger = "2.42"
[libraries]
dagger-android = { module = "com.google.dagger:dagger-android", version.ref = "dagger" }
buildLibs.versions.toml
[versions]
dagger = "2.42"
[libraries]
hiltAndroidGradlePlugin = { module = "com.google.dagger:hilt-android-gradle-plugin", version.ref = "dagger" }
I use the same dagger version across both Version Catalogs, and when I need to bump the dagger version I have to remember to update all toml files.
My workaround is to share the version using the Version Catalog builder API by doing:
In my settings.gradle
ext.sharedVersions = [ dagger : "2.42"]
dependencyResolutionManagement {
versionCatalogs {
libs {
version('dagger', sharedVersions.dagger)
library('dagger-android', 'com.google.dagger', 'dagger-android').versionRef('dagger')
}
buildLibs {
version('dagger', sharedVersions.dagger)
library('hiltAndroidGradlePlugin', 'com.google.dagger', 'hilt-android-gradle-plugin').versionRef('dagger')
}
}
}
which works, but takes away from my dependencies being centralized as some are declared in toml files, while other are declared in settings.gradle.
As of now, the Version Catalog Builder API is the recommended solution.
https://discuss.gradle.org/t/share-dependency-versions-across-multiple-version-catalogs/43145

Kotlin Multi Platform framwork CodeSig problem on a Mac OS application

I created a module using kotlin multi-platform and is it is working perfectly on Android and iOS, but when I try to do the same for a macOS app I get the following error:
XYZ.app: code object is not signed at all
Command CodeSign failed with a nonzero exit code
I'm generating the framework as follow:
kotlin {
jvm("android")
macosX64("mac") {
binaries {
framework {
baseName = "XyzForMac"
}
}
}
def iosClosure = {
binaries {
framework {
baseName = "XyzForIos"
}
}
}
if (System.getenv("SDK_NAME")?.startsWith("iphoneos")) {
iosArm64("ios", iosClosure)
} else {
iosX64("ios", iosClosure)
}
sourceSets {…}
}
task packForXcode(type: Sync) {
def targetDir = new File(buildDir, "xcode-frameworks")
def mode = System.getenv("CONFIGURATION") ?: "DEBUG"
def frameworkMac = kotlin.targets.getByName("mac").binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn frameworkMac.linkTask
from frameworkMac.outputDirectory
into targetDir
def frameworkIos = kotlin.targets.getByName("ios").binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn frameworkIos.linkTask
from frameworkIos.outputDirectory
into targetDir
doLast {
def gradlew = new File(targetDir, "gradlew")
gradlew.text = """\
|#!/bin/bash
|export 'JAVA_HOME=${System.getProperty("java.home")}'
|cd '${rootProject.rootDir}'
|./gradlew \$#""".stripMargin().stripIndent()
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)
It looks I'm doing everything correctly, especially because the app is running as expected on Android and iOS. I'm wondering if I missing any mac os specific configuration to make it works…
I solve the problem changing the approach, instead of using the custom task packForXcode and importing manually the framework, I'm using now the CocoaPods integration, so what I did:
Using cocoapods, deleting the packForXcode task (and the custom steps on Xcode)
I'm moving the targets to a specific block on gradle build:
Because I'm using cocoapods there are no different packed binaries anymore
kotlin {
targets { // <-- this is new
jvm("android")
macosX64("mac") {
binaries {
framework("Xyz") // Removed the ForMac
}
}
def iosClosure = {
binaries {
framework("Xyz") // Removed the ForIos
}
}
if (System.getenv("SDK_NAME")?.startsWith("iphoneos")) {
iosArm64("ios", iosClosure)
} else {
iosX64("ios", iosClosure)
}
}
cocoapods {…} // cocoa pods block
sourceSets {…}
}

Multiple configurations for a task in my build.gradle

I'm using this awesome Gradle plugin to compile my iOS projet.
According to the documentation my build.gradle looks like this :
buildscript {
repositories {
maven {
url('http://openbakery.org/repository/')
}
mavenCentral()
}
dependencies {
classpath group: 'org.openbakery', name: 'xcodePlugin', version: '0.9.+'
}
}
apply plugin: 'xcode'
task wrapper(type: Wrapper) {
gradleVersion = '1.12'
}
xcodebuild {
workspace = 'WORKSPACE'
sdk = 'iphoneos'
target = 'TARGET'
signing {
mobileProvisionURI = 'URI'
certificateURI = 'URI'
certificatePassword = 'PASSWORD'
}
scheme = 'SCHEME'
configuration = 'CONFIGURATION'
}
How can I manage multiple configurations for my xcodebuild task ?
I would like something like
...
xcodebuild-staging {
workspace = 'STAGING_WORKSPACE'
sdk = 'iphoneos'
target = 'STAGING_TARGET'
signing {
mobileProvisionURI = 'URI'
certificateURI = 'URI'
certificatePassword = 'STAGING_PASSWORD'
}
scheme = 'STAGING_SCHEME'
configuration = 'STAGING_CONFIGURATION'
}
xcodebuild-production {
workspace = 'PRODUCTION_WORKSPACE'
sdk = 'iphoneos'
target = 'PRODUCTION_TARGET'
signing {
mobileProvisionURI = 'PRODUCTION_URI'
certificateURI = 'PRODUCTION_URI'
certificatePassword = 'PRODUCTION_PASSWORD'
}
scheme = 'PRODUCTION_SCHEME'
configuration = 'PRODUCTION_CONFIGURATION'
}
...
I tried multiple things : create a new task that calls xcodebuild.execute() or extend xcodebuild. None of them worked like I wanted to.
I ended having different build.gradle files...
Do you know how to do that ?
After a quick investigation of the source it seems that, what You need is impossible (and it seems a bit strange - such a plugin should enable user to build multiple schemes). I suggest You to contact with the author.
It might be possible! Have you tried adding the task type as a property? something like...
task xcodebuild-staging (type: org.openbakery.XcodeBuildTask) {
workspace = 'STAGING_WORKSPACE'
sdk = 'iphoneos'
target = 'STAGING_TARGET'
signing {
mobileProvisionURI = 'URI'
certificateURI = 'URI'
certificatePassword = 'STAGING_PASSWORD'
}
scheme = 'STAGING_SCHEME'
configuration = 'STAGING_CONFIGURATION'
}
task xcodebuild-production (type: org.openbakery.XcodeBuildTask){
workspace = 'PRODUCTION_WORKSPACE'
sdk = 'iphoneos'
target = 'PRODUCTION_TARGET'
signing {
mobileProvisionURI = 'PRODUCTION_URI'
certificateURI = 'PRODUCTION_URI'
certificatePassword = 'PRODUCTION_PASSWORD'
}
scheme = 'PRODUCTION_SCHEME'
configuration = 'PRODUCTION_CONFIGURATION'
}
It is dependent on how the plugin is written but you can override tasks like this as long as there is not significant config supplied by the plugin. I have found that plugins can also be extended https://docs.gradle.org/current/userguide/custom_plugins.html#custom_plugins
but that's more complex.

Resources