Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def self.run(params)
required_devices = params[:devices]
UI.user_error!('No devices specified') if required_devices.nil? || required_devices.empty?

shell_helper = CreateSimulatorDevices::ShellHelper.new(print_command: params[:print_command], print_command_output: params[:print_command_output], action_context: self)
shell_helper = CreateSimulatorDevices::ShellHelper.new(verbose: verbose, print_command: params[:print_command], print_command_output: params[:print_command_output], action_context: self)
runtime_helper = CreateSimulatorDevices::RuntimeHelper.new(cache_dir: params[:cache_dir], shell_helper: shell_helper, verbose: verbose)

runner = CreateSimulatorDevices::Runner.new(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def self.run(params)
required_devices = params[:devices]
UI.user_error!('No devices specified') if required_devices.nil? || required_devices.empty?

shell_helper = CreateSimulatorDevices::ShellHelper.new(print_command: params[:print_command], print_command_output: params[:print_command_output], action_context: self)
shell_helper = CreateSimulatorDevices::ShellHelper.new(verbose: verbose, print_command: params[:print_command], print_command_output: params[:print_command_output], action_context: self)
runtime_helper = CreateSimulatorDevices::RuntimeHelper.new(cache_dir: nil, shell_helper: shell_helper, verbose: verbose)

create_simulator_devices_runner = ::Fastlane::CreateSimulatorDevices::Runner.new(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ def almost_equal?(other)
end

def major
@build_version.match(/^([0-9]+)([A-Z][0-9]{2,3})([0-9]+)/)[1]
@build_version.match(/^([0-9]+)([A-Z][0-9]{1,3})([0-9]+)/)[1]
end

def minor
@build_version.match(/^([0-9]+)([A-Z][0-9]{2,3})([0-9]+)/)[2]
@build_version.match(/^([0-9]+)([A-Z][0-9]{1,3})([0-9]+)/)[2]
end

def patch
@build_version.match(/^([0-9]+)([A-Z][0-9]{2,3})([0-9]+)/)[3]
@build_version.match(/^([0-9]+)([A-Z][0-9]{1,3})([0-9]+)/)[3]
end

def <(other)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ class ShellHelper
UI = ::Fastlane::UI unless defined?(UI)

# Proprty verbose
attr_accessor :print_command, :print_command_output, :action_context
attr_accessor :verbose, :print_command, :print_command_output, :action_context

def initialize(print_command: false, print_command_output: false, action_context: nil)
def initialize(verbose: false, print_command: false, print_command_output: false, action_context: nil)
self.verbose = verbose
self.print_command = print_command
self.print_command_output = print_command_output
self.action_context = action_context
Expand Down Expand Up @@ -141,8 +142,6 @@ def delete_runtime(runtime_identifier)
end

def download_runtime(missing_runtime, cache_dir)
UI.message("Downloading #{missing_runtime.runtime_name} to #{cache_dir}. This may take a while...")

command = [
'xcrun',
'xcodebuild',
Expand All @@ -162,6 +161,30 @@ def download_runtime(missing_runtime, cache_dir)
command << missing_runtime.product_version.to_s.shellescape
end

simulator_architecture_variant = 'universal'

if Fastlane::Helper.xcode_at_least?('26') && missing_runtime.product_version >= '26'
xcode_binary_path = File.join(Fastlane::Helper.xcode_path, '..', 'MacOS', 'Xcode')
xcode_binary_path = File.expand_path(xcode_binary_path)

UI.message('Getting Xcode architecture variants with lipo...') if verbose

xcode_architecture_variants = sh(command: "lipo -archs #{xcode_binary_path.shellescape}", print_command: print_command, print_command_output: print_command_output).split

UI.message("Xcode architecture variants: #{xcode_architecture_variants}") if verbose

simulator_architecture_variant = if xcode_architecture_variants.include?('x86_64')
'universal'
else
'arm64'
end

command << '-architectureVariant'
command << simulator_architecture_variant.shellescape
end

UI.message("Downloading #{missing_runtime.runtime_name} (arch: #{simulator_architecture_variant}) to #{cache_dir}. This may take a while...")

sh(command: command.join(' '), print_command: true, print_command_output: true)
end

Expand Down
62 changes: 61 additions & 1 deletion spec/create_simulator_devices/shell_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,14 @@
end

describe '#download_runtime' do
it 'downloads runtime platform using xcodebuild' do
it 'downloads runtime platform using xcodebuild (< 26)' do
# GIVEN: Runtime platform and version details
missing_platform = 'iOS'
missing_version = '17.4'
cache_dir = '/tmp/test_cache'

allow(Fastlane::Helper).to receive(:xcode_at_least?).with('26').and_return(false)

missing_runtime = RequiredRuntime.new(sdk_platform: nil, os_name: missing_platform, product_version: missing_version, product_build_version: AppleBuildVersion.new('21E210'), is_latest: false)
expect(sut).to receive(:sh).with(
command: "xcrun xcodebuild -verbose -exportPath #{cache_dir.shellescape} -downloadPlatform #{missing_platform.shellescape} -buildVersion #{missing_version.shellescape}",
Expand All @@ -226,6 +228,64 @@

# THEN: Should execute the xcodebuild download command (expectation verified above)
end

it 'downloads runtime platform using xcodebuild (>= 26, universal)' do
# GIVEN: Runtime platform and version details
missing_platform = 'iOS'
missing_version = '26.1'
cache_dir = '/tmp/test_cache'

allow(Fastlane::Helper).to receive(:xcode_at_least?).with('26').and_return(true)
allow(Fastlane::Helper).to receive(:xcode_version).and_return('26.1')
allow(Fastlane::Helper).to receive(:xcode_path).and_return('/Applications/Xcode.app/Contents/Developer')

allow(sut).to receive(:sh).with(
command: 'lipo -archs /Applications/Xcode.app/Contents/MacOS/Xcode',
print_command: false,
print_command_output: false
).and_return('x86_64 arm64')

missing_runtime = RequiredRuntime.new(sdk_platform: nil, os_name: missing_platform, product_version: missing_version, product_build_version: AppleBuildVersion.new('23B77'), is_latest: false)
expect(sut).to receive(:sh).with(
command: "xcrun xcodebuild -verbose -exportPath #{cache_dir.shellescape} -downloadPlatform #{missing_platform.shellescape} -buildVersion #{missing_version.shellescape} -architectureVariant universal",
print_command: true,
print_command_output: true
)

# WHEN: Downloading runtime
sut.download_runtime(missing_runtime, cache_dir)

# THEN: Should execute the xcodebuild download command (expectation verified above)
end

it 'downloads runtime platform using xcodebuild (>= 26, arm64)' do
# GIVEN: Runtime platform and version details
missing_platform = 'iOS'
missing_version = '26.1'
cache_dir = '/tmp/test_cache'

allow(Fastlane::Helper).to receive(:xcode_at_least?).with('26').and_return(true)
allow(Fastlane::Helper).to receive(:xcode_version).and_return('26.1')
allow(Fastlane::Helper).to receive(:xcode_path).and_return('/Applications/Xcode.app/Contents/Developer')

allow(sut).to receive(:sh).with(
command: 'lipo -archs /Applications/Xcode.app/Contents/MacOS/Xcode',
print_command: false,
print_command_output: false
).and_return('arm64')

missing_runtime = RequiredRuntime.new(sdk_platform: nil, os_name: missing_platform, product_version: missing_version, product_build_version: AppleBuildVersion.new('23B77'), is_latest: false)
expect(sut).to receive(:sh).with(
command: "xcrun xcodebuild -verbose -exportPath #{cache_dir.shellescape} -downloadPlatform #{missing_platform.shellescape} -buildVersion #{missing_version.shellescape} -architectureVariant arm64",
print_command: true,
print_command_output: true
)

# WHEN: Downloading runtime
sut.download_runtime(missing_runtime, cache_dir)

# THEN: Should execute the xcodebuild download command (expectation verified above)
end
end

describe '#import_runtime' do
Expand Down