class Fastlane::Actions::CreateXcframeworkAction

Constants

PARAMETERS_TO_OPTIONS

Public Class Methods

artifact_info_as_options(artifact_info) click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 50
def self.artifact_info_as_options(artifact_info)
  artifact_info.map { |type, file| [PARAMETERS_TO_OPTIONS[type], "\"#{file}\""] }.flatten
end
authors() click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 194
def self.authors
  ["jgongo"]
end
available_options() click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 104
def self.available_options
  [
    FastlaneCore::ConfigItem.new(key: :frameworks,
                                 env_name: "FL_CREATE_XCFRAMEWORK_FRAMEWORKS",
                                 description: "Frameworks (without dSYMs) to add to the target xcframework",
                                 type: Array,
                                 optional: true,
                                 conflicting_options: [:frameworks_with_dsyms, :libraries, :libraries_with_headers_or_dsyms],
                                 verify_block: proc do |value|
                                   normalized_artifact_info(value, [:dsyms]).each do |framework, framework_info|
                                     UI.user_error!("#{framework} doesn't end with '.framework'. Is this really a framework?") unless framework.end_with?('.framework')
                                     UI.user_error!("Couldn't find framework at #{framework}") unless File.exist?(framework)
                                     UI.user_error!("#{framework} doesn't seem to be a framework") unless File.directory?(framework)
                                     check_artifact_info(framework_info)
                                   end
                                 end),
    FastlaneCore::ConfigItem.new(key: :frameworks_with_dsyms,
                                 env_name: "FL_CREATE_XCFRAMEWORK_FRAMEWORKS_WITH_DSYMS",
                                 description: "Frameworks (with dSYMs) to add to the target xcframework",
                                 type: Hash,
                                 optional: true,
                                 conflicting_options: [:frameworks, :libraries, :libraries_with_headers_or_dsyms],
                                 verify_block: proc do |value|
                                   normalized_artifact_info(value, [:dsyms]).each do |framework, framework_info|
                                     UI.user_error!("#{framework} doesn't end with '.framework'. Is this really a framework?") unless framework.end_with?('.framework')
                                     UI.user_error!("Couldn't find framework at #{framework}") unless File.exist?(framework)
                                     UI.user_error!("#{framework} doesn't seem to be a framework") unless File.directory?(framework)
                                     check_artifact_info(framework_info)
                                   end
                                 end),
    FastlaneCore::ConfigItem.new(key: :libraries,
                                 env_name: "FL_CREATE_XCFRAMEWORK_LIBRARIES",
                                 description: "Libraries (without headers or dSYMs) to add to the target xcframework",
                                 type: Array,
                                 optional: true,
                                 conflicting_options: [:frameworks, :frameworks_with_dsyms, :libraries_with_headers_or_dsyms],
                                 verify_block: proc do |value|
                                   normalized_artifact_info(value, [:headers, :dsyms]).each do |library, library_info|
                                     UI.user_error!("Couldn't find library at #{library}") unless File.exist?(library)
                                     check_artifact_info(library_info)
                                   end
                                 end),
    FastlaneCore::ConfigItem.new(key: :libraries_with_headers_or_dsyms,
                                 env_name: "FL_CREATE_XCFRAMEWORK_LIBRARIES_WITH_HEADERS_OR_DSYMS",
                                 description: "Libraries (with headers or dSYMs) to add to the target xcframework",
                                 type: Hash,
                                 optional: true,
                                 conflicting_options: [:frameworks, :frameworks_with_dsyms, :libraries],
                                 verify_block: proc do |value|
                                   normalized_artifact_info(value, [:headers, :dsyms]).each do |library, library_info|
                                     UI.user_error!("Couldn't find library at #{library}") unless File.exist?(library)
                                     check_artifact_info(library_info)
                                   end
                                 end),
    FastlaneCore::ConfigItem.new(key: :output,
                                 env_name: "FL_CREATE_XCFRAMEWORK_OUTPUT",
                                 description: "The path to write the xcframework to",
                                 type: String,
                                 optional: false),
    FastlaneCore::ConfigItem.new(key: :allow_internal_distribution,
                                 env_name: "FL_CREATE_XCFRAMEWORK_ALLOW_INTERNAL_DISTRIBUTION",
                                 description: "Specifies that the created xcframework contains information not suitable for public distribution",
                                 type: Boolean,
                                 optional: true,
                                 default_value: false)
  ]
end
category() click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 190
def self.category
  :building
end
check_artifact_info(artifact_info) click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 54
def self.check_artifact_info(artifact_info)
  UI.user_error!("Headers and dSYMs information should be a hash") unless artifact_info.kind_of?(Hash)
  UI.user_error!("#{artifact_info[:headers]} doesn't exist or is not a directory") if artifact_info[:headers] && !File.directory?(artifact_info[:headers])
  UI.user_error!("#{artifact_info[:dsyms]} doesn't seem to be a dSYM archive") if artifact_info[:dsyms] && !File.directory?(artifact_info[:dsyms])
end
description() click to toggle source

@!group Documentation

# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 64
def self.description
  "Package multiple build configs of a library/framework into a single xcframework"
end
details() click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 68
      def self.details
        <<~DETAILS
          Utility for packaging multiple build configurations of a given library
          or framework into a single xcframework.

          If you want to package several frameworks just provide one of:

            * An array containing the list of frameworks using the :frameworks parameter
              (if they have no associated dSYMs):
                ['FrameworkA.framework', 'FrameworkB.framework']

            * A hash containing the list of frameworks with their dSYMs using the
              :frameworks_with_dsyms parameter:
                {
                  'FrameworkA.framework' => {},
                  'FrameworkB.framework' => { dsyms: 'FrameworkB.framework.dSYM' }
                }

          If you want to package several libraries just provide one of:

            * An array containing the list of libraries using the :libraries parameter
              (if they have no associated headers or dSYMs):
                ['LibraryA.so', 'LibraryB.so']

            * A hash containing the list of libraries with their headers and dSYMs
              using the :libraries_with_headers_or_dsyms parameter:
                {
                  'LibraryA.so' => { dsyms: 'libraryA.so.dSYM' },
                  'LibraryB.so' => { headers: 'headers' }
                }

          Finally specify the location of the xcframework to be generated using the :output
          parameter.
        DETAILS
      end
example_code() click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 181
def self.example_code
  [
    "create_xcframework(frameworks: ['FrameworkA.framework', 'FrameworkB.framework'], output: 'UniversalFramework.xcframework')",
    "create_xcframework(frameworks_with_dsyms: {'FrameworkA.framework' => {}, 'FrameworkB.framework' => { dsyms: 'FrameworkB.framework.dSYM' } }, output: 'UniversalFramework.xcframework')",
    "create_xcframework(libraries: ['LibraryA.so', 'LibraryB.so'], output: 'UniversalFramework.xcframework')",
    "create_xcframework(libraries_with_headers_or_dsyms: { 'LibraryA.so' => { dsyms: 'libraryA.so.dSYM' }, 'LibraryB.so' => { headers: 'LibraryBHeaders' } }, output: 'UniversalFramework.xcframework')"
  ]
end
is_supported?(platform) click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 198
def self.is_supported?(platform)
  [:ios, :mac].include?(platform)
end
normalized_artifact_info(artifacts_with_info, valid_info) click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 34
def self.normalized_artifact_info(artifacts_with_info, valid_info)
  case artifacts_with_info
  when Array
    artifacts_with_info.map { |artifact| [artifact, {}] }.to_h
  when Hash
    # Convert keys of artifact info to symbols ('dsyms' to :dsyms) and only keep keys we are interested in
    # For example with valid_info = [:dsyms]
    #  { 'FrameworkA.framework' => { 'dsyms' => 'FrameworkA.framework.dSYM', 'foo' => bar } }
    # gets converted to
    #  { 'FrameworkA.framework' => { dsyms: 'FrameworkA.framework.dSYM' } }
    artifacts_with_info.transform_values { |artifact_info| artifact_info.transform_keys(&:to_sym).slice(*valid_info) }
  else
    artifacts_with_info
  end
end
output() click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 172
def self.output
  [
    ['XCFRAMEWORK_PATH', 'Location of the generated xcframework']
  ]
end
return_value() click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 178
def self.return_value
end
run(params) click to toggle source
# File fastlane/lib/fastlane/actions/create_xcframework.rb, line 10
def self.run(params)
  artifacts = normalized_artifact_info(params[:frameworks], [:dsyms]) ||
              normalized_artifact_info(params[:frameworks_with_dsyms], [:dsyms]) ||
              normalized_artifact_info(params[:libraries], [:headers, :dsyms]) ||
              normalized_artifact_info(params[:libraries_with_headers_or_dsyms], [:headers, :dsyms])

  UI.user_error!("Please provide either :frameworks, :frameworks_with_dsyms, :libraries or :libraries_with_headers_or_dsyms to be packaged into the xcframework") unless artifacts

  artifacts_type = params[:frameworks] || params[:frameworks_with_dsyms] ? '-framework' : '-library'
  create_command = ['xcodebuild', '-create-xcframework']
  create_command << artifacts.map { |artifact, artifact_info| [artifacts_type, "\"#{artifact}\""] + artifact_info_as_options(artifact_info) }.flatten
  create_command << ['-output', "\"#{params[:output]}\""]
  create_command << ['-allow-internal-distribution'] if params[:allow_internal_distribution]

  if File.directory?(params[:output])
    UI.message("Deleting existing: #{params[:output]}")
    FileUtils.remove_dir(params[:output])
  end

  Actions.lane_context[SharedValues::XCFRAMEWORK_PATH] = params[:output]

  sh(create_command)
end