Building iOS apps with Genero

Genero provides a command-line tool to build applications for iOS devices.

Basics

Genero mobile apps for iOS are distributed as IPA packages like any other iOS app. Genero provides a command line tool to build the .ipa package for your mobile application, or the .app directory for simulators.

Note: This documentation section assumes that you are familiar with iOS app programming concepts and requirements. In order to build your apps, you must have an Apple developer account, as well as certificates and provisioning profiles to deploy your apps. For more details, visit the Apple developer site at https://developer.apple.com.

Prerequisites

Before starting the command line tool to build or deploy the app, fulfill the following prerequisites:
  • The Genero BDL development environment (FGLDIR) must be installed on the Mac computer to compile your program files.
  • The GMI build tool must be installed and available (check that the gmibuildtool command is available).
    Note: The GMI build tool is provided as a ZIP archive (fjs-fglgmi-*.zip) that must be extracted directly into FGLDIR.
    Important: When re-installing a new GMI archive, remove all "build" directories created by the gmibuildtool.
  • An Apple developer account, device identifiers (UDID) and corresponding identifiers to sign your iOS app (certificate, bundle id, provisioning profile).
    Important: The UDID is the identifier of your physical device, it can be found with the instruments -s command when the device is plugged to the Mac. When deploying on a physical device, make sure that the UDID of the device is listed in the Apple Developer account that is used to generate the provisioning profiles.
  • XCode must be installed on your Mac OS X computer (utilities from XCode toolchain are required).
    Note: Make sure that the installed XCode version supports the iOS versions of your mobile devices. As a general rule, update the XCode and iOS to the latest versions.
  • iOS app resources such as icons and launch images (in all required sizes).

Finding the UDID of the plugged device

In order to find the UDID of the device plugged to your Mac, execute the instruments -s command, and identify the line describing your physical device:
$ instruments -s
Known Devices:
fraise [55D6D6C1-DE87-52F0-865E-3C6DC79F13D7]
Fourjs2 iPod touch (9.1) [78b7452fa9462c98c3bc7047da344314fd032004]
iPad 2 (9.0) [19CDA827-CA55-46F1-9376-BF61E2ECFDBB]
iPad Air (9.0) [F55E1207-C42B-472E-BD76-5B5AE46DE77A]
iPad Air 2 (9.0) [A0E8C4CD-67CD-42CB-84DF-9C75AC773293]
...
Known Templates:
"Activity Monitor"
"Allocations"
...

In the above output, the UDID of the iPod is 78b7452fa9462c98c3bc7047da344314fd032004.

Environment settings

Before starting the command-line build tool,
  • Make sure that XCode tools are available (try xcodebuild from the command line)

Creating the GMI front-end for development purpose

Four Js is not allowed to provide a ready-to-use front-end component for iOS devices, because of iOS app limitations defined by Apple: An iOS app shipped on the App Store cannot listen to a TCP port to provide a GUI service. Therefore, you will have to create your own GMI front-end, with your own Apple certificate and provisioning profile. The generated GMI can then be deployed on your device or simulator for development purpose listening on the port 6400, to display applications running on a server (FGLSERVER).

In order to build your own GMI front-end:
  1. Make sure that the gmibuildtool is available (if not done yet, extract the fjs-fglgmi*.zip archive into FGLDIR).
  2. Go to the FGLDIR/demo/MobileDemo/gmiclient directory.
  3. Delete the complete build directory if it exists (can be done with a make clean command).
  4. Make the GMI app with make (program files like main.42m file must exist).
  5. Build the GMI front-end:
    • In order to build only the GMI front-end (GMI.app directory) for the simulator, execute the gmibuildtool command without any parameter:
      $ gmibuildtool
    • In order to build and install the GMI front-end on the simulator, first make sure that the simulator is started (open -a simulator command), then execute the gmibuildtool command with following parameters:
      $ gmibuildtool --device booted
    • In order to build only the GMI front-end IPA for devices, get a development certificate and provisioning profile and execute the gmibuildtool command with following parameters:
      $ gmibuildtool \
          --device phone \
          --certificate HGRW8... \
          --provisioning "~/Library/MobileDevice/Provisioning Profiles/myapp.mobileprovision"

      The generated IPA file can be found in the build subdirectory. This IPA file can be installed on your devices by using iTunes.

    • In order to build and install the GMI front-end on the device plugged to your Mac, get a development certificate and provisioning profile, and the exact device name (with the instruments -s command) and execute the gmibuildtool command with following parameters::
      $ gmibuildtool \
          --device "Mike's iPhone 6 (9.0)"  \
          --certificate HGRW8... \
          --provisioning "~/Library/MobileDevice/Provisioning Profiles/myapp.mobileprovision"

Specifying the target to build and deploy the iOS app

The gmibuildtool command can build and install iOS apps for the simulator or for physical devices.

The build and/or install action is controlled by the --device option:

  • By default, when not specifying the --device option, a GMI.app directory is created for the simulator.
  • When specifying the --device booted option, the GMI.app directory is created and the app is installed on the booted simulator.
  • When specifying the --device phone option, the GMI.app directory and .ipa file are created.
  • When specifying the --device physical-device-name option (with a real physical device name plugged on your Mac), the GMI.app directory and .ipa file are created and the app is installed on the device.

By default, the generated GMI.app directory and .ipa archive can be found in $PWD/build sub-directories. However you can specify the destination IPA file with the --output option.

Elements used to build the iOS app

The gmibuildtool command builds the iOS app package from the following:
  • The GMI binary archive, containing the GMI front end and the FGL runtime system library,
    Note: These files are provided in the fjs-fglgmi-*.zip archive that must be extracted directly under FGLDIR.
    Important: When re-installing a new GMI archive, remove all "build" directories created by the gmibuildtool.
  • The compiled application program and resource files (.42m, .42f, etc),
    Note: The application program files must include a main.42m or main.42r module.
  • The display name of the app (--app-name parameter),
  • The version of the app (--app-version parameter),
  • The debug or release mode (--mode parameter),
  • The certificate (to sign the app) (--certificate parameter),
  • The bundle Identifier (--bundle-id parameter),
  • The app provisioning profile (.mobileprovision file) (--provisioning parameter),
  • iOS app specific resources:
    • App icons (--icons parameter),
    • Launch images (--launch-images parameter) or launch storyboard file (--storyboard parameter).

For a complete description of command options, see gmibuildtool.

Default build directory structure

For convenience, the build tool supports a default directory structure to find all files required to build the app:

top-dir
|
|-- main.42m and other program files, as described in Directory structure for GMI apps
|
|-- gmi
|   |
|   |-- Info.plist
|   |
|   |-- LaunchScreen.storyboard
|   |
|   |-- Default@2x.png
|   |-- Default-568h@2x.png
|   |-- Default-Landscape.png
|   |-- Default-Landscape-667h@2x.png
|   |-- Default-Landscape-736h@3x.png
|   |-- Default-Landscape@2x.png
|   |-- Default-Portrait.png
|   |-- Default-Portrait-736h@3x.png
|   |-- Default-Portrait-667h@2x.png
|   |-- Default-Portrait@2x.png
|   |   ...
|   |-- icon_29x29.png
|   |-- icon_40x40.png
|   |-- icon_57x57.png
|   |-- icon_58x58.png
|   |-- icon_72x72.png
|   |-- icon_76x76.png
|   |-- icon_80x80.png
|   |-- icon_120x120.png
|   |-- icon_152x152.png
|   |   ...
In the above directory structure:
  1. top-dir is the top directory of the default structure. It will typically hold your application program files. A different program files directory can be specified with the --program-files option.
  2. top-dir/gmi is the default directory containing the app resource files such as icons:
    1. Info.plist is the Information Property List File that will be used to build the app. Some properties will be overwritten by gmibuildtool options like --app-name and --app-version.
    2. LaunchScreen.storyboard is the default storyboard file for the app launch screen. This file can be specified with the gmibuildtool --storyboard option.
    3. Default-*.png are the app launch image files. The directory to find launch images can be specified with the gmibuildtool --launch-images option.
    4. icon_*.png are the app icon files. The directory to find icons can be specified with the gmibuildtool --icons option.

Debug and release versions

iOS apps can be generated in a debug or release version. Release version are prepared for distribution on the App Store, while debug versions are used in development.

In debug mode, the app installed on the device can listen on the debug TCP port to allow fgldb -m connections, after enabling the debug port in the app settings.

Debug or release mode must be specified in the command line with the --mode debug or --mode release option. Additionnally, if you want to deploy on a physical device, you need to use a provisioning profile corresponding to the debug or release mode:

Defining the app version and build number

Apple distinguishes the app version number of a bundle (visible to the end user), from the build version number of a bundle (called a release version number in Apple docs).

You specify the app version number with the --app-version option of the gmibuildtool command. This option sets the CFBundleVersion property of the Info.plist file), and must match the version specified in iTunes Connect.

In order to distinguish multiple builds (Apple's term is "releases") of the same app version number, define the build version number of your app with the --build-number option. This option sets the CFBundleShortVersionString property of the Info.plist file. For a given app version, you need to increase this build number, to be able to upload a new binary on iTunes Connect.

Note: If you do not specify the --build-number option, the build version number defaults to the app version specified with the --app-version option.

Defining app properties in the ./gmi/Info.plist file

iOS app are created with a set of properties that are essential configuration information for a bundled executable. These properties are defined in the "Information Property List File", an XML formatted file, named Info.plist by convention.

Most important Info.plist properties are defined with gmibuildtool options such as --app-name and --app-version. However, you may need to define other properties that are out of the scope of the build tool. For example: background modes, device capabilities, screen orientations, permanent wifi, etc.

In order to define specific app properties, setup an Info.plist file in top-dir/gmi directory, before executing the gmibuildtool. Properties covered by the build tool will be overwritten, while any other property defined in the top-dir/gmi/Info.plist file will be left untouched.

For more details about the Info.plist file structure, see Apple developer site page about Information Property List File.

Building an iOS app with gmibuildtool

Follow the next steps to setup a GMI app build directory in order to create an iOS app, based on the default directory structure:

  1. Create the root distribution directory (top-dir)
  2. Copy compiled program files (.42m, .42f, fglprofile, application images, web component files, etc) under top-dir.
  3. Copy the default English .42s compiled string resource file under top-dir.
  4. Create non-English langage directories (fr, ge, ...) under top-dir and copie the corresponding .42s files.
  5. Copy default application data files (database file for ex) under top-dir.
  6. Create the top-dir/gmi directory.
  7. Copy iOS app resources (icons, launch screen, storyboard) under top-dir/gmi.
  8. If needed, create an top-dir/gmi/Info.plist file, to define specific iOS app properties.
Once the build directory is prepared, issue the following commands:
$ cd top-dir
$ gmibuildtool \
    --output myapp.ipa \
    --app-name "My App" \
    --app-version "v3.1.6" \
    --bundle-id "com.example.mycompany.myapp" \
    --mode release \
    --certificate HGRW8... \
    --provisioning "~/Library/MobileDevice/Provisioning Profiles/myapp.mobileprovision" \
    --device phone

Building a GMI app with C extensions or custom front calls

In order to create an iOS app using C extensions written in Objective-C as in Implementing C-Extensions for GMI, you need to setup a Makefile calling the FGLDIR/lib/Makefile-gmi generic makefile file.

In your Makefile, define the following variables to be passed to the generic makefile:
  • APPNAME: Defines the display name of the app.
  • BUNDLE_IDENTIFIER: Defines the Bundle Id (or App Id) of the app.
  • IDENTITY: Defines the certificate to be used for this app.
  • PROVISIONING_PROFILE: Defines the provisioning profile generated for this app.
  • USEREXTENSION: Defines the lib name containing the C extensions.
  • TARGET: Defines the device where the app must be installed (can be phone or simulator).
Custom Makefile example:
...

all: $(MODULES) $(FORMS) ...

run: all userextension.dylib
      fglrun -e userextension main

userextension.dylib: userextension.c
      fglmkext $?
...

GMI_OPTIONS = \
   APPNAME=MyApp \
   BUNDLE_IDENTIFIER=com.mycomany.myapp \
   IDENTITY=HGRW8... \
   PROVISIONING_PROFILE=~/Library/MobileDevice/Provisioning\ Profiles/myapp.mobileprovision \
   USEREXTENSION=userextension.o \
   TARGET=phone

GMI_MAKE = make -f $(FGLDIR)/lib/Makefile-gmi $(GMI_OPTIONS)

gmi.all: all
      $(GMI_MMAKE) all

gmi.install: all
      $(GMI_MMAKE) install

gmi.uninstall:
      $(GMI_MMAKE) uninstall

gmi.info:
      $(GMI_MMAKE) info

gmi.clean:
      ~$(GMI_MMAKE) clean

The same technique can be used to build apps that must include custom front calls.

For complete examples, see FGLDIR/demo/MobileDemo/userextension and FGLDIR/demo/MobileDemo/userfrontcall