I have a problem with our ant script / Jenkins since using CocoaPods (which I think is not the real cause for the problem, it's more a class of problems), which turned the Xcode project in a Xcode workspace.
We use Jenkins for the OTA (over the air) distribution.
Therein is a job, which executes an ant script. The build.xml is:
<project name="iOS Compile" default="simulatorbuild" basedir=".">
<!-- properties -->
<property file="default.properties" />
<property environment="env" />
<property name="sdk.simulator" value="iphonesimulator${sdk.version}" />
<property name="sdk.device" value="iphoneos${sdk.version}" />
<property name="build.dir" location="build"/>
<!-- clean -->
<target name="clean">
<exec executable="xcodebuild" failonerror="true">
<arg line="clean" />
</exec>
<delete dir="${build.dir}" />
<mkdir dir="build"/>
</target>
<!-- simulator build -->
<target name="simulatorbuild" depends="clean">
<exec executable="xcodebuild" failonerror="true">
<arg line="-sdk ${sdk.simulator}" />
<arg line="-configuration ${config.simulator}" />
<!--<arg line="-target ${target.app}" />-->
<arg line="-workspace ${app.title}.xcworkspace" />
<arg line="-scheme ${app.title}" />
</exec>
</target>
<!-- simulator build for code coverage -->
<target name="-cc_simulatorbuild">
<exec executable="xcodebuild" failonerror="true">
<arg line="-sdk ${sdk.simulator}" />
<arg line="-configuration ${config.simulator}" />
<!--<arg line="-target ${target.app}" />-->
<arg line="-workspace ${app.title}.xcworkspace" />
<arg line="-scheme ${app.title}" />
<!-- Changing some project settings to activate code coverage. -->
<!--<arg line="OTHER_CFLAGS=- -coverage" /> -->
<arg line="GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES" />
<arg line="GCC_GENERATE_TEST_COVERAGE_FILES=YES" />
<!--<arg line="GCC_PRECOMPILE_PREFIX_HEADER=NO" />-->
</exec>
</target>
<!-- device build -->
<target name="devicebuild">
<exec executable="xcodebuild" failonerror="true">
<arg line="-sdk ${sdk.device}" />
<arg line="-configuration ${config.device}" />
<!--<arg line="-target ${target.app}" />-->
<arg line="-workspace ${app.title}.xcworkspace" />
<arg line="-scheme ${app.title}" />
</exec>
</target>
<!-- unit tests -->
<target name="unittest" depends="simulatorbuild">
<exec executable="xcodebuild" output="${build.dir}/tmp" errorproperty="error.unittest">
<arg line="-sdk ${sdk.simulator}" />
<arg line="-configuration Debug" />
<arg line="-target ${target.unittests}" />
</exec>
<exec executable="ruby">
<arg line="ocunit2junit.rb" />
<arg file="${build.dir}/tmp" />
</exec>
<delete file="${build.dir}/tmp" />
</target>
<!-- code coverage -->
<target name="codecoverage" depends="-cc_simulatorbuild">
<exec executable="xcodebuild" output="${build.dir}/tmp" errorproperty="error.unittest">
<arg line="-sdk ${sdk.simulator}" />
<arg line="-configuration Debug" />
<arg line="-target ${target.unittests}" />
<!-- Changing some project settings to activate code coverage. -->
<!--<arg line="OTHER_CFLAGS=- -coverage" /> -->
<arg line="GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES" />
<arg line="GCC_GENERATE_TEST_COVERAGE_FILES=YES" />
</exec>
<exec executable="ruby">
<arg line="ocunit2junit.rb" />
<arg file="${build.dir}/tmp" />
</exec>
<delete file="${build.dir}/tmp" />
<mkdir dir="${build.dir}/code-coverage"/>
<exec executable="python">
<arg line="gcovr" />
<arg line="-x" /> <!-- set XML-Output-->
<arg line="-v" /> <!-- set more output details -->
<arg line="-r '${basedir}'" /> <!-- set the root dir -->
<arg line="-o '${build.dir}/code-coverage/coverage.xml'" />
</exec>
</target>
<!-- Distribute Target -->
<target name="distribute" depends="devicebuild">
<echo message="Set up Over-The-Air-Distribution"/>
<property name="fileprefix" value="${env.JOB_NAME}-${env.BUILD_NUMBER}-${config.device}"/>
<property name="app.path" value="${build.dir}/${config.device}-iphoneos/${target.app}.app"/>
<property name="dSYM.path" value="${build.dir}/${config.device}-iphoneos/${target.app}.app.dSYM"/>
<property name="output.dir" location="${basedir}/output"/>
<delete dir="${output.dir}" />
<mkdir dir="${output.dir}/${fileprefix}" />
<exec executable="perl">
<arg line="parsePlist.pl" />
<arg line="${target.app}" />
</exec>
<property file="${target.app}-Infoplist.properties" />
<!-- generate ipa file -->
<exec executable="xcrun" failonerror="true">
<arg line="-verbose" />
<arg line="-sdk ${sdk.device}" />
<arg line="PackageApplication" />
<arg line="-v '${app.path}'" />
<arg line="-o '${output.dir}/${fileprefix}/${app.title}.ipa'" />
<arg line="--sign '${codesign}'" />
<arg line="--embed '${basedir}/${provisioningprofile}'" />
</exec>
<!-- manage app icons -->
<copy file="${basedir}/${icon.small}" tofile="${output.dir}/${fileprefix}/Icon-57.png"/>
<copy file="${basedir}/${icon.large}" tofile="${output.dir}/${fileprefix}/Icon-512.png"/>
<!--copy file="${dSYM.path}" tofile="${output.dir}/${fileprefix}/${target.app}.app.dSYM"/-->
<!-- generate app manifest -->
<echoxml file="${output.dir}/${fileprefix}/app-manifest.plist">
<!--<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">-->
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>${OTAURL}/output/${fileprefix}/${app.title}.ipa</string>
</dict>
<dict>
<key>kind</key>
<string>full-size-image</string>
<key>needs-shine</key>
<true/>
<key>url</key>
<string>${OTAURL}/output/${fileprefix}/Icon-512.png</string>
</dict>
<dict>
<key>kind</key>
<string>display-image</string>
<key>needs-shine</key>
<true/>
<key>url</key>
<string>${OTAURL}/output/${fileprefix}/Icon-57.png</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>${CFBundleIdentifier}</string>
<key>bundle-version</key>
<string>${CFBundleShortVersionString} #${env.BUILD_NUMBER}</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>${app.title}</string>
<key>subtitle</key>
<string>${app.subtitle}</string>
</dict>
</dict>
</array>
</dict>
</plist>
</echoxml>
</target>
</project>
There is also a default.properties file:
# default properties
sdk.version = 5.1
app.title = <APP_NAME>
app.subtitle = <APP_NAME>
config.simulator = Debug
config.device = Release
target.app = <APP_NAME>
target.unittests = <APP_NAME>Test
provisioningprofile = <APP_NAME>AdHoc.mobileprovision
codesign = iPhone Distribution: <COMPANY_NAME>
icon.small = Icon.png
icon.large = Icon@2x.png
OTAURL = http://<COMPANY_NAME>.com/OTA/<APP_NAME>
When I run
ant distribute
on my local machine (not even on the CI server), the following error occurs:
[exec] error: Specified application doesn't exist or isn't a bundle directory : '/Users/<MY_USERNAME>/Documents/<COMPANY_NAME>/projects/<APP_NAME>/build/Release-iphoneos/<APP_NAME>.app'
I did a lot of researching the last days. But now, I don't, what else to do ...
What I got so far:
Since Xcode 4, the build path is no longer your project directory, but instead a unique folder in the user library. The settings for this can be found under "Derived Data". "Legacy" is the project folder and "unique" (the new default setting) is the user library.
The dependency of "distribute" is "devicebuild". That target uses the unique folder and correctly creates it under
/Users//Library/Developer/Xcode/DerivedData
On the other side (in the target "distribute") the only line I need to change is
< arg line="-v '${app.path}'" />
which points to the local / project directory.
Instead of the app.path I need to set the unique folder (user library).
In How do I print a list of "Build Settings" in Xcode project? I found a list of Xcode environment variables. The
BUILD_DIR
variable is close to what I need. It's a bit deeper in the folder hierarchy, but ok.
- I thought, perhaps is Xcrun PackageApplication, failed unable to copy application a similar problems. But it's not really the same.
Even though BUILD_DIR is not absolutely correct, I tried to use that one. But I did not succeed in that.
How do I call that Xcode env variable in my ant script? Is that even possible?
I tried:
< arg line="-v '${BUILD_DIR}'" />
< arg line="-v '$BUILD_DIR'" />
< arg line="-v 'BUILD_DIR'" />
Please, tell me which stupid mistake I did without knowing it. :-)
Really big thanks in advance! And if you need more information (even thought I don't think, there is much left I did not tell you), just ask.
Greetings and have a nice day, Dominic