- Intro
- Running macOS in a VirtualBox
- Install XCode
- Install socat
- Creating the project
- Share the project folder
- Development tools: React Native and Figwheel
- Run the project
- Trigger.io Forge Documentation
- Developing iOS apps on Linux¶
- Setting up Forge to run iOS apps¶
- Creating a signing certificate¶
- Creating a provisioning profile¶
Intro
If you are a developer writing mobile applications in the year 2019, chances are you are working with React Native. React Native workflow is split into two separate steps. One is the packager, an engine which lets you work with the native mobile UI components through JavaScript, that reloads every time you save your JavaScript code. The other is the simulator.
Unfortunately, to run the iOS simulator and do any kind of iOS development you need a macOS and the XCode IDE. If you’re like me, my Linux setup is just paramount to my productivity and I can’t imagine working without e.g. a tiling window manager or keyboard shortcuts perfected by the years of practice 🙂
In this blog post I will show you the setup and workflow that allows you to write your code in the OS and code editor of your choice 1 , while still running the iOS simulator.
Re-Natal is a CLI tool to automate the setup of a React Native app running on ClojureScript. In a few simple commands it will bootstrap a skeleton application with reagent + re-frame, REPL and hot reloading (using Figwheel) directly to the simulated iOS device, just like you would if it was a web app running in a browser.
If you like the idea let’s get started.
We are going to install all the neccessary development tools on the host machine, and just the bare minimum required to run the iOS simulator on a guest macOS running in a VirtualBox, then make the two machines talk to each other via forwarded ports.
Running macOS in a VirtualBox
Begin by insatlling VirtualBox 6.X for your distribution, you can get it from here or directly from your OS repositories:
sudo apt install virtualbox virtualbox-dkms virtualbox-ext-pack virtualbox-guest-additions-iso virtualbox-guest-utils virtualbox-qt
Now download the vmdk with macos, for example from Techsviewer. Launch VB and create new virtual machine from the image. Make sure to name the VM without using spaces (e.g. macos). Give the machine at least 2 cores, 4GB of RAM, and 128MB of graphics with 3D acceleration turned on, set the VB Network Adapter to Bridged:
Close Virtualbox for now. Now you can download the setup script, graciously made availiable by hkdb.
Save the script, make it executable and call it with the name of your vm and the desired resolution as the arguments:
./setup.sh -v "macos" -r 1920x1080
Launch VirtualBox again and start the MacOS VM.
Install XCode
Once the VM boots you can install the XCode version for the MacOS version you are running:
You can use the App Store, or for the older versions of the IDE they can be downloaded from here.
Once installed launch Xcode, select menu > Preferences > Locations and choose your Xcode version from the dropdown:
Install socat
For bidirectional data communication between the Linux host and macOS guest we will use socat. MacOS doesn’t have a native package manager, therefore we will need Homebrew installed. Start the Terminal and install it:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
then using homebrew install socat:
We are done with the guest for now, lets go to the host and create our project.
Creating the project
Lets start by installing re-natal and react-native. Both come as convenient node packages, that we can install globally:
npm install -g re-natal react-native
You will also need Leiningen and Java 8, but we won’t cover installing them here.
Once that’s done we can create the skeleton app. Mind the CamelCase in the apps name:
re-natal init AppName -i reagent6
Now execute some basic setup commands that will bootstrap the app as an iOS project:
cd app-name/ re-natal use-ios-device simulator re-natal use-figwheel
Share the project folder
We will need to share the projects directory with the guest. In principle virtualbox can share folders betwen the host and the guest using Guest Additions, however I was unable to get it going 2 .
Instead I opted for using the samba server. Every major Linux distro should have it in its repositories:
sudo apt-get install samba
Now create a user (samba will prompt you for the password):
Next edit the samba config:
sudo nano /etc/samba/smb.conf
Add to the end of the config, substitutting path with the path to the just created re-natal project and user with the created samba user:
[] path = /home// valid users = read only = no
You can test the config file for configuration errors by calling: testparm on the command line. If all is fine with the config, go ahead and start the Samba service daemon plus enable it at startup:
systemctl restart smbd systemctl enable smbd
Development tools: React Native and Figwheel
We will now start the react-native packager, binding it to port 8081 and broadcasting on 0.0.0.0:
react-native start --host 0.0.0.0 --port 8081
Next we can start Figwheel, which will give us the REPL, as well as watch and recompile on source code changes:
Figwheel will recompile the sources and just hang for now, waiting for connection with the simulator to give us the REPL, but not before printing the port on which it is running (3449 by default). Last piece of information we need is the local IPv4 address of the host (e.g. 192.168.1.3 ), which we can get with:
Now let’s go back to the guest OS.
Run the project
On the guest we can now start listening on the ports occupied by the react-native and Figwheel servers:
socat tcp-listen:3449,reuseaddr,fork tcp:192.168.1.3:3449 socat tcp-listen:8081,reuseaddr,fork tcp:192.168.1.3:8081
Next lets mount the shared folder. Click on the Go -> connect to server…, paste smb://192.168.1.3 and click on Connect:
When prompted for the username and password use the ones created when Sharing the project folder. by default the directory is mounted as /Volumes/app-name/ . Open this directory in XCode, wait until it indexes the project and run it.
Once the project is up and running Figwheel on the host box should now give you a fully functional REPL, with live reloading on code edits:
From now on the workflow is quite snappy and un-obtrusive, you can for example keep you editor and the simulator tiled one next to the other and quickly iterate during development.
1: Allthough I don’t see how you could use anything else but Linux/Emacs combo.
2: Please let me know in the comment box if you had any luck yourself and how have you done it.
Trigger.io Forge Documentation
This documentation is deprecated, and only kept here to support users of browser extension APIs. If you are using Trigger.io for iOS or Android, see https://trigger.io/docs/.
Developing iOS apps on Linux¶
Forge allows the development of iOS apps on Linux without the use of an OS X machine. To do this you will need a physical iOS device (the iOS simulator will only run on OS X), and an iOS developer account. In order to sign your application (which is required to install it onto the device, even for testing), we provide a remote signing service, which your app will be sent to, signed and returned as part of the forge run ios and forge package ios command.
Setting up Forge to run iOS apps¶
- Apple iOS developer account.
- ideviceinstaller installed on the device you are going to develop with
- An iOS device connected via USB to the machine you wish to develop on
In order to sign your application you need to provide us with the following:
Both of these can be created and managed from the Apple iOS provisioning portal, which should be accessible from the iOS developer center: https://developer.apple.com/ios/. The instructions on that site are for OS X, more detailed instructions for creating a developer certificate on Linux are included below.
Once these are setup you should be able to use forge run ios to install the app on your device.
Creating a signing certificate¶
To create a certificate you need to generate a certificate signing request, in Linux this can be done by following these steps:
- Run openssl req -subj "/CN=Connor Dunn/O=User" -nodes -newkey rsa:2048 -keyout private.key -out request.csr replacing Connor Dunn with your name as registered with your Apple ID.
- On the iOS provisioning portal site choose to create a new certificate and upload the file request.csr you just created
- Your certificate request should be approved shortly: when it is, download it to the folder you ran the original command, the next steps assume it is called ios_development.cer .
- Run openssl x509 -inform der -in ios_development.cer -out certificate.pem to convert the certificate format
- Run openssl pkcs12 -export -in certificate.pem -inkey private.key -name "iOS Developement Certificate" -out certificate_with_key.p12 to package the certificate and key. The password you supply will be the one you need to provide to Forge, and prevents unauthorized users from using the certificate if they were to come into possession of the certificate file.
- You should now be able to configure the developer_certificate_path and developer_certificate_password in your local_config.json file.
This will leave you with a few files you no longer need, you can safely delete request.csr , ios_development.cer and certificate.pem . You can also delete private.key as it is included in the p12 file, if you don’t delete it you should store it securely as it can be used to sign with your certificate. You should keep certificate_with_key.p12 to use with Forge, and make sure it and the password are stored securely so others can’t sign as you.
Creating a provisioning profile¶
Once you have created a certificate you need to create a provisioning profile, this is also done via the iOS provisioning portal website:
- First make sure your device has been added to the provisioning portal, to do this you will need the device identifier (UDID), this can be found by clicking on the device’s serial number in iTunes.
- Next create an app id, for development entering * as a Bundle Identifier is recommended, as it means multiple apps can be signed with a single provisioning profile.
- Finally create a development provisioning profile, making sure you choose the correct app id and enable any devices you wish to be able to test with.
- You can now download and configure the location of your provisioning profile in local_config.json .
Provisioning profiles must be recreated if certificates or devices are changed.