Class: Gym::XcodebuildFixes

Inherits:
Object
  • Object
show all
Defined in:
lib/gym/xcodebuild_fixes/swift_fix.rb,
lib/gym/xcodebuild_fixes/watchkit_fix.rb,
lib/gym/xcodebuild_fixes/package_application_fix.rb

Class Method Summary collapse

Class Method Details

.clear_patched_package_applicationObject

Remove the patched script after it was used



47
48
49
50
51
52
# File 'lib/gym/xcodebuild_fixes/package_application_fix.rb', line 47

def clear_patched_package_application
  if @patched_package_application_path and File.exist?(@patched_package_application_path)
    Helper.log.debug "Removing patched PackageApplication file at path '#{@patched_package_application_path}'" if $verbose
    File.delete(@patched_package_application_path)
  end
end

.patch_package_applicationObject

Fix PackageApplication Perl script by Xcode to create the IPA from the archive



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/gym/xcodebuild_fixes/package_application_fix.rb', line 5

def patch_package_application
  require 'fileutils'

  # Initialization
  @patched_package_application_path = File.join("/tmp", "PackageApplication4Gym")
  # Remove any previous patched PackageApplication
  FileUtils.rm @patched_package_application_path if File.exist?(@patched_package_application_path)

  Dir.mktmpdir do |tmpdir|
    # Check current PackageApplication MD5
    require 'digest'

    path = File.join(Helper.gem_path("gym"), "lib/assets/package_application_patches/PackageApplication_MD5")
    expected_md5 = File.read(path)

    # If that location changes, search it using xcrun --sdk iphoneos -f PackageApplication
    package_application_path = "#{Gym.xcode_path}/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication"

    raise "Unable to patch the `PackageApplication` script bundled in XCode. This is not supported." unless expected_md5 == Digest::MD5.file(package_application_path).hexdigest

    # Duplicate PackageApplication script to PackageApplication4Gym
    FileUtils.copy_file(package_application_path, @patched_package_application_path)

    # Apply patches to PackageApplication4Gym from patches folder
    Dir[File.join(Helper.gem_path("gym"), "lib/assets/package_application_patches/*.diff")].each do |patch|
      Helper.log.info "Applying Package Application patch: #{File.basename(patch)}" if $verbose
      command = ["patch #{@patched_package_application_path} < #{patch}"]
      Runner.new.print_command(command, "Applying Package Application patch: #{File.basename(patch)}") if $verbose

      FastlaneCore::CommandExecutor.execute(command: command,
                                          print_all: false,
                                      print_command: $verbose,
                                              error: proc do |output|
                                                ErrorHandler.handle_package_error(output)
                                              end)
    end
  end

  return @patched_package_application_path # Return path to the patched PackageApplication
end

.swift_library_fixObject

Determine whether it is a Swift project and, eventually, include all required libraries to copy from Xcode’s toolchain directory. Since there’s no “xcodebuild” target to do just that, it is done post-build when exporting an archived build.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/gym/xcodebuild_fixes/swift_fix.rb', line 6

def swift_library_fix
  require 'fileutils'

  ipa_swift_frameworks = Dir["#{PackageCommandGenerator.appfile_path}/Frameworks/libswift*"]
  Helper.log.info "Checking for Swift framework" if $verbose

  return if ipa_swift_frameworks.empty?
  Helper.log.info "Packaging up the Swift Framework as the current app is a Swift app" if $verbose

  Dir.mktmpdir do |tmpdir|
    # Copy all necessary Swift libraries to a temporary "SwiftSupport" directory so that we can
    # easily add it to the .ipa later.
    swift_support = File.join(tmpdir, "SwiftSupport")

    Dir.mkdir(swift_support)

    ipa_swift_frameworks.each do |path|
      framework = File.basename(path)

      FileUtils.copy_file("#{Gym.xcode_path}/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos/#{framework}", File.join(swift_support, framework))
    end

    # Add "SwiftSupport" to the .ipa archive
    Dir.chdir(tmpdir) do
      command_parts = ["zip --recurse-paths #{PackageCommandGenerator.ipa_path} SwiftSupport"]
      command_parts << "> /dev/null" unless $verbose
      print_command(command_parts, "Fix Swift embedded code if needed") if $verbose

      FastlaneCore::CommandExecutor.execute(command: command_parts,
                                          print_all: false,
                                      print_command: !Gym.config[:silent],
                                              error: proc do |output|
                                                ErrorHandler.handle_package_error(output)
                                              end)
    end
  end
end

.watchkit?Boolean

Does this application have a WatchKit target

Returns:

  • (Boolean)


28
29
30
31
32
# File 'lib/gym/xcodebuild_fixes/watchkit_fix.rb', line 28

def watchkit?
  Dir["#{PackageCommandGenerator.appfile_path}/**/*.plist"].any? do |plist_path|
    `/usr/libexec/PlistBuddy -c 'Print WKWatchKitApp' '#{plist_path}' 2>&1`.strip == 'true'
  end
end

.watchkit_fixObject

Determine whether this app has WatchKit support and manually package up the WatchKit framework



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/gym/xcodebuild_fixes/watchkit_fix.rb', line 5

def watchkit_fix
  return unless watchkit?

  Helper.log.info "Adding WatchKit support" if $verbose

  Dir.mktmpdir do |tmpdir|
    # Make watchkit support directory
    watchkit_support = File.join(tmpdir, "WatchKitSupport")
    Dir.mkdir(watchkit_support)

    # Copy WK from Xcode into WatchKitSupport
    FileUtils.copy_file("#{Gym.xcode_path}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/Library/Application Support/WatchKit/WK", File.join(watchkit_support, "WK"))

    # Add "WatchKitSupport" to the .ipa archive
    Dir.chdir(tmpdir) do
      abort unless system %(zip --recurse-paths "#{PackageCommandGenerator.ipa_path}" "WatchKitSupport" > /dev/null)
    end

    Helper.log.info "Successfully added WatchKit support" if $verbose
  end
end