diff --git a/images.CI/download-repo.ps1 b/images.CI/download-repo.ps1 index 40270769..14374702 100644 --- a/images.CI/download-repo.ps1 +++ b/images.CI/download-repo.ps1 @@ -11,4 +11,4 @@ $env:GIT_REDIRECT_STDERR = '2>&1' git clone $RepoUrl . -b $RepoBranch --single-branch --depth 1 Write-Host "Latest commit:" -git log --pretty=format:"Date: %cd; Commit: %H - %s; Author: %an <%ae>" -1 \ No newline at end of file +git --no-pager log --pretty=format:"Date: %cd; Commit: %H - %s; Author: %an <%ae>" -1 \ No newline at end of file diff --git a/images/macos/helpers/Common.Helpers.psm1 b/images/macos/helpers/Common.Helpers.psm1 index 90981790..66edb878 100644 --- a/images/macos/helpers/Common.Helpers.psm1 +++ b/images/macos/helpers/Common.Helpers.psm1 @@ -85,6 +85,19 @@ function Invoke-RestMethodWithRetry { Invoke-RestMethod $Url -MaximumRetryCount 10 -RetryIntervalSec 30 } +function Invoke-ValidateCommand { + param( + [Parameter(Mandatory)] + [string]$Command + ) + + $output = Invoke-Expression -Command $Command + if ($LASTEXITCODE -ne 0) { + throw "Command '$Command' has finished with exit code $LASTEXITCODE" + } + return $output +} + function Start-DownloadWithRetry { Param diff --git a/images/macos/helpers/Xcode.Helpers.psm1 b/images/macos/helpers/Xcode.Helpers.psm1 index 52a182d5..de3b94be 100644 --- a/images/macos/helpers/Xcode.Helpers.psm1 +++ b/images/macos/helpers/Xcode.Helpers.psm1 @@ -8,9 +8,7 @@ function Get-XcodeRootPath { } function Get-DefaultXcodeRootPath { - $defaultXcodePath = "/Applications/Xcode.app" - $defaultXcodeItem = Get-Item -Path $defaultXcodePath - return $defaultXcodeItem.Target + return (Get-Item -Path "/Applications/Xcode.app").Target } function Get-XcodeToolPath { @@ -29,6 +27,21 @@ function Get-XcodeToolPath { return Join-Path $XcodeRootPath "Contents/Developer/usr/bin" $ToolName } +function Get-XcodeVersionInfo { + param( + [Parameter(Mandatory)] + [string]$XcodeRootPath + ) + + $xcodebuildPath = Get-XcodeToolPath -XcodeRootPath $XcodeRootPath -ToolName "xcodebuild" + [string]$output = Invoke-Expression "$xcodebuildPath -version" + $versionOutputParts = $output.Split(" ") + return @{ + Version = [System.Version]::Parse($versionOutputParts[1]) + Build = $versionOutputParts[4] + } +} + function Switch-Xcode { param ( [Parameter(ParameterSetName = 'Version')] diff --git a/images/macos/helpers/Xcode.Installer.psm1 b/images/macos/helpers/Xcode.Installer.psm1 new file mode 100644 index 00000000..64d2381b --- /dev/null +++ b/images/macos/helpers/Xcode.Installer.psm1 @@ -0,0 +1,212 @@ +Import-Module "$PSScriptRoot/Xcode.Helpers.psm1" + +function Install-XcodeVersion { + param( + [Parameter(Mandatory)] + [string]$Version, + [Parameter(Mandatory)] + [string]$LinkTo + ) + + $xcodeDownloadDirectory = "$env:HOME/Library/Caches/XcodeInstall" + $xcodeTargetPath = Get-XcodeRootPath -Version $LinkTo + + Invoke-DownloadXcodeArchive -Version $Version + Expand-XcodeXipArchive -DownloadDirectory $xcodeDownloadDirectory -TargetPath $xcodeTargetPath + + Get-ChildItem $xcodeDownloadDirectory | Remove-Item -Force +} + +function Invoke-DownloadXcodeArchive { + param( + [Parameter(Mandatory)] + [string]$Version + ) + + $resolvedVersion = Resolve-ExactXcodeVersion -Version $Version + if (-not $resolvedVersion) { + throw "Version '$Version' can't be matched to any available version" + } + + # TO-DO: Consider replacing of xcversion with own implementation + Write-Host "Downloading Xcode $resolvedVersion" + Invoke-ValidateCommand "xcversion install '$resolvedVersion' --no-install" +} + +function Resolve-ExactXcodeVersion { + param( + [Parameter(Mandatory)] + [string]$Version + ) + + # if toolset string contains spaces, consider it as a full name of Xcode + if ($Version -match "\s") { + return $Version + } + + $semverVersion = [SemVer]::Parse($Version) + $availableVersions = Get-AvailableXcodeVersions + $satisfiedVersions = $availableVersions | Where-Object { $semverVersion -eq $_.stableSemver } + return $satisfiedVersions | Select-Object -Last 1 -ExpandProperty rawVersion +} + +function Get-AvailableXcodeVersions { + $rawVersionsList = & xcversion list | ForEach-Object { $_.Trim() } | Where-Object { $_ -match "^\d" } + $availableVersions = $rawVersionsList | ForEach-Object { + $partStable,$partMajor = $_.Split(" ", 2) + $semver = $stableSemver = [SemVer]::Parse($partStable) + if ($partMajor) { + # Convert 'beta 3' -> 'beta.3', 'Release Candidate' -> 'releasecandidate', 'GM Seed 2' -> 'gmseed.2' + $normalizedLabel = $partMajor.toLower() -replace " (\d)", '.$1' -replace " ([a-z])", '$1' + $semver = [SemVer]::new($stableSemver.Major, $stableSemver.Minor, $stableSemver.Patch, $normalizedLabel) + } + + return [PSCustomObject]@{ + semver = $semver + rawVersion = $_ + stableSemver = $stableSemver + } + } + + return $availableVersions | Sort-Object -Property semver +} + +function Expand-XcodeXipArchive { + param( + [Parameter(Mandatory)] + [string]$DownloadDirectory, + [Parameter(Mandatory)] + [string]$TargetPath + ) + + $xcodeXipPath = Get-ChildItem -Path $DownloadDirectory -Filter "Xcode_*.xip" | Select-Object -First 1 + + Write-Host "Extracting Xcode from '$xcodeXipPath'" + Push-Location $DownloadDirectory + Invoke-ValidateCommand "xip -x $xcodeXipPath" + Pop-Location + + if (Test-Path "$DownloadDirectory/Xcode-beta.app") { + Write-Host "Renaming Xcode-beta.app to Xcode.app" + Rename-Item -Path "$DownloadDirectory/Xcode-beta.app" -NewName "Xcode.app" + } + + if (-not (Test-Path "$DownloadDirectory/Xcode.app")) { + throw "XIP archive '$xcodeXipPath' doesn't contain 'Xcode.app'" + } + + Write-Host "Moving '$DownloadDirectory/Xcode.app' to '$TargetPath'" + Move-Item -Path "$DownloadDirectory/Xcode.app" -Destination $TargetPath +} + +function Confirm-XcodeIntegrity { + param( + [Parameter(Mandatory)] + [string]$Version + ) + + $XcodeRootPath = Get-XcodeRootPath -Version $Version + if (Test-XcodeStableRelease -XcodeRootPath $XcodeRootPath) { + Write-Host "Validating Xcode integrity for '$XcodeRootPath'..." + Invoke-ValidateCommand "spctl --assess --raw $XcodeRootPath" + } +} + +function Approve-XcodeLicense { + param( + [Parameter(Mandatory)] + [string]$Version + ) + + $XcodeRootPath = Get-XcodeRootPath -Version $Version + Write-Host "Approving Xcode license for '$XcodeRootPath'..." + $xcodeBuildPath = Get-XcodeToolPath -XcodeRootPath $XcodeRootPath -ToolName "xcodebuild" + Invoke-ValidateCommand "sudo $xcodeBuildPath -license accept" +} + +function Install-XcodeAdditionalPackages { + param( + [Parameter(Mandatory)] + [string]$Version + ) + + Write-Host "Installing additional packages for Xcode $Version..." + $xcodeRootPath = Get-XcodeRootPath -Version $Version + $packages = Get-ChildItem -Path "$xcodeRootPath/Contents/Resources/Packages" -Filter "*.pkg" -File + $packages | ForEach-Object { + Invoke-ValidateCommand "sudo installer -pkg $($_.FullName) -target / -allowUntrusted" + } +} + +function Invoke-XcodeRunFirstLaunch { + param( + [Parameter(Mandatory)] + [string]$Version + ) + + if ($Version.StartsWith("8") -or $Version.StartsWith("9")) { + return + } + + Write-Host "Running 'runFirstLaunch' for Xcode $Version..." + $xcodeRootPath = Get-XcodeToolPath -Version $Version -ToolName "xcodebuild" + Invoke-ValidateCommand "sudo $xcodeRootPath -runFirstLaunch" +} + +function Build-XcodeSymlinks { + param( + [Parameter(Mandatory)] + [string]$Version, + [string[]]$Symlinks + ) + + $sourcePath = Get-XcodeRootPath -Version $Version + $Symlinks | Where-Object { $_ } | ForEach-Object { + $targetPath = Get-XcodeRootPath -Version $_ + Write-Host "Creating symlink: '$targetPath' -> '$sourcePath'" + New-Item -Path $targetPath -ItemType SymbolicLink -Value $sourcePath | Out-Null + } +} + +function Build-ProvisionatorSymlink { + param( + [Parameter(Mandatory)] + [string]$Version + ) + + $sourcePath = Get-XcodeRootPath -Version $Version + $versionInfo = Get-XcodeVersionInfo -XcodeRootPath $sourcePath + + $targetVersion = [SemVer]::Parse($versionInfo.Version).ToString() + $targetPath = Get-XcodeRootPath -Version $targetVersion + if ($sourcePath -ne $targetPath) { + Write-Host "Creating symlink: '$targetPath' -> '$sourcePath'" + New-Item -Path $targetPath -ItemType SymbolicLink -Value $sourcePath | Out-Null + } +} + +function Set-XcodeDeveloperDirEnvironmentVariables { + param( + [Parameter(Mandatory)] + [string[]]$XcodeList + ) + + $exactVersionsList = $XcodeList | Where-Object { Test-XcodeStableRelease -Version $_ } | ForEach-Object { + $xcodeRootPath = Get-XcodeRootPath -Version $_ + $xcodeVersionInfo = Get-XcodeVersionInfo -XcodeRootPath $xcodeRootPath + return @{ + RootPath = $xcodeRootPath + Version = [SemVer]::Parse($xcodeVersionInfo.Version) + } + } | Sort-Object -Property Version -Descending + + $majorVersions = $exactVersionsList.Version.Major | Select-Object -Unique + $majorVersions | ForEach-Object { + $majorVersion = $_ + $latestXcodeVersion = $exactVersionsList | Where-Object { $_.Version.Major -eq $majorVersion } | Select-Object -First 1 + $variableName = "XCODE_${_}_DEVELOPER_DIR" + $variableValue = "$($latestXcodeVersion.RootPath)/Contents/Developer" + Write-Host "Set ${variableName}=${variableValue}" + "export ${variableName}=${variableValue}" | Out-File "$env:HOME/.bashrc" -Append + } +} \ No newline at end of file diff --git a/images/macos/provision/configuration/configure-machine.sh b/images/macos/provision/configuration/configure-machine.sh index df991c21..9b8915af 100644 --- a/images/macos/provision/configuration/configure-machine.sh +++ b/images/macos/provision/configuration/configure-machine.sh @@ -1,10 +1,14 @@ #!/bin/bash -e -o pipefail +echo "Enabling safari driver..." # https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari # Safari’s executable is located at /usr/bin/safaridriver # Configure Safari to Enable WebDriver Support sudo safaridriver --enable +echo "Enabling developer mode..." +sudo /usr/sbin/DevToolsSecurity --enable + # Turn off hibernation and get rid of the sleepimage sudo pmset hibernatemode 0 sudo rm -f /var/vm/sleepimage diff --git a/images/macos/provision/core/xamarin.sh b/images/macos/provision/core/xamarin.sh index 18eef321..387e3f45 100755 --- a/images/macos/provision/core/xamarin.sh +++ b/images/macos/provision/core/xamarin.sh @@ -9,7 +9,7 @@ XAMARIN_MAC_VERSIONS=($(get_toolset_value '.xamarin."mac-versions" | reverse | . XAMARIN_ANDROID_VERSIONS=($(get_toolset_value '.xamarin."android-versions" | reverse | .[]')) LATEST_SDK_SYMLINK=$(get_toolset_value '.xamarin.bundles[0].symlink') CURRENT_SDK_SYMLINK=$(get_toolset_value '.xamarin."bundle-default"') -DEFAULT_XCODE_VERSION=$(get_default_xcode_from_toolset) +DEFAULT_XCODE_VERSION=$(get_toolset_value '.xcode.default') if [ "$CURRENT_SDK_SYMLINK" == "latest" ]; then CURRENT_SDK_SYMLINK=$LATEST_SDK_SYMLINK diff --git a/images/macos/provision/core/xcode-postbuild.sh b/images/macos/provision/core/xcode-postbuild.sh index 6afd42c2..1a82545b 100644 --- a/images/macos/provision/core/xcode-postbuild.sh +++ b/images/macos/provision/core/xcode-postbuild.sh @@ -1,8 +1,8 @@ #!/bin/bash -e -o pipefail source ~/utils/utils.sh -XCODE_LIST=($(get_xcode_list_from_toolset)) -DEFAULT_XCODE_VERSION=$(get_default_xcode_from_toolset) +XCODE_LIST=($(get_toolset_value '.xcode.versions | reverse | .[].link')) +DEFAULT_XCODE_VERSION=$(get_toolset_value '.xcode.default') # https://github.com/microsoft/appcenter/issues/847 # Assets.xcassets : error : CoreData: error: (6922) I/O error for database @@ -15,11 +15,6 @@ do #add sleep to let CoreSimulatorService to exit sleep 3 - # Version 12.2_beta installed into 12.2 directory and 12.1_GM_seed in 12.1 - pattern="[0-9]{1,2}.*_" - if [[ $XCODE_VERSION =~ $pattern ]] ; then - XCODE_VERSION=$(echo $XCODE_VERSION | cut -d"_" -f 1) - fi # Select xcode version by default sudo xcode-select -s "/Applications/Xcode_${XCODE_VERSION}.app/Contents/Developer" diff --git a/images/macos/provision/core/xcode-tools.sh b/images/macos/provision/core/xcode-tools.sh deleted file mode 100755 index 5c491708..00000000 --- a/images/macos/provision/core/xcode-tools.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/bash -e -o pipefail - -# The script currently requires 2 external variables to be set: XCODE_INSTALL_USER -# and XCODE_INSTALL_PASSWORD, in order to access the Apple Developer Center - -source ~/utils/utils.sh -source ~/utils/xcode-utils.sh - -if [ -z $XCODE_INSTALL_USER ] || [ -z $XCODE_INSTALL_PASSWORD ]; then - echo "Required environment variables XCODE_INSTALL_USER and XCODE_INSTALL_PASSWORD are not set" - exit 1 -fi - -XCODE_LIST=($(get_xcode_list_from_toolset)) -LATEST_XCODE_VERSION=$(get_latest_xcode_from_toolset) -DEFAULT_XCODE_VERSION=$(get_default_xcode_from_toolset) -WORK_DIR="${HOME}/Library/Caches/XcodeInstall" - -# Update the list of available versions -xcversion update - -for XCODE_VERSION in "${XCODE_LIST[@]}" -do - VERSION_TO_INSTALL="$(getXcodeVersionToInstall "$XCODE_VERSION")" - if [[ -z "$VERSION_TO_INSTALL" ]]; then - echo "No versions were found matching $XCODE_VERSION" - exit 1 - fi - - echo "Downloading Xcode $VERSION_TO_INSTALL ..." - xcversion install "$VERSION_TO_INSTALL" --no-install - - echo "Extracting Xcode.app ($VERSION_TO_INSTALL) to ${WORK_DIR} ..." - extractXcodeXip $WORK_DIR "$VERSION_TO_INSTALL" - - XCODE_VERSION=$(echo $XCODE_VERSION | cut -d"_" -f 1) - - echo "Checking if unpacked Xcode ${XCODE_VERSION} is valid" - validateXcodeIntegrity "$WORK_DIR" - - # Move Xcode to /Applications - mv -f "${WORK_DIR}/Xcode.app" "/Applications/Xcode_${XCODE_VERSION}.app" - - echo "Accepting license for Xcode ${XCODE_VERSION}..." - approveLicense $XCODE_VERSION - - # Creating a symlink for all Xcode 10* and Xcode 9.3, 9.4 to stay backwards compatible with consumers of the Xcode beta version - createBetaSymlink $XCODE_VERSION - - createXamarinProvisionatorSymlink "$XCODE_VERSION" - - find $WORK_DIR -mindepth 1 -delete -done - -echo "Configuring 'runFirstLaunch' for all Xcode versions" -if is_Less_Catalina; then - echo "Install additional packages for Xcode ${LATEST_XCODE_VERSION}" - installAdditionalPackages $LATEST_XCODE_VERSION -fi - -for XCODE_VERSION in "${XCODE_LIST[@]}" -do - if [[ $XCODE_VERSION == 8* || $XCODE_VERSION == 9* ]]; then - continue - fi - - XCODE_VERSION=$(echo $XCODE_VERSION | cut -d"_" -f 1) - - echo "Running 'runFirstLaunch' for Xcode ${XCODE_VERSION}..." - runFirstLaunch $XCODE_VERSION -done - -echo "Running 'runFirstLaunch' for default Xcode ${DEFAULT_XCODE_VERSION}..." -runFirstLaunch $DEFAULT_XCODE_VERSION - -# Create symlinks for Xcode on Catalina: 11.3 -> 11.3.1, 11.2 -> 11.2.1 -if is_Catalina; then - ln -sf /Applications/Xcode_11.2.1.app /Applications/Xcode_11.2.app - ln -sf /Applications/Xcode_11.3.1.app /Applications/Xcode_11.3.app - ln -sf /Applications/Xcode_11.4.1.app /Applications/Xcode_11.4.app -fi - -echo "Setting Xcode ${DEFAULT_XCODE_VERSION} as default" -sudo xcode-select -s "/Applications/Xcode_${DEFAULT_XCODE_VERSION}.app/Contents/Developer" - -echo "Adding symlink '/Applications/Xcode_${DEFAULT_XCODE_VERSION}.app' -> '/Applications/Xcode.app'" -ln -s "/Applications/Xcode_${DEFAULT_XCODE_VERSION}.app" "/Applications/Xcode.app" - -echo "Enabling developer mode" -sudo /usr/sbin/DevToolsSecurity --enable - -echo "Setting environment variables 'XCODE__DEVELOPER_DIR'" -setXcodeDeveloperDirVariables - -# Cleanup -echo "Doing cleanup. Emptying ${WORK_DIR}..." -rm -rf "$WORK_DIR" diff --git a/images/macos/provision/core/xcode.ps1 b/images/macos/provision/core/xcode.ps1 new file mode 100644 index 00000000..46f11518 --- /dev/null +++ b/images/macos/provision/core/xcode.ps1 @@ -0,0 +1,44 @@ +# The script currently requires 2 external variables to be set: XCODE_INSTALL_USER +# and XCODE_INSTALL_PASSWORD, in order to access the Apple Developer Center + +$ErrorActionPreference = "Stop" + +Import-Module "$env:HOME/image-generation/helpers/Common.Helpers.psm1" +Import-Module "$env:HOME/image-generation/helpers/Xcode.Installer.psm1" + +if ([string]::IsNullOrEmpty($env:XCODE_INSTALL_USER) -or [string]::IsNullOrEmpty($env:XCODE_INSTALL_PASSWORD)) { + throw "Required environment variables XCODE_INSTALL_USER and XCODE_INSTALL_PASSWORD are not set" +} + +$os = Get-OSVersion +$xcodeVersions = Get-ToolsetValue "xcode.versions" +$defaultXcode = Get-ToolsetValue "xcode.default" +[Array]::Reverse($xcodeVersions) + +Write-Host "Installing Xcode versions..." +$xcodeVersions | ForEach-Object { + Install-XcodeVersion -Version $_.version -LinkTo $_.link + Confirm-XcodeIntegrity -Version $_.link + Approve-XcodeLicense -Version $_.link +} + +Write-Host "Configuring Xcode versions..." +if ($os.IsLessThanCatalina) { + $latestXcodeVersion = $xcodeVersions | Select-Object -Last 1 -ExpandProperty link + Install-XcodeAdditionalPackages -Version $latestXcodeVersion +} +$xcodeVersions | ForEach-Object { Invoke-XcodeRunFirstLaunch -Version $_.link } +Invoke-XcodeRunFirstLaunch -Version $defaultXcode + +Write-Host "Configuring Xcode symlinks..." +$xcodeVersions | ForEach-Object { + Build-XcodeSymlinks -Version $_.link -Symlinks $_.symlinks + Build-ProvisionatorSymlink -Version $_.link +} + +Write-Host "Setting default Xcode to $defaultXcode" +Switch-Xcode -Version $defaultXcode +New-Item -Path "/Applications/Xcode.app" -ItemType SymbolicLink -Value (Get-XcodeRootPath -Version $defaultXcode) | Out-Null + +Write-Host "Setting environment variables 'XCODE__DEVELOPER_DIR'" +Set-XcodeDeveloperDirEnvironmentVariables -XcodeList $xcodeVersions.link \ No newline at end of file diff --git a/images/macos/provision/utils/utils.sh b/images/macos/provision/utils/utils.sh index c43f4efe..fab443e7 100755 --- a/images/macos/provision/utils/utils.sh +++ b/images/macos/provision/utils/utils.sh @@ -92,18 +92,6 @@ get_toolset_value() { echo "$(jq -r "$query" $toolset_path)" } -get_xcode_list_from_toolset() { - echo $(get_toolset_value '.xcode.versions | reverse | .[]') -} - -get_latest_xcode_from_toolset() { - echo $(get_toolset_value '.xcode.versions[0]') -} - -get_default_xcode_from_toolset() { - echo $(get_toolset_value '.xcode.default') -} - verlte() { sortedVersion=$(echo -e "$1\n$2" | sort -V | head -n1) [ "$1" = "$sortedVersion" ] diff --git a/images/macos/provision/utils/xcode-utils.sh b/images/macos/provision/utils/xcode-utils.sh deleted file mode 100644 index a5874c6f..00000000 --- a/images/macos/provision/utils/xcode-utils.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash -e -o pipefail - -createXamarinProvisionatorSymlink() { - local XCODE_VERSION="$1" - local FULL_VERSION=$(echo "${XCODE_VERSION}.0.0" | cut -d'.' -f 1,2,3) - - # temporary trick for 12.0.1 - if [[ $XCODE_VERSION == "12" ]]; then - FULL_VERSION="12.0.1" - fi - - if [ $FULL_VERSION != $XCODE_VERSION ]; then - ln -sf "/Applications/Xcode_${XCODE_VERSION}.app" "/Applications/Xcode_${FULL_VERSION}.app" - fi -} - -getXcodeVersionToInstall() { - local XCODE_VERSION="$1" - - if [[ $XCODE_VERSION == "12" ]]; then - echo "12.0.1" - elif [[ ! $XCODE_VERSION =~ "_beta" ]]; then - echo "${XCODE_VERSION//_/ }" - else - local XCODE_BETA="${XCODE_VERSION/_/ }" - echo "$(xcversion list | sort -r | grep -m 1 "$XCODE_BETA")" - fi -} - -validateXcodeIntegrity() { - local WORKING_DIR="$1" - local XCODE_VERSION="$2" - - if echo $XCODE_VERSION | grep "beta"; then - return 0 - fi - - spctl --assess --raw "${WORKING_DIR}/Xcode.app" -} - -approveLicense() { - local XCODE_VERSION="$1" - sudo "/Applications/Xcode_${XCODE_VERSION}.app/Contents/Developer/usr/bin/xcodebuild" -license accept -} - -installAdditionalPackages() { - # should be called only for old High Sierra and Mojave - local XCODE_VERSION="$1" - find /Applications/Xcode_${XCODE_VERSION}.app/Contents/Resources/Packages/ -name '*.pkg' | xargs -I '{}' sudo installer -pkg '{}' -target / -allowUntrusted -} - -runFirstLaunch() { - local XCODE_VERSION="$1" - sudo "/Applications/Xcode_${XCODE_VERSION}.app/Contents/Developer/usr/bin/xcodebuild" -runFirstLaunch -} - -setXcodeDeveloperDirVariables() { - stable_xcode_versions=$(get_xcode_list_from_toolset | tr " " "\n" | grep -v "beta" | grep -v "Release_Candidate") - major_versions=($(echo ${stable_xcode_versions[@]} | tr " " "\n" | cut -d '.' -f 1 | uniq)) - for MAJOR_VERSION in "${major_versions[@]}" - do - LATEST_STABLE_VERSION=$(echo "${stable_xcode_versions[*]}" | grep "${MAJOR_VERSION}" | tail -n 1) - LATEST_STABLE_VERSION=$(echo $LATEST_STABLE_VERSION | cut -d"_" -f 1) - echo "export XCODE_${MAJOR_VERSION}_DEVELOPER_DIR=/Applications/Xcode_${LATEST_STABLE_VERSION}.app/Contents/Developer" >> "$HOME/.bashrc" - done -} - -extractXcodeXip() { - local WORKING_DIR="$1" - local XCODE_VERSION="$2" - XCODE_XIP="${WORKING_DIR}/Xcode_${XCODE_VERSION// /_}.xip" - - pushd $WORKING_DIR - xip -x "${XCODE_XIP}" - popd - - if [[ -d "${WORKING_DIR}/Xcode-beta.app" ]]; then - mv -f "${WORKING_DIR}/Xcode-beta.app" "${WORKING_DIR}/Xcode.app" - fi - - if [[ ! -d "${WORKING_DIR}/Xcode.app" ]]; then - echo "'Xcode.app' doesn't exist after Xcode XIP extraction" - exit 1 - fi -} - -createBetaSymlink() { - local XCODE_VERSION=$1 - if [[ $XCODE_VERSION =~ 1[01].* ]] || [[ $XCODE_VERSION == "12" ]]; then - ln -sf "/Applications/Xcode_${XCODE_VERSION}.app" "/Applications/Xcode_${XCODE_VERSION}_beta.app" - fi -} \ No newline at end of file diff --git a/images/macos/software-report/SoftwareReport.Xcode.psm1 b/images/macos/software-report/SoftwareReport.Xcode.psm1 index 3d4cfa52..31967d30 100644 --- a/images/macos/software-report/SoftwareReport.Xcode.psm1 +++ b/images/macos/software-report/SoftwareReport.Xcode.psm1 @@ -1,4 +1,5 @@ Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" +Import-Module "$PSScriptRoot/../helpers/Xcode.Helpers.psm1" $os = Get-OSVersion @@ -7,19 +8,16 @@ function Get-XcodePaths { return $xcodePaths | Select-Object -ExpandProperty Fullname } -function Get-XcodeVersionInfo { - [string]$output = Invoke-Expression "xcodebuild -version" - $versionOutputParts = $output.Split(" ") - return @{ - Version = [System.Version]::Parse($versionOutputParts[1]) - Build = $versionOutputParts[4] - } -} - function Get-XcodeSDKList { - $versionInfo = Get-XcodeVersionInfo + param( + [Parameter(Mandatory)] + [string]$XcodeRootPath + ) + + $versionInfo = Get-XcodeVersionInfo -XcodeRootPath $XcodeRootPath + $xcodebuildPath = Get-XcodeToolPath -XcodeRootPath $XcodeRootPath -ToolName "xcodebuild" if ($versionInfo.Version -le [System.Version]::Parse("9.4.1")) { - $output = Invoke-Expression "xcodebuild -showsdks" + $output = Invoke-Expression "$xcodebuildPath -showsdks" $sdkList = $output | Where-Object { $_ -Match "-sdk" } return $sdkList | ForEach-Object { @@ -31,7 +29,7 @@ function Get-XcodeSDKList { } } - [string]$output = Invoke-Expression "xcodebuild -showsdks -json" + [string]$output = Invoke-Expression "$xcodebuildPath -showsdks -json" return $output | ConvertFrom-Json } @@ -43,14 +41,14 @@ function Get-XcodeInfoList { $xcodeRootPath = $_ Switch-Xcode -XcodeRootPath $xcodeRootPath - $versionInfo = Get-XcodeVersionInfo + $versionInfo = Get-XcodeVersionInfo -XcodeRootPath $xcodeRootPath $versionInfo.Path = $xcodeRootPath $versionInfo.IsDefault = ($xcodeRootPath -eq $defaultXcodeRootPath) $versionInfo.IsStable = Test-XcodeStableRelease -XcodeRootPath $xcodeRootPath $xcodeInfo.Add($xcodeRootPath, [PSCustomObject] @{ VersionInfo = $versionInfo - SDKInfo = Get-XcodeSDKList + SDKInfo = Get-XcodeSDKList -XcodeRootPath $xcodeRootPath SimulatorsInfo = Get-XcodeSimulatorsInfo }) } @@ -101,7 +99,7 @@ function Build-XcodeTable { } } -function Get-XcodeDevicesList { +function Build-XcodeDevicesList { param ( [Parameter(Mandatory)][object] $XcodeInfo, [Parameter(Mandatory)][object] $Runtime @@ -190,7 +188,7 @@ function Build-XcodeSimulatorsTable { $xcodeInfo.Values | ForEach-Object { $runtimeFound = $_.SimulatorsInfo.runtimes | Where-Object { $_.identifier -eq $runtime.identifier } | Select-Object -First 1 if ($runtimeFound) { - $devicesToAdd = Get-XcodeDevicesList -XcodeInfo $_ -Runtime $runtimeFound + $devicesToAdd = Build-XcodeDevicesList -XcodeInfo $_ -Runtime $runtimeFound $runtimeDevices += $devicesToAdd | Select-Object -ExpandProperty name $xcodeList += $_.VersionInfo.Version } diff --git a/images/macos/templates/macOS-10.13.json b/images/macos/templates/macOS-10.13.json index 58b5427d..24ae7c3f 100644 --- a/images/macos/templates/macOS-10.13.json +++ b/images/macos/templates/macOS-10.13.json @@ -147,12 +147,8 @@ }, { "type": "shell", - "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} {{ .Path }}", - "scripts": [ - "./provision/core/xcode-tools.sh", - "./provision/core/xcode-sims.sh", - "./provision/core/build-xcode-symlinks.sh" - ], + "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} pwsh -f {{ .Path }}", + "script": "./provision/core/xcode.ps1", "environment_vars": [ "XCODE_INSTALL_USER={{user `xcode_install_user`}}", "XCODE_INSTALL_PASSWORD={{user `xcode_install_password`}}" @@ -186,7 +182,9 @@ "./provision/core/firefox.sh", "./provision/core/toolcache-high-sierra.sh", "./provision/core/pypy.sh", - "./provision/core/pipx-packages.sh" + "./provision/core/pipx-packages.sh", + "./provision/core/xcode-sims.sh", + "./provision/core/build-xcode-symlinks.sh" ] }, { diff --git a/images/macos/templates/macOS-10.14.json b/images/macos/templates/macOS-10.14.json index e2822693..e99ff39d 100644 --- a/images/macos/templates/macOS-10.14.json +++ b/images/macos/templates/macOS-10.14.json @@ -147,11 +147,8 @@ }, { "type": "shell", - "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} {{ .Path }}", - "scripts": [ - "./provision/core/xcode-tools.sh", - "./provision/core/xcode-sims.sh" - ], + "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} pwsh -f {{ .Path }}", + "script": "./provision/core/xcode.ps1", "environment_vars": [ "XCODE_INSTALL_USER={{user `xcode_install_user`}}", "XCODE_INSTALL_PASSWORD={{user `xcode_install_password`}}" @@ -188,6 +185,7 @@ "./provision/core/edge.sh", "./provision/core/firefox.sh", "./provision/core/miniconda.sh", + "./provision/core/xcode-sims.sh", "./provision/core/xcode-postbuild.sh", "./provision/core/toolcache.sh", "./provision/core/pypy.sh", diff --git a/images/macos/templates/macOS-10.15.json b/images/macos/templates/macOS-10.15.json index 162af8bd..530175f0 100644 --- a/images/macos/templates/macOS-10.15.json +++ b/images/macos/templates/macOS-10.15.json @@ -148,8 +148,8 @@ }, { "type": "shell", - "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} {{ .Path }}", - "script": "./provision/core/xcode-tools.sh", + "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} pwsh -f {{ .Path }}", + "script": "./provision/core/xcode.ps1", "environment_vars": [ "XCODE_INSTALL_USER={{user `xcode_install_user`}}", "XCODE_INSTALL_PASSWORD={{user `xcode_install_password`}}" diff --git a/images/macos/templates/macOS-11.0.json b/images/macos/templates/macOS-11.0.json index 5586da94..debb3c34 100644 --- a/images/macos/templates/macOS-11.0.json +++ b/images/macos/templates/macOS-11.0.json @@ -148,8 +148,8 @@ }, { "type": "shell", - "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} {{ .Path }}", - "script": "./provision/core/xcode-tools.sh", + "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} pwsh -f {{ .Path }}", + "script": "./provision/core/xcode.ps1", "environment_vars": [ "XCODE_INSTALL_USER={{user `xcode_install_user`}}", "XCODE_INSTALL_PASSWORD={{user `xcode_install_password`}}" diff --git a/images/macos/tests/Xcode.Tests.ps1 b/images/macos/tests/Xcode.Tests.ps1 index b00ab298..244b66dc 100644 --- a/images/macos/tests/Xcode.Tests.ps1 +++ b/images/macos/tests/Xcode.Tests.ps1 @@ -2,49 +2,60 @@ Import-Module "$PSScriptRoot/../helpers/Common.Helpers.psm1" Import-Module "$PSScriptRoot/../helpers/Xcode.Helpers.psm1" Import-Module "$PSScriptRoot/../helpers/Tests.Helpers.psm1" -$XCODE_VERSIONS = Get-ToolsetValue "xcode.versions" -$DEFAULT_XCODE = Get-ToolsetValue "xcode.default" -$LATEST_XCODE_VERSION = $XCODE_VERSIONS | Select-Object -First 1 -$OS = Get-OSVersion +$xcodeVersions = Get-ToolsetValue "xcode.versions" +$defaultXcode = Get-ToolsetValue "xcode.default" +$latestXcodeVersion = $xcodeVersions | Select-Object -First 1 +$os = Get-OSVersion Describe "Xcode" { - It "Default Xcode is $DEFAULT_XCODE" { - "xcodebuild -version" | Should -ReturnZeroExitCode - (Get-CommandResult "xcodebuild -version").Output | Should -BeLike "Xcode $DEFAULT_XCODE*" - } + $testCases = $xcodeVersions | ForEach-Object { @{ XcodeVersion = $_.link; LatestXcodeVersion = $xcodeVersions[0].link; Symlinks = $_.symlinks } } - # Cut "_beta" postfix for test cases - $testCases = $XCODE_VERSIONS | ForEach-Object { @{XcodeVersion = $_.Split("_")[0] } } - - It "" -TestCases $testCases { - param ( [string] $XcodeVersion ) - - $xcodebuildPath = Get-XcodeToolPath -Version $XcodeVersion -ToolName "xcodebuild" - "$xcodebuildPath -version" | Should -ReturnZeroExitCode - } - - It "Xcode tools are installed" -TestCases $testCases -Skip:($os.IsHighSierra) { - param ( [string] $XcodeVersion ) - - $TOOLS_NOT_INSTALLED_EXIT_CODE = 69 - $xcodebuildPath = Get-XcodeToolPath -Version $XcodeVersion -ToolName "xcodebuild" - $result = Get-CommandResult "$xcodebuildPath -checkFirstLaunchStatus" - - if ($XcodeVersion -ne $LATEST_XCODE_VERSION) { - $result.ExitCode | Should -Not -Be $TOOLS_NOT_INSTALLED_EXIT_CODE - } else { - $result.ExitCode | Should -BeIn (0, $TOOLS_NOT_INSTALLED_EXIT_CODE) + Context "Versions" { + It "" -TestCases $testCases { + $xcodebuildPath = Get-XcodeToolPath -Version $XcodeVersion -ToolName "xcodebuild" + "$xcodebuildPath -version" | Should -ReturnZeroExitCode } } - It "Xcode has correct beta symlink" -TestCases $testCases { - param ( [string] $XcodeVersion ) + Context "Default" { + $defaultXcodeTestCase = @{ DefaultXcode = $defaultXcode } + It "Default Xcode is " -TestCases $defaultXcodeTestCase { + "xcodebuild -version" | Should -ReturnZeroExitCode + (Get-CommandResult "xcodebuild -version").Output | Should -BeLike "Xcode ${DefaultXcode}*" + } - $xcodesWithBetaSymlink = @("12", "9.3", "9.4") - $shouldBetaSymlinkExists = $XcodeVersion.StartsWith("10") -or $XcodeVersion.StartsWith("11") -or ($XcodeVersion -in $xcodesWithBetaSymlink) + It "Xcode.app points to default Xcode" -TestCases $defaultXcodeTestCase { + $xcodeApp = "/Applications/Xcode.app" + $expectedTarget = Get-XcodeRootPath -Version $DefaultXcode + $xcodeApp | Should -Exist + $expectedTarget | Should -Exist + (Get-Item $xcodeApp).Target | Should -Be $expectedTarget + } + } - $betaSymlinkPath = Get-XcodeRootPath -Version "${XcodeVersion}_beta" - Test-Path $betaSymlinkPath | Should -Be $shouldBetaSymlinkExists + Context "Additional tools" { + It "Xcode tools are installed" -TestCases $testCases -Skip:($os.IsHighSierra) { + $TOOLS_NOT_INSTALLED_EXIT_CODE = 69 + $xcodebuildPath = Get-XcodeToolPath -Version $XcodeVersion -ToolName "xcodebuild" + $result = Get-CommandResult "$xcodebuildPath -checkFirstLaunchStatus" + + if ($XcodeVersion -ne $LatestXcodeVersion) { + $result.ExitCode | Should -Not -Be $TOOLS_NOT_INSTALLED_EXIT_CODE + } else { + $result.ExitCode | Should -BeIn (0, $TOOLS_NOT_INSTALLED_EXIT_CODE) + } + } + } + + Context "Symlinks" { + It "Xcode has correct symlinks" -TestCases $testCases { + $sourcePath = Get-XcodeRootPath -Version $XcodeVersion + $Symlinks | Where-Object { $_ } | ForEach-Object { + $targetPath = Get-XcodeRootPath -Version $_ + $targetPath | Should -Exist + (Get-Item $targetPath).Target | Should -Be $sourcePath + } + } } It "/Applications/Xcode* symlinks are valid" { @@ -54,54 +65,50 @@ Describe "Xcode" { $_ | Should -Exist } } +} - Context "XCODE_DEVELOPER_DIR" { - $stableXcodeVersions = $XCODE_VERSIONS | Where-Object { $_ -notlike "*Release*Candidate*" } | ForEach-Object { $_.Split("_")[0] } | Where-Object { Test-XcodeStableRelease -Version $_ } - $majorXcodeVersions = $stableXcodeVersions | ForEach-Object { $_.Split(".")[0] } | Select-Object -Unique - $testCases = $majorXcodeVersions | ForEach-Object { - $majorXcodeVersion = $_ - $expectedVersion = $stableXcodeVersions | Where-Object { $_.StartsWith("$majorXcodeVersion") } | Select-Object -First 1 - return @{ - MajorXcodeVersion = $majorXcodeVersion - ExpectedVersion = $expectedVersion - } +Describe "XCODE_DEVELOPER_DIR variables" { + $exactVersionsList = $xcodeVersions.link | Where-Object { Test-XcodeStableRelease -Version $_ } | ForEach-Object { + $xcodeRootPath = Get-XcodeRootPath -Version $_ + $xcodeVersionInfo = Get-XcodeVersionInfo -XcodeRootPath $xcodeRootPath + return @{ + RootPath = $xcodeRootPath + Version = [SemVer]::Parse($xcodeVersionInfo.Version) } + } | Sort-Object -Property Version -Descending + $majorVersions = $exactVersionsList.Version.Major | Select-Object -Unique + $testCases = $majorVersions | ForEach-Object { @{ MajorVersion = $_; VersionsList = $exactVersionsList } } - It "XCODE__DEVELOPER_DIR" -TestCases $testCases { - param ( - [string] $MajorXcodeVersion, - [string] $ExpectedVersion - ) - - $variableName = "XCODE_${MajorXcodeVersion}_DEVELOPER_DIR" - $actualPath = Get-EnvironmentVariable $variableName - $expectedPath = Join-Path (Get-XcodeRootPath -Version $ExpectedVersion) "Contents/Developer" - - $actualPath | Should -Exist - $actualPath | Should -Be $expectedPath - } + It "XCODE__DEVELOPER_DIR" -TestCases $testCases { + $variableName = "XCODE_${MajorVersion}_DEVELOPER_DIR" + $actualPath = Get-EnvironmentVariable $variableName + $expectedVersion = $VersionsList | Where-Object { $_.Version.Major -eq $MajorVersion } | Select-Object -First 1 + $expectedPath = "$($expectedVersion.RootPath)/Contents/Developer" + $actualPath | Should -Exist + $actualPath | Should -Be $expectedPath } } Describe "Xcode simulators" { - $XCODE_VERSIONS | Where-Object { $_ -notlike "*Release*Candidate*" } | ForEach-Object { $_.Split("_")[0] } | Where-Object { Test-XcodeStableRelease -Version $_ } | ForEach-Object { - Switch-Xcode -Version $_ - + $xcodeVersions.link | Where-Object { Test-XcodeStableRelease -Version $_ } | ForEach-Object { Context "$_" { - It "No duplicates in devices" { + $testCase = @{ XcodeVersion = $_ } + It "No duplicates in devices" -TestCases $testCase { + Switch-Xcode -Version $XcodeVersion [array]$devicesList = @(Get-XcodeDevicesList | Where-Object { $_ }) Validate-ArrayWithoutDuplicates $devicesList -Because "Found duplicate device simulators" } - It "No duplicates in pairs" { + It "No duplicates in pairs" -TestCases $testCase { + Switch-Xcode -Version $XcodeVersion [array]$pairsList = @(Get-XcodePairsList | Where-Object { $_ }) Validate-ArrayWithoutDuplicates $pairsList -Because "Found duplicate pairs simulators" } } } - AfterAll { - $DEFAULT_XCODE = Get-ToolsetValue "xcode.default" - Switch-Xcode -Version $DEFAULT_XCODE + AfterEach { + $defaultXcode = Get-ToolsetValue "xcode.default" + Switch-Xcode -Version $defaultXcode } } \ No newline at end of file diff --git a/images/macos/toolsets/Readme.md b/images/macos/toolsets/Readme.md index 671ef482..14453889 100644 --- a/images/macos/toolsets/Readme.md +++ b/images/macos/toolsets/Readme.md @@ -1,10 +1,27 @@ # Toolset JSON structure ## Xcode -- `default` - version of Xcode to set as default - **Example:** `"11.2.1"` +- `versions` - the array of objects that will present installed Xcode versions + - `link` property points to the place where Xcode will be located on image. `/Applications/Xcode_.app` + - `version` points to Xcode version that will be downloaded and installed + - `symlinks` describes the list of aliases where symlinks will be created to +- `default` - version of Xcode to set as default (should be metched with any `link` in `versions` property) + **Example:** `"11.2"` -- `versions` - the array of versions of Xcode to install - **Example:** `[ "11.3", "11.2.1", "11.2", "11.1", "11" ]` +**Note:** +- If `version` is specified with spaces, it is considered as exact Xcode name like `12.1.1 Release Candidate`. +- If `version` doesn't contain spaces, the latest version will be resolved with the following priority: + - stable version like `12.1` + - release candidate version like `12.1 Release Candidate N` (the latest N will be chosen) + - GM version like `12.1 GM Seed N` (the latest N will be chosen) + - beta version like `12.1 beta N` (the latest N will be chosen) + +**Example:** +``` +"versions": [ + { "link": "12.2", "version": "12.2.0" }, + { "link": "11.7", "version": "11.7.0", "symlinks": ["11.7_beta"] } +] +``` ## Xamarin - `vsmac` - version of Visual Studio For Mac to install. diff --git a/images/macos/toolsets/toolset-10.13.json b/images/macos/toolsets/toolset-10.13.json index c96c723e..8e2bcc9d 100644 --- a/images/macos/toolsets/toolset-10.13.json +++ b/images/macos/toolsets/toolset-10.13.json @@ -2,7 +2,19 @@ "xcode": { "default": "10.1", "versions": [ - "10.1", "10", "9.4.1", "9.4", "9.3.1", "9.3", "9.2", "9.1", "9", "8.3.3", "8.2.1", "8.1", "8" + { "link": "10.1", "version": "10.1.0", "symlinks": ["10.1_beta"] }, + { "link": "10", "version": "10.0.0", "symlinks": ["10_beta"] }, + { "link": "9.4.1", "version": "9.4.1" }, + { "link": "9.4", "version": "9.4.0", "symlinks": ["9.4_beta"] }, + { "link": "9.3.1", "version": "9.3.1" }, + { "link": "9.3", "version": "9.3.0", "symlinks": ["9.3_beta"] }, + { "link": "9.2", "version": "9.2.0" }, + { "link": "9.1", "version": "9.1.0" }, + { "link": "9", "version": "9.0.0" }, + { "link": "8.3.3", "version": "8.3.3" }, + { "link": "8.2.1", "version": "8.2.1" }, + { "link": "8.1", "version": "8.1.0" }, + { "link": "8", "version": "8.0.0" } ] }, "xamarin": { diff --git a/images/macos/toolsets/toolset-10.14.json b/images/macos/toolsets/toolset-10.14.json index f66c2f38..9b1d3d30 100644 --- a/images/macos/toolsets/toolset-10.14.json +++ b/images/macos/toolsets/toolset-10.14.json @@ -2,7 +2,18 @@ "xcode": { "default": "11.3.1", "versions": [ - "11.3.1", "11.3", "11.2.1", "11.2", "11.1", "11", "10.3", "10.2.1", "10.2", "10.1", "10", "9.4.1" + { "link": "11.3.1", "version": "11.3.1", "symlinks": ["11.3.1_beta"] }, + { "link": "11.3", "version": "11.3.0", "symlinks": ["11.3_beta"] }, + { "link": "11.2.1", "version": "11.2.1", "symlinks": ["11.2.1_beta"] }, + { "link": "11.2", "version": "11.2.0", "symlinks": ["11.2_beta"] }, + { "link": "11.1", "version": "11.1.0", "symlinks": ["11.1_beta"] }, + { "link": "11", "version": "11.0.0", "symlinks": ["11_beta"] }, + { "link": "10.3", "version": "10.3.0", "symlinks": ["10.3_beta"] }, + { "link": "10.2.1", "version": "10.2.1", "symlinks": ["10.2.1_beta"] }, + { "link": "10.2", "version": "10.2.0", "symlinks": ["10.2_beta"] }, + { "link": "10.1", "version": "10.1.0", "symlinks": ["10.1_beta"] }, + { "link": "10", "version": "10.0.0", "symlinks": ["10_beta"] }, + { "link": "9.4.1", "version": "9.4.1" } ] }, "xamarin": { diff --git a/images/macos/toolsets/toolset-10.15.json b/images/macos/toolsets/toolset-10.15.json index e8a30acb..6a6e9b18 100644 --- a/images/macos/toolsets/toolset-10.15.json +++ b/images/macos/toolsets/toolset-10.15.json @@ -2,7 +2,18 @@ "xcode": { "default": "12", "versions": [ - "12.3_beta", "12.2", "12.1.1_Release_Candidate", "12.1", "12", "11.7", "11.6", "11.5", "11.4.1", "11.3.1", "11.2.1", "10.3" + { "link": "12.3", "version": "12.3.0"}, + { "link": "12.2", "version": "12.2.0" }, + { "link": "12.1.1", "version": "12.1.1" }, + { "link": "12.1", "version": "12.1.0" }, + { "link": "12", "version": "12.0.1", "symlinks": ["12_beta"] }, + { "link": "11.7", "version": "11.7.0", "symlinks": ["11.7_beta"] }, + { "link": "11.6", "version": "11.6.0", "symlinks": ["11.6_beta"] }, + { "link": "11.5", "version": "11.5.0", "symlinks": ["11.5_beta"] }, + { "link": "11.4.1", "version": "11.4.1", "symlinks": ["11.4", "11.4.1_beta"] }, + { "link": "11.3.1", "version": "11.3.1", "symlinks": ["11.3", "11.3.1_beta"] }, + { "link": "11.2.1", "version": "11.2.1", "symlinks": ["11.2", "11.2.1_beta"] }, + { "link": "10.3", "version": "10.3", "symlinks": ["10.3_beta"] } ] }, "xamarin": { diff --git a/images/macos/toolsets/toolset-11.0.json b/images/macos/toolsets/toolset-11.0.json index 3fbbbde2..1cdc2f46 100644 --- a/images/macos/toolsets/toolset-11.0.json +++ b/images/macos/toolsets/toolset-11.0.json @@ -2,7 +2,9 @@ "xcode": { "default": "11.7", "versions": [ - "12.3_beta", "12.2", "11.7" + { "link": "12.3", "version": "12.3.0"}, + { "link": "12.2", "version": "12.2.0" }, + { "link": "11.7", "version": "11.7.0", "symlinks": ["11.7_beta"] } ] }, "xamarin": {