Exporting a distribution IPA with XCode 8

What’s the recommended way for exporting a distribution IPA for uploading to the AppStore with XCode 8? Is there a gradle task for this, or does it have to be done via the generated XCode project?

Hi Paul,

we like to build our distribution IPAs with Jenkins so the build can be easily reproduced if necessary. We use the xcodebuild archive task in a Jenkins build pipeline to create a distribution archive. Depending on how your Xcode project is checked into version control, you might need to overwrite the signing identity using environment variables.

It is also possible to use the Gradle plugin to make an IPA, but in most cases the project is configured for development (e.g. the signing configuration), not for distribution.

We have a feature request to provide support for generating distribution IPA (in addition to the developer IPA): Issue 25, but it is not yet scheduled to a release.

It should be possible to create a custom Gradle task in your project to temporarily change your signing configuration to create a distribution IPA from Gradle, but we have not tried it yet.

Best Regards,
Gergely

Thanks Gergely, I’m using Jenkins as well, though still using the old-style jobs - no pipelines yet. Still, I should probably be able to do that straight on the command line. I found this site, is this about the sort of thing you’re doing?

https://pewpewthespells.com/blog/migrating_code_signing.html#building-for-distribution-xcode-8

Yes, exactly.

Technically, it should be enough to call just this, and the Java build parts should be started by the Xcode custom build phase automatically.

That said, we usually build the Java parts beforehand with Gradle, mostly because our build process includes multiple stages e.g. compiling different Java dependencies before getting to the main app itself.

I’m having a little trouble getting this to work. I’m using the call:

 xcodebuild -project ios/xcode/ios-moe.xcodeproj -scheme ios-moe -configuration Release archive -archivePath build/glitterdeep.xcarchive DEVELOPMENT_TEAM=TEAMCODEHERE

This seems to work at first, I get a lot of output, which ends with:

java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
Looking for gradlew in /Users/psiegel/code/svn/lanternboy/glitterdeep/client/ios
Looking for gradlew in /Users/psiegel/code/svn/lanternboy/glitterdeep/client

And then it just hangs. Looking at the activity monitor it’s pretty clear nothing is happening. Any thoughts on what I should try?

You need a standard gradlew wrapper script to be available in your ios module or in the folder above it.

There is one, in fact, it’s in that directory in the last message.

It’s strange, it looks like the whole process just jams up. There are still xcodebuild and gradlew processes sitting around, just nothing is happening. Activity monitor shows nothing consuming any CPU, and I’ve left it sit for half an hour without change.

:~ psiegel$ ps aux | grep xcode
psiegel 16778 0.0 0.4 2750748 61068 s001 S+ 6:21PM 0:00.95 /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project ios/xcode/ios-moe.xcodeproj -scheme ios-moe -configuration Release clean archive -archivePath build/glitterdeep.xcarchive DEVELOPMENT_TEAM=TEAMNAMEHERE
psiegel 16917 0.0 0.0 2432804 820 s000 S+ 6:28PM 0:00.00 grep xcode
:~ psiegel$ ps aux | grep gradle
psiegel 16795 0.0 0.7 8275320 115408 s001 T 6:21PM 0:01.29 /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin/java -Xdock:name=Gradle -Xdock:icon=/Users/psiegel/code/svn/lanternboy/glitterdeep/client/media/gradle.icns -Dorg.gradle.appname=gradlew -classpath /Users/psiegel/code/svn/lanternboy/glitterdeep/client/gradle/wrapper/gradle-wrapper.jar org.gradle.wrapper.GradleWrapperMain --daemon moeXcodeInternal
psiegel 16774 0.0 2.8 4608368 464568 s001 S 6:21PM 0:27.65 /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin/java -Xms128m -Xmx512m -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -cp /Users/psiegel/.gradle/wrapper/dists/gradle-2.14.1-all/4cj8p00t3e5ni9e8iofg8ghvk7/gradle-2.14.1/lib/gradle-launcher-2.14.1.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 2.14.1

Tried modifying the script in the xcode project to pass --debug and --info to the gradle call. The end of my logs before the hang now show:

Connected to daemon DaemonInfo{pid=1434, address=[0a81505b-0eca-4a2d-b24d-269771697dae port:49515, addresses:[/0:0:0:0:0:0:0:1, /127.0.0.1]], idle=false, lastBusy=1480815659515, context=DefaultDaemonContext[uid=de876bee-9270-4586-b815-47b92b864b37,javaHome=/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home,daemonRegistryDir=/Users/psiegel/.gradle/daemon,pid=1434,idleTimeout=10800000,daemonOpts=-Xms128m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant]}. Dispatching request Build{id=84aaf96e-f49d-4fe3-829a-77a9c23412ca.1, currentDir=/Users/psiegel/code/svn/lanternboy/glitterdeep/client/ios}.
Received result org.gradle.launcher.daemon.protocol.BuildStarted@46268f08 from daemon DaemonInfo{pid=1434, address=[0a81505b-0eca-4a2d-b24d-269771697dae port:49515, addresses:[/0:0:0:0:0:0:0:1, /127.0.0.1]], idle=false, lastBusy=1480815659515, context=DefaultDaemonContext[uid=de876bee-9270-4586-b815-47b92b864b37,javaHome=/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home,daemonRegistryDir=/Users/psiegel/.gradle/daemon,pid=1434,idleTimeout=10800000,daemonOpts=-Xms128m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant]} (build should be starting).

It looks like the Gradle daemon is getting stuck for some reason. As a workaround, please try to add the --no-daemon switch to the gradlew command in the Xcode project script. We are looking into this why it can happen.

Created a GH issue for tracking: Issue 68

Interestingly, that did not fix it. I still hang, just now I get this as the last bit of output:

Looking for gradlew in /Users/psiegel/code/svn/lanternboy/glitterdeep/client/ios
Looking for gradlew in /Users/psiegel/code/svn/lanternboy/glitterdeep/client
To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/2.14.1/userguide/gradle_daemon.html.

After this message it just hangs, again with gradle and xcode processes seemingly running but doing nothing.

Now, the good news is that I’ve come up with a work-around. I ended up creating one Jenkins job to build both the adhoc and the appstore IPA. I use the standard moeIpaBuild gradle target to make the adhoc IPA, and since then the java part is built I can skip that for the appstore IPA by setting the MOE_GRADLE_EXTERNAL_BUILD variable. Basically it looks like this:

./gradlew moeIpaBuild
export MOE_GRADLE_EXTERNAL_BUILD=true
cd ios
xcodebuild archive -project xcode/ios-moe.xcodeproj \
                                   -scheme ios-moe \
                                   -configuration Release \
                                   -archivePath ./build/project.xcarchive \
                                   DEVELOPMENT_TEAM=TEAMNAMEHERE
xcodebuild -exportArchive \
                   -archivePath ./build/project.xcarchive \
                   -exportOptionsPlist ./exportOptions.plist \
                   -exportPath ./build

Hi Paul,

this is interesting. Which Gradle version are you running?

We do the same in Jenkins, what you are doing here: this would have been my next suggestion – you just beat me to it :slight_smile:

Best Regards,
Gergely

psiegel$ ./gradlew --version

------------------------------------------------------------
Gradle 2.14.1
------------------------------------------------------------

Build time:   2016-07-18 06:38:37 UTC
Revision:     d9e2113d9fb05a5caabba61798bdb8dfdca83719

Groovy:       2.4.4
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_111 (Oracle Corporation 25.111-b14)
OS:           Mac OS X 10.12.1 x86_64

Hi Paul,

Could you please make sure that all previously started Gradle daemons are stopped before the --no-daemon option is tried?

Are you on Sierra already, or still on El Capitan?

Best Regards,
Gergely

Hey Gergely -

Sorry I dropped the ball on this. My work-around has been working so I’m not blocked by this, which made it easy to forget about. I popped back onto the boards yesterday to get some help upgrading to 1.3 (all set there now), and saw I never replied here. I figured I might as well test again and see if anything has changed. Unfortunately it looks like it has not, I continue to see hangs if I don’t first set the MOE_GRADLE_EXTERNAL_BUILD environment variable.

I’ve updated my project to use LibGDX 1.9.6 and MOE 1.3.6. I’ve set it up to use CocoaPods using the instructions here (Generating Java Bindings in 1.3 beta - How to do so?) which is now working great. I build on two different machines, here’s the specs:

Macbook Pro Late 2016, Sierra (10.12.4), XCode 8.3.2
Mac Mini Late 2009, El Capitan (10.11.6), XCode 8.1

The mini is used as a Jenkins slave for automated builds. Unfortunately it so old it doesn’t support Sierra or XCode 8.3. I’m sure this will eventually bite me in the ass.

If you want me to run any further specific tests, just let me know. Great job on 1.3 BTW - the CocoaPods integration is really nice, and my IPA dropped from 79 MB to 54 MB!

Paul

Hi Paul,

thanks for the updates. Good to know that MOE 1.3 is working well for you!

Best Regards,
Gergely