Most of the time, iOS apps are developed and distributed from macOS machines. It’s hard to imagine developing apps for the iOS platform without macOS. However, with the combination of Flutter and Codemagic, you can develop and distribute iOS apps without using macOS. In our previous post, we have explained the process of code signing iOS apps without a Mac. In this post, we will cover in detail the process of developing Flutter apps on Linux and using custom/manual code signing with Codemagic to have full control over app signing on the example of Comagic-Demo app.
Developing Flutter apps on Linux
Flutter is a cross-platform mobile application development framework that enables to develop iOS and Android apps from the same source code. However, Apple’s native frameworks used for developing iOS apps cannot compile on other platforms like Linux or Windows. The native iOS components require a macOS or Darwin for developing and distributing iOS apps. However, technologies like Flutter allow us to develop cross-platform apps on Linux or Windows and we can then distribute the apps to Google Play Store or Apple App Store using the Codemagic CI/CD solution.
Getting a Flutter app on Linux
Android apps can be built, tested and published from the Linux platform. We can take advantage of this Android feature to enable Flutter app development on Linux. We have a Flutter app called Comagic-Demo. We will use that app to show how to build for Android & iOS on Linux. However, keep in mind that, we can only develop against Android on Linux not iOS. We will still get iOS app that can be deployed to App Store while developing Android app on Linux. We can get our Comagic-Demo to Linux using different ways.
Get a Linux machine
If you already have a computer with Linux installed on it, then the whole process is easy. You just have to install Android SDK and Flutter on the Linux machine. Once we clone the Comagic-Demo app, we can start working on it straightway.
Create Docker containers
Another way to get a Flutter app on Linux is by using Docker. If you are familiar with the Docker ecosystem, then you can create a Dockerfile which has Android SDK and Flutter installed. There are many Android Dockerfiles on Dockerhub, we just need to extend those images with Flutter SDK. Let’s create a simple Dockerfile extending a sample Android docker image here to get the Android and Flutter environment into the Docker container. The Dockerfile should copy the app into the container and run the Flutter Android environment. The example Dockerfile for Comagic-Demo will look like this:
FROM runmymind/docker-android-sdk RUN mkdir /codemagic-demo WORKDIR /codemagic-demo ADD . /codemagic-demo RUN apt-get update && \ apt-get install -y lcov git-core curl unzip && \ git clone https://github.com/flutter/flutter.git && \ /flutter/bin/flutter doctor && \ apt-get remove -y curl unzip && \ apt autoremove -y && \ rm -rf /var/lib/apt/lists/* ENV PATH $PATH:/flutter/bin/cache/dart-sdk/bin:/flutter/bin RUN flutter doctor
This code snippet is just for illustration purposes, but you can customize the Dockerfile as per your needs. Once you have the Dockerfile and Docker installed, you can get the Codemagic-app using Docker.
$ docker build -t codemagic-demo . $ docker run --name codemagic-demo
Once we run these commands, we will have the Docker container running with Flutter environment.
Dockerising Futter apps will be a different topic and we will cover it in details in a future post.
Generating code signing assets from App Store Connect
In order to code sign iOS apps, you need an Apple developer account, a development and a distribution certificate, your app ID and provisioning profiles created for the app. We have covered the details of code signing activities in a previous post. In order to configure manual code signing for the development or debug builds of iOS apps on Codemagic, we need following things:
- Development or distribution certificate in .P12 format
- Downloaded provisioning profile from App Store Connect or Apple Developer portal
- Bundle identifier of the iOS app
We can download both the certificate and the provisioning profiles from the Certificates, Identifiers and Profiles sections in Apple Developer portal.
Similarly, we can download the provisioning profiles from the Apple developer portal.
We need both a certificate and a provisioning profile to code sign our iOS app on Codemagic, so save these files for using later.
Updating Xcode project files
Now, we have got all the code signing assets from Apple Developer portal. Next, we need to sort out the Xcode project file so as to use manual code signing with the correct team and provisioning profile. We can do this by using a Ruby script using Xcodeproj Gem or we can just change the following fields in the ios/YOUR_APP.xcodeproj/project.pbxproj file.
- DevelopmentTeam = YOUR_DEVELOPMENT_TEAM_ID
- ProvisioningStyle = Manual
- PROVISIONING_PROFILE_SPECIFIER = NAME_OF_YOUR_PROVISIONING_PROFILE
In our Codemagic-Demo app, we have to edit the Xcode project file here on GitHub. We have to make sure to make these changes for the debug configuration for internal builds and for the release configuration for App Store builds. Once we set the values in project.pbxproj, we are ready to deploy the iOS app from Codemagic without any issues.
Setting up manual code signing in Codemagic
When developing on Linux, we can only see the state of the Android app as Xcode and iOS tooling can not be installed or run on Linux. There are some ongoing efforts to bring Swift and iOS tooling on Linux but it will take lot of time. When we are ready to distribute the apps, we can easily set up CI/CD for the app using Codemagic, see the Getting Started Guide. On Codemagic, we can enable iOS code signing from the Publish section by uploading the certificate and the provisioning profile that we have downloaded from Apple Developer portal. In the Codemagic app, navigate to Settings → Publish → iOS code signing → Manual and upload your certificate and provisioning profile there.
When you now run the build, you will get the iOS app in the form of the IPA file which can be deployed on the provisioned devices. The list of build artifacts on Codemagic will look like this:
As can be seen in the Artifacts section, we got codemagic_demo.ipa as well as dSYMs files for crash reports. We can install this app on any iOS device that had been added to the provisioning profile and test our iOS app. If we see any bugs there, we can always go back to the Linux environment and fix those bugs.
Distributing iOS app to App Store
As of now, we have built the debug version of the iOS app for testing internally. In a similar way, we can distribute the iOS app to the App Store. When we are ready to deploy the app to the App Store, we need to build the app in Release mode and using the distribution certificate and production provisioning profile. We can generate the the certificate and profiles in a similar way but we have to make sure to choose App Store distribution while creating the provisioning profile.
The distribution provisioning profile will run the iOS app on any device and we don’t need to add the devices explicitly in the provisioning profile. The App Store provisioning profile will look like this:
Once, we have the iOS distribution certificate and the production provisioning profile at hand, we can select the Release mode in the Build section in Codemagic as shown below.
We have also set the build arguments to release instead of debug. In the Publish section, we need to upload the distribution certificate and the production provisioning profile to generate the App Store version of the app.
Once Codemagic generates the build artifacts, we can the build to the App Store Connect, formerly known as iTunesConnect, following the App Store guidelines and submit the app for review.
With the combination of a cross-platform mobile application development framework and a magical CI/CD solution like Codemagic, owning a Mac for iOS app development isn’t mandatory at all. There might be some issues in debugging the app while developing for iOS, but it’s completely possible to develop and publish iOS apps to the App Store using the combination of Flutter and Codemagic.