Skip to content
  • Services
  • About
  • Partners
  • Work
  • Insights
  • Careers
  • Contact
  • Services
  • About
  • Partners
  • Work
  • Insights
  • Careers
  • Contact
November 17, 2015

Cordova Automation – xcodebuild Hangs in iOS Build

DevOps

The Cordova Command Line Interface (CLI) has come a long way since it was introduced with Cordova 3.0 back in the summer of 2013. Developers can use this to create, configure, and build apps – greatly reducing the need to directly use “traditional” tools such as Xcode for iOS and Eclipse for Android.

The Cordova CLI has also enabled a much more straightforward Continuous Integration (CI) workflow for building and distributing Cordova based apps. At Modus Create, we’ve had success using the Jenkins and Circle CI products to build our Cordova apps for Android and iOS, often paired with HockeyApp to push the resulting binaries to test users for on-device testing.

Whilst the Cordova CLI gets us all of the way to a distributable .apk file on Android, we still have to use the Apple command line tool xcodebuild to archive and sign our .ipa file for iOS apps. In doing so, we found that xcodebuild can hang when working with projects generated by the Cordova CLI. However, there is a relatively simple fix for this that allows us to complete the iOS CI workflow without ever having to resort to opening Xcode interactively.

New Cordova Projects Make xcodebuild Hang

If we create a new Cordova project, and attempt to use xcodebuild with it, we find that xcodebuild hangs and never exits. To demonstrate this, try the following in a Terminal window:

cordova create someapp com.mycompany.someapp SomeApp
cd someapp
cordova platform add ios
cordova build ios
cd platforms/ios
xcodebuild -list

This creates a new app, adds the iOS platform to it, builds iOS, then attempts to use xcodebuild to list the schemes in the project. A scheme is a build configuration, and xcodebuild -list should list all schemes in the project. However, the command hangs and never returns because the Xcode project that the Cordova CLI created for us seems to lack any schemes.

So, rather than a list of schemes, the output we see from xcodebuild -list looks like:

$ xcodebuild -list
Information about project "SomeApp":
    Targets:
        SomeApp

    Build Configurations:
        Debug
        Release

    If no build configuration is specified and -scheme is not passed then "Release" is used.

The command never returns. This also applies when we try to use xcodebuild to archive the project and generate our .ipa file.

This causes issues with a CI workflow, as we can’t check out our project from source control then generate an .ipa for upload to HockeyApp, TestFlight, or other app testing platforms using scripts alone.

Solution: Create Schemes in Cordova’s iOS Project

There are two ways we can create the schemes that xcodebuild needs to find in our Cordova iOS project.

1. Open the Project with the XCode IDE

Opening platforms/ios/SomeApp.xcodeproj with the Xcode IDE, then simply quitting Xcode will fix the issue, and xcodebuild -list now does what we would expect and returns when finished:

$ xcodebuild -list
Information about project "SomeApp":
    Targets:
        SomeApp

    Build Configurations:
        Debug
        Release

    If no build configuration is specified and -scheme is not passed then "Release" is used.

    Schemes:
        SomeApp
        CordovaLib

This is great, but doesn’t help with our goal to have a CI workflow, as a CI server isn’t going to open Xcode interactively, then quit it. We need something that is more scriptable and performed as part of our build process.

Thankfully, we can achieve this using some relatively simple scripting, which is our second option.

2. Add Schemes Programmatically Using a Build Hook Script

Opening Xcode to have it generate the required schemes works well enough when building on a developer’s local machine, but not when using a CI server. Here, we want a repeatable, automated, “lights out” process that runs without user intervention.

It is also considered bad practice to commit the platforms folder of a Cordova project to source control, because everything in there can — and should — be generated by the Cordova CLI. Given that the Xcode project files live in the platforms folder, we should really use a script based approach to maintain a repeatable process.

For this, we’ll need something that allows us to perform housekeeping tasks on Xcode projects using command line tools. Fortunately, the Xcodeproj Ruby Gem was designed to do just that, and allows us to create schemes in a project.

Installation of the Xcodeproj Gem is simple:

sudo gem install xcodeproj

Then, all we need to do is write a small script to use it to add the schemes to the project, and to have that run whenever the iOS platform is added to the project. The Cordova CLI supports extensions to customize existing actions using hook scripts. We can add a script named fix_xcode_schemes.rb to the hooks folder of the Cordova project, and save the following into it:

#!/usr/bin/env ruby
require 'xcodeproj'
xcproj = Xcodeproj::Project.open("platforms/ios/schemedemo.xcodeproj")
xcproj.recreate_user_schemes
xcproj.save

This will modify the project to add the schemes that xcodebuild needs to work properly. We need to make sure this script can be executed so let’s set the permissions on it appropriately from the terminal:

chmod 755 hooks/fix_xcode_schemes.rb

Then to make sure our script is run at the appropriate point (after cordova platform add ios completes), we need to configure the hook in the project’s config.xml file by adding the following hook element inside the iOS platform element.

<platform name="ios">
    <hook type="after_platform_add" src="hooks/fix_xcode_schemes.rb" />
    ...
</platform>

Now, whenever we first clone the project from source control, our custom script will fix the schemes for us as soon as the iOS platform is installed, and we can then build the project, archive and sign an .ipa all at the command line or under the control of our CI server.

Conclusion

Out of the box, a newly created Cordova project does not enable a Continuous Integration workflow because the auto generated Xcode project lacks scheme definitions that xcodebuild requires. This causes xcodebuild to freeze and stops the build process.

We have demonstrated that this can easily be fixed using the Xcodeproj Ruby Gem and a Cordova build hook script to add the missing schemes. This allows us to build the project entirely from the command line under the control of a Continuous Integration server such as Jenkins or Circle CI.

To help you get your Cordova project builds automated, I’ve created an example project with the hook script configured, and have made it available via GitHub.

Maybe you’ve hit similar issues with automating your Cordova workflow, or perhaps you’ve found some better solutions. Let us know in the comments or on Twitter; we’d love to hear from you.

Posted in DevOps
Share this

Simon Prickett

Simon Prickett is a pragmatic technology enthusiast with broad experience of technical consultancy, product and software development, technical training, software architecture, development and system analysis. Simon has developed and led solutions for clients including MTV Networks, Coca-Cola and USA Today. Simon graduated top of his class from Aston University. During his time with Modus Create, Simon filled the role of Architect.
Follow

Related Posts

  • Swift
    Writing a Cordova Plugin in Swift 3 for iOS

    This blog post is an update to one I wrote back in April 2016 and…

  • Cordova 5 & iOS 9 Security Policy Changes
    Cordova 5 & iOS 9 Security Policy Changes

    Modus recommends Cordova 5 as it contains improvements to developer workflow, bug fixes, performance enhancements…

Subscribe to the Modus Newsletter

Receive the latest blog articles and insights every month from the Modus team.

Let's Chat

If forms aren’t your thing, you can always call us (+1-855-721-7223).

Modus-Logo-Primary-White.svg
  • Services
  • About
    • Newsroom
  • Partners
  • Work
  • Insights
    • Blog
    • Modus Labs
  • Careers
Virginia (US)

12100 Sunset Hills Road
Suite 150
Reston, Virginia, 20190
Tel: +1-855-721-7223

California (US)
12130 Millennium Dr

Los Angeles, CA 90094

Missouri (US)
609 E High St

Jefferson City, MO 65101

Romania

Str. Mihai Veliciu, no. 17
Cluj-Napoca, Romania
Tel: +40-0786-887-444

Costa Rica

2nd Floor, Plaza Koros, Av 3
San José, Santa Ana, Costa Rica

© 2021 Modus. All Rights Reserved.

Privacy Policy | Accessibility Statement | Sitemap

This website uses cookies.
These cookies are used to collect information about how you interact with our website and allow us to remember you. We use this information in order to improve and customize your browsing experience, and for analytics and metrics about our visitors both on this website and other media. To find out more about the cookies we use, see our Privacy Policy.

Accept
Privacy & Cookies Policy

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary
Always Enabled

Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.

Non-necessary

Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.

Scroll To Top