as Apple announced that Xcode Cloud is now available for all developers, I tried to set it up for a Kotlin Multiplatform project. The start was a little bit hard tbh. Currently I am facing following problem during a simple test action:
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.
Command PhaseScriptExecution failed with a nonzero exit code
So I tried to install a jdk during the ci_post_clone.sh phase. The output of java -version after the installation on the Xcode Cloud is the following:
openjdk version "17.0.2" 2022-01-18
OpenJDK Runtime Environment (build 17.0.2+8-86)
OpenJDK 64-Bit Server VM (build 17.0.2+8-86, mixed mode, sharing)
Installed java
also ./gradlew -v output:
Showing All Messages
------------------------------------------------------------
Gradle 7.4.2
------------------------------------------------------------
Kotlin: 1.5.31
Groovy: 3.0.9
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 17.0.2 (Oracle Corporation 17.0.2+8-86)
OS: Mac OS X 12.4 x86_64
Nevertheless, I still get the same error. Is this maybe a restriction by Apple?
Any ideas?
Basically we install a JDK through a tar ball into the project folder using ci_post_clone.sh. We choose the project folder because we have control over this directory, contrary to for example installing java through brew (where you would have to symlink the java install into a system directory, which isn't allowed (https://developer.apple.com/documentation/xcode/making-dependencies-available-to-xcode-cloud)
Note You can use custom build scripts to perform a variety of tasks, but you can’t obtain administrator privileges by using sudo.
This is the script we use:
#!/bin/sh
root_dir=$CI_WORKSPACE_PATH
repo_dir=$CI_PRIMARY_REPOSITORY_PATH
jdk_dir="${CI_DERIVED_DATA_PATH}/JDK"
gradle_dir="${repo_dir}/Common"
cache_dir="${CI_DERIVED_DATA_PATH}/.gradle"
jdk_version="20.0.1"
# Check if we stored gradle caches in DerivedData.
recover_cache_files() {
echo "\nRecover cache files"
if [ ! -d $cache_dir ]; then
echo " - No valid caches found, skipping"
return 0
fi
echo " - Copying gradle cache to ${gradle_dir}"
rm -rf "${gradle_dir}/.gradle"
cp -r $cache_dir $gradle_dir
return 0
}
# Install the JDK
install_jdk_if_needed() {
echo "\nInstall JDK if needed"
if [[ $(uname -m) == "arm64" ]]; then
echo " - Detected M1"
arch_type="macos-aarch64"
else
echo " - Detected Intel"
arch_type="macos-x64"
fi
# Location of version / arch detection file.
detect_loc="${jdk_dir}/.${jdk_version}.${arch_type}"
if [ -f $detect_loc ]; then
echo " - Found a valid JDK installation, skipping install"
return 0
fi
echo " - No valid JDK installation found, installing..."
tar_name="jdk-${jdk_version}_${arch_type}_bin.tar.gz"
# Download and un-tar JDK to our defined location.
curl -OL "https://download.oracle.com/java/20/archive/${tar_name}"
tar xzf $tar_name -C $root_dir
# Move the JDK to our desired location.
rm -rf $jdk_dir
mkdir -p $jdk_dir
mv "${root_dir}/jdk-${jdk_version}.jdk/Contents/Home" $jdk_dir
# Some cleanup.
rm -r "${root_dir}/jdk-${jdk_version}.jdk"
rm $tar_name
# Add the detection file for subsequent builds.
touch $detect_loc
echo " - Set JAVA_HOME in Xcode Cloud to ${jdk_dir}/Home"
return 0
}
recover_cache_files
install_jdk_if_needed
After running the script for the first time, the logs will print the last echo in the script to indicate where the Java SDK is located. This value should be set as JAVA_HOME in the "Environment Variables" inside the "Edit" section of the workflow.

After that, the build will work with the Java SDK and build the artifacts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With