简体   繁体   中英

How to read .xcconfig file constants with ruby to use them as Fastlane lane variables?

I'm trying to deploy my iOS apps with Fastlane with the current configuration: a single project with multiple targets and multiple environments (using .xccconfig files). I created 3 lanes: development, beta, distribution. Theses lanes takes a "brand_name" as parameter so I can use the same lane for every targets.

What I'm trying to achieve is to "read" the constants in the target's .xcconfig file (eg PRODUCT_BUNDLE_IDENTIFIER ) and use it as a variable in my lane. I managed to do this by creating and reading a yaml file containing the target's bundle id, but since I'm already using .xcconfig files I would like to avoid duplication. I did some searching to find an answer but since I'm fairly new to ruby I'm stuck right now. Is there a way to achieve this please?

If it helps, here is a working lane I'm currently using with a comment on the part I want to replace using a .xcconfig file instead of a yaml file :

lane :development do |options|

    # Getting lane settings

    #adding lane_name to the options
    options = options.merge(lane_name: 'development') 

    # THIS IS THE PART I'D LIKE TO REPLACE WITH .XCCONFIG FILE INSTEAD OF YAML
    #fastlane config path
    config = YAML.load_file(File.join(File.dirname(__FILE__),"../Brand", options[:brand_name],"Configs/fastlane_config.yaml"))
    settings = OpenStruct.new(config)
    lane_settings = settings[options[:lane_name]]

    # Settings the App Identifier
    app_identifier = lane_settings["bundle_identifier"]

    pilot(skip_submission: true)
end

Thank you

I've been working on a similar task and have found a solution that seems to work. Answering your question, we can open the .xcconfig file and read a value by key.

lane :development do |options|
    fastlane_require 'Xcodeproj'

    # Compose .xcconfig file path
    configuration_file = "../Brand" + options[:brand_name] + "Configs/config.xcconfig"

    # Read values from the .xcconfig file
    configuration = Xcodeproj::Config.new(configuration_file)
    app_identifier = configuration.attributes['PRODUCT_BUNDLE_IDENTIFIER']

    ... 
end

But I find it as a quite dirty solution, as there is still some duplication: we've specified a config file for target/configuration in the Xcode project, and now we manually specifying it again.

There are even more issues appear as soon as we begin to "inherit" (include) configuration files from each other. It can be useful in case you have lots of build configurations and most of them share same settings, but only some settings differ across configurations.

The right way to achieve what you most likely need is to get the flag value by merging all applicable sources: project, target, configuration, configuration files. This can be done by getting build settings from your configuration , not from the .xcconfig itself.

lane :development do |options|
    fastlane_require 'Xcodeproj'


    # Here we can define some hardcoded values,
    # or read them from lane options,
    # or read them from environment variables...
    project_name = '../XXX.xcodeproj'
    target_name = 'YYY'
    configuration_name = 'ZZZ'

    # Read values from the configuration,
    # specified in project settings for a specific target.
    project = Xcodeproj::Project.open(project_name)
    target = project.native_targets.find {|s| s.name == target_name }
    configuration = target.build_configurations.find {|s| s.name == configuration_name}
    app_identifier = configuration.resolve_build_setting('PRODUCT_BUNDLE_IDENTIFIER')

    ...

end

What about directly open Xcode project and loop through targets/configurations to find the correct one:

lane :development do |options|

    # Getting lane settings

    #adding lane_name to the options
    options = options.merge(lane_name: 'development')

    project = '../PATH_TO_XCODE_PROJ'
    target = 'TARGET'
    buildConfiguration = 'BUILD_CONFIGURATION'
    app_identifier = ''

    project = Xcodeproj::Project.open(project)
    project.targets.each do |mtarget|
        if mtarget.name == target
            mtarget.build_configurations.each do |mbuild|
                if mbuild.name == buildConfiguration
                    app_identifier = mbuild.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
                end
            end
        end
    end

    pilot(skip_submission: true)
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM