Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions .github/workflows/ios-packaging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
name: Test iOS packaging

on:
pull_request:
paths:
- '.github/workflows/ios-packaging.yml'
- 'maven/codenameone-maven-plugin/**'
- 'vm/ByteCodeTranslator/**'
- 'scripts/build-ios-app.sh'
- 'scripts/run-ios-ui-tests.sh'
- 'scripts/run-ios-native-tests.sh'
- 'scripts/ios/**'
- 'scripts/hellocodenameone/**'
- '!docs/**'
push:
branches: [ master ]
paths:
- '.github/workflows/ios-packaging.yml'
- 'maven/codenameone-maven-plugin/**'
- 'vm/ByteCodeTranslator/**'
- 'scripts/build-ios-app.sh'
- 'scripts/run-ios-ui-tests.sh'
- 'scripts/run-ios-native-tests.sh'
- 'scripts/ios/**'
- 'scripts/hellocodenameone/**'
- '!docs/**'

jobs:
packaging-matrix:
permissions:
contents: read
runs-on: macos-15
timeout-minutes: 75
strategy:
fail-fast: false
matrix:
packaging:
- name: pods-only
args: >-
-Dcodename1.arg.ios.dependencyManager=cocoapods
-Dcodename1.arg.ios.pods=AFNetworking
- name: spm-only
args: >-
-Dcodename1.arg.ios.dependencyManager=spm
-Dcodename1.arg.ios.spm.packages=swift-collections|https://github.com/apple/swift-collections.git|from:1.1.0
-Dcodename1.arg.ios.spm.products.swift-collections=Collections
- name: both
args: >-
-Dcodename1.arg.ios.dependencyManager=both
-Dcodename1.arg.ios.pods=AFNetworking
-Dcodename1.arg.ios.spm.packages=swift-collections|https://github.com/apple/swift-collections.git|from:1.1.0
-Dcodename1.arg.ios.spm.products.swift-collections=Collections
steps:
- uses: actions/checkout@v4

- name: Ensure CocoaPods tooling
run: |
mkdir -p ~/.codenameone
cp maven/UpdateCodenameOne.jar ~/.codenameone/
set -euo pipefail
GEM_USER_DIR="$(ruby -e 'print Gem.user_dir')"
export PATH="$GEM_USER_DIR/bin:$PATH"
gem install cocoapods xcodeproj --no-document --user-install
pod --version
- name: Compute setup-workspace hash
id: setup_hash
run: |
set -euo pipefail
echo "hash=$(shasum -a 256 scripts/setup-workspace.sh | awk '{print $1}')" >> "$GITHUB_OUTPUT"
- name: Set TMPDIR
run: echo "TMPDIR=${{ runner.temp }}" >> $GITHUB_ENV

- name: Cache codenameone-tools
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/codenameone-tools
key: ${{ runner.os }}-cn1-tools-${{ steps.setup_hash.outputs.hash }}
restore-keys: |
${{ runner.os }}-cn1-tools-
- name: Restore cn1-binaries cache
uses: actions/cache@v4
with:
path: ../cn1-binaries
key: cn1-binaries-${{ runner.os }}-${{ steps.setup_hash.outputs.hash }}
restore-keys: |
cn1-binaries-${{ runner.os }}-
- name: Setup workspace
run: ./scripts/setup-workspace.sh -q -DskipTests
timeout-minutes: 40

- name: Build iOS port
run: ./scripts/build-ios-port.sh -q -DskipTests
timeout-minutes: 40

- name: Build sample iOS app
id: build_ios_app
env:
IOS_DEPENDENCY_ARGS: ${{ matrix.packaging.args }}
run: ./scripts/build-ios-app.sh -q -DskipTests
timeout-minutes: 30

- name: Run iOS UI smoke
env:
ARTIFACTS_DIR: ${{ github.workspace }}/artifacts/${{ matrix.packaging.name }}
run: |
set -euo pipefail
mkdir -p "${ARTIFACTS_DIR}"
./scripts/run-ios-ui-tests.sh \
"${{ steps.build_ios_app.outputs.workspace }}" \
"" \
"${{ steps.build_ios_app.outputs.scheme }}"
timeout-minutes: 30

- name: Run native iOS notification tests
if: matrix.packaging.name == 'both'
env:
ARTIFACTS_DIR: ${{ github.workspace }}/artifacts/${{ matrix.packaging.name }}-native
run: |
set -euo pipefail
mkdir -p "${ARTIFACTS_DIR}"
./scripts/run-ios-native-tests.sh \
"${{ steps.build_ios_app.outputs.workspace }}" \
"${{ steps.build_ios_app.outputs.scheme }}"
timeout-minutes: 20

- name: Upload packaging artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: ios-packaging-${{ matrix.packaging.name }}
path: artifacts
if-no-files-found: warn
retention-days: 14
140 changes: 140 additions & 0 deletions .github/workflows/scripts-ios-native.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
name: Test iOS native test scripts

on:
pull_request:
paths:
- '.github/workflows/scripts-ios-native.yml'
- 'scripts/setup-workspace.sh'
- 'scripts/build-ios-port.sh'
- 'scripts/build-ios-app.sh'
- 'scripts/run-ios-native-tests.sh'
- 'scripts/ios/create-shared-scheme.py'
- 'scripts/ios/notification-tests/native-tests/**'
- 'scripts/ios/notification-tests/install-native-notification-tests.sh'
- 'scripts/ios/notification-tests/**'
- 'scripts/hellocodenameone/**'
- 'scripts/templates/**'
- '!scripts/templates/**/*.md'
- 'CodenameOne/src/**'
- '!CodenameOne/src/**/*.md'
- 'Ports/iOSPort/**'
- '!Ports/iOSPort/**/*.md'
- 'vm/**'
- '!vm/**/*.md'
- 'tests/**'
- '!tests/**/*.md'
- '!docs/**'
- 'maven/**'
- '!maven/core-unittests/**'
push:
branches: [ master ]
paths:
- '.github/workflows/scripts-ios-native.yml'
- 'scripts/setup-workspace.sh'
- 'scripts/build-ios-port.sh'
- 'scripts/build-ios-app.sh'
- 'scripts/run-ios-native-tests.sh'
- 'scripts/ios/create-shared-scheme.py'
- 'scripts/ios/notification-tests/native-tests/**'
- 'scripts/ios/notification-tests/install-native-notification-tests.sh'
- 'scripts/ios/notification-tests/**'
- 'scripts/hellocodenameone/**'
- 'scripts/templates/**'
- '!scripts/templates/**/*.md'
- 'CodenameOne/src/**'
- '!CodenameOne/src/**/*.md'
- 'Ports/iOSPort/**'
- '!Ports/iOSPort/**/*.md'
- 'vm/**'
- '!vm/**/*.md'
- 'tests/**'
- '!tests/**/*.md'
- '!docs/**'
- 'maven/**'
- '!maven/core-unittests/**'

jobs:
native-ios:
permissions:
contents: read
runs-on: macos-15
timeout-minutes: 65
concurrency:
group: mac-ci-${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true

steps:
- uses: actions/checkout@v4

- name: Ensure CocoaPods tooling
run: |
mkdir -p ~/.codenameone
cp maven/UpdateCodenameOne.jar ~/.codenameone/
set -euo pipefail
if ! command -v ruby >/dev/null; then
echo "ruby not found"; exit 1
fi
GEM_USER_DIR="$(ruby -e 'print Gem.user_dir')"
export PATH="$GEM_USER_DIR/bin:$PATH"
gem install cocoapods xcodeproj --no-document --user-install
pod --version
- name: Compute setup-workspace hash
id: setup_hash
run: |
set -euo pipefail
echo "hash=$(shasum -a 256 scripts/setup-workspace.sh | awk '{print $1}')" >> "$GITHUB_OUTPUT"
- name: Set TMPDIR
run: echo "TMPDIR=${{ runner.temp }}" >> $GITHUB_ENV

- name: Cache codenameone-tools
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/codenameone-tools
key: ${{ runner.os }}-cn1-tools-${{ steps.setup_hash.outputs.hash }}
restore-keys: |
${{ runner.os }}-cn1-tools-
- name: Restore cn1-binaries cache
uses: actions/cache@v4
with:
path: ../cn1-binaries
key: cn1-binaries-${{ runner.os }}-${{ steps.setup_hash.outputs.hash }}
restore-keys: |
cn1-binaries-${{ runner.os }}-
- name: Setup workspace
run: ./scripts/setup-workspace.sh -q -DskipTests
timeout-minutes: 40

- name: Build iOS port
run: ./scripts/build-ios-port.sh -q -DskipTests
timeout-minutes: 40

- name: Build sample iOS app
id: build_ios_app
env:
IOS_UISCENE: "false"
run: ./scripts/build-ios-app.sh -q -DskipTests
timeout-minutes: 30

- name: Run native iOS notification tests (XCTest)
env:
ARTIFACTS_DIR: ${{ github.workspace }}/artifacts/native-ios-tests
run: |
set -euo pipefail
mkdir -p "${ARTIFACTS_DIR}"
./scripts/run-ios-native-tests.sh \
"${{ steps.build_ios_app.outputs.workspace }}" \
"${{ steps.build_ios_app.outputs.scheme }}"
timeout-minutes: 25

- name: Upload native iOS artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: ios-native-tests
path: artifacts
if-no-files-found: warn
retention-days: 14
17 changes: 3 additions & 14 deletions .github/workflows/scripts-ios.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Test iOS build scripts
name: Test iOS UI build scripts

on:
pull_request:
Expand Down Expand Up @@ -127,11 +127,11 @@ jobs:
- name: Setup workspace
run: ./scripts/setup-workspace.sh -q -DskipTests
# per-step timeout
timeout-minutes: 25
timeout-minutes: 40

- name: Build iOS port
run: ./scripts/build-ios-port.sh -q -DskipTests
timeout-minutes: 25
timeout-minutes: 40

- name: Build sample iOS app and compile workspace (UIScene on)
id: build-ios-app-scene
Expand Down Expand Up @@ -179,17 +179,6 @@ jobs:
"${{ steps.build-ios-app.outputs.scheme }}"
timeout-minutes: 30

- name: Run native iOS notification tests (XCTest)
env:
ARTIFACTS_DIR: ${{ github.workspace }}/artifacts
run: |
set -euo pipefail
mkdir -p "${ARTIFACTS_DIR}"
./scripts/run-ios-native-tests.sh \
"${{ steps.build-ios-app.outputs.workspace }}" \
"${{ steps.build-ios-app.outputs.scheme }}"
timeout-minutes: 20

- name: Upload iOS artifacts
if: always()
uses: actions/upload-artifact@v4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ Codename One supports debugging applications on devices by using the natively ge

In iOS this is usually strait forward, just open the project with xcode and run it optionally disabling bitcode. Unzip the .bz2 file and open the `.xcworkspace` file if it's available otherwise open the `.xcodeproj` file inside the `dist` directory.

IMPORTANT: Only the `.xcworkspace` if it is there, it is activated by the CocoaPods build pipeline so it won't always be there
IMPORTANT: The `.xcworkspace` is no longer exclusive to CocoaPods-based builds. Use it whenever it is generated, whether the project uses CocoaPods, Swift Package Manager, or both.

With Android Studio this is sometimes as very easy task as it is possible to actually open the gradle project in Android Studio and just run it. However, due to the fragile nature of the gradle project this stopped working for some builds and has been "flaky".

Expand Down
18 changes: 18 additions & 0 deletions docs/developer-guide/Working-With-iOS.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ However, it seems that Apple will reject your app if you just include that and d

=== Using Cocoapods

NOTE: CocoaPods remains fully supported, but it is no longer the only supported iOS dependency path. Swift Package Manager (SPM) is also supported. The current guidance is documented in this section.

https://cocoapods.org/[CocoaPods] is a dependency manager for Swift and Objective-C Cocoa projects. It has over eighteen thousand libraries and can help you scale your projects elegantly. Cocoapods can be used in your Codename One project to include native iOS libraries without having to go through the hassle of bundling the actual library into your project. Rather than bundling .h and .a files in your ios/native directory, you can specify which "pods" your app uses via the `ios.pods` build hint. (There are other build hints also if you need more advanced features).

**Examples**
Expand Down Expand Up @@ -252,6 +254,22 @@ ios.pods=GoogleMaps

(Note that the `ios.pods.sources` directive is optional).

=== Using Swift Package Manager

Swift Package Manager can be used as an alternative to CocoaPods for remote Swift package dependencies on iOS. Select the dependency path with `ios.dependencyManager`. Supported values are `auto`, `cocoapods`, `spm`, and `both`.

For an SPM-only configuration, declare the packages in `ios.spm.packages` using the format `<identity>|<url>|<requirement>` and then declare the products to link using `ios.spm.products.<identity>`.

----
ios.dependencyManager=spm
ios.spm.packages=swift-collections|https://github.com/apple/swift-collections.git|from:1.1.0
ios.spm.products.swift-collections=Collections
----

Supported requirement formats are `from:`, `exact:`, `branch:`, `revision:`, and `range:`.

`ios.dependencyManager=auto` preserves backward compatibility. Existing projects with only `ios.pods` continue to use CocoaPods. Projects with only `ios.spm.*` use SPM. If both hint families are present, both are applied.

=== Including Dynamic Frameworks

If you need to use a dynamic framework (e.g. SomeThirdPartySDK.framework), and it isn't available via cocoapods, then you can add it to your project by simply zipping up the framework and copying it to your native/ios directory.
Expand Down
2 changes: 2 additions & 0 deletions docs/website/content/blog/cocoapods.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ author: Steve Hannah

![Header Image](/blog/cocoapods/cocoapods.png)

_Editor note: CocoaPods remains supported, but current iOS dependency guidance now also covers Swift Package Manager (SPM) and mixed CocoaPods/SPM setups. See the current "Working with iOS" section in the developer guide._

[CocoaPods](https://cocoapods.org/) is a dependency manager for Swift and Objective-C Cocoa projects.
It has over eighteen thousand libraries and can help you scale your projects elegantly. Cocoapods can be
used in your Codename One project to include native iOS libraries without having to go through the hassle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ author: Shai Almog

![Header Image](/blog/tip-use-ios-cocoapods-dependencies-native-code/tip.jpg)

_Editor note: This post is still valid for CocoaPods, but current iOS dependency setup also supports Swift Package Manager (SPM). See the current "Working with iOS" section in the developer guide._

Last week I talked about [using gradle dependencies](/blog/tip-use-android-gradle-dependencies-native-code.html) to build native code, this week I’ll talk about the iOS equivalent: CocoaPods. We’ve [discussed CocoaPods before](/blog/cocoapods.html) but this bares repeating especially in the context of a specific cn1lib like [intercom](/blog/intercom-support.html).

CocoaPods allow us to add a native library dependency to iOS far more easily than Gradle. However, I did run into a caveat with target OS versioning. By default we target iOS 7.0 or newer which is supported by Intercom only for older versions of the library. Annoyingly CocoaPods seemed to work, to solve this we had to explicitly define the build hint `ios.pods.platform=8.0` to force iOS 8 or newer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ These are unresolved questions, but we are poised to find out their answers, as

### iOS Builds

The Local iOS build target generates an Xcode project that you can open and build directly in Xcode. This target necessarily requires a Mac with Xcode and cocoapods installed. See [Building for iOS](https://shannah.github.io/cn1-maven-archetypes/cn1app-archetype-tutorial/getting-started.html#ios) from [this tutorial](https://shannah.github.io/cn1-maven-archetypes/cn1app-archetype-tutorial/getting-started.html) for more information.
The Local iOS build target generates an Xcode project that you can open and build directly in Xcode. This target requires a Mac with Xcode installed. CocoaPods is only required for CocoaPods-based builds; projects that use Swift Package Manager use the normal Apple toolchain instead. See the current "Working with iOS" section in the developer guide and [Building for iOS](https://shannah.github.io/cn1-maven-archetypes/cn1app-archetype-tutorial/getting-started.html#ios) for more information.

![intellij-build-ios-project](https://www.codenameone.com/wp-content/uploads/2021/04/intellij-build-ios-project.png)

Expand Down
Loading
Loading