iOS定制化的自动打包脚本

栏目: IOS · 发布时间: 5年前

内容简介:本文主要是基于用同一套代码生成不用包名、不同开发者证书、不同功能、不同组件依赖、不同Extension、多target等各种需求定制。

本文主要是基于用同一套代码生成不用包名、不同开发者证书、不同功能、不同组件依赖、不同Extension、多target等各种需求定制。

环境安装

  • 安装cocoapods,如果这个都没有安装,基本上不用往后面看了。
  • 安装 ruby 库xcodeproj,详见 Xcodeproj Github

定制打包

一、加载xxx.project的配置

project_path = 'xxx.xcodeproj'
project = Xcodeproj::Project.open(project_path)
复制代码

二、修改工程某Target的build setting

project.targets.each do |target|
    #your target name
    if target.name == 'Scene'
        target.build_configurations.each do |config|
         # Debug / Release
        if config.name == 'Release'
             #获得build settings
            build_settings = config.build_settings
            #build_settings是一个哈希,里面是一个个配置
            build_settings.each do |key,value|
                print key, " == ", value, "\n"
                # 可在这里进行设置证书等操作,常用的如下:
                # 比如修改bundle id ,测试
                # build_settings[key] = "com.test.demo"
                # 设置授权文件
                # build_settings["CODE_SIGN_ENTITLEMENTS"] = "xxx.entitlements"
                # 设置签名 iPhone Distribution / iPhone Developer
                build_settings["PROVISIONING_PROFILE_SPECIFIER"] = "PROFILENAME"
                build_settings["PRODUCT_BUNDLE_IDENTIFIER"] = "your BUNDLEID"
                build_settings["DEVELOPMENT_TEAM"] = "your TEAMID"
                # ..... 其他的视情况(需求)去查找API
            end
        end
    end
 end
复制代码

三、依赖和取消依赖Extension

def updateDependecies(mode, project, app_target_name, ext)
        require 'xcodeproj'
        
        # Find project and app target
        puts mode
        xc = project
        app_target = xc.targets.find { |t| t.name == app_target_name }
        
        # Find app extensions' target objects
        target = xc.targets.find { |t| t.name == ext }
        return "Couldn't find a '#{ext}' target in '#{app_target_name}'" if target.nil?
        return "'#{ext}' doesn't seem to be an application extension target" unless target.product_type.include? 'app-extension'
        target
        
        # Find .appex product files
        appex = target.product_reference
        
        # Add or remove dependency on extension targets
        dependency = app_target.dependency_for_target(target)
        puts app_target.dependencies
        if mode == 'add'
            if dependency
                puts "[WARN] App already has dependency on #{target.name}"
                else
                app_target.add_dependency(target)
            end
            else
            if dependency
                app_target.dependencies.delete(dependency)
                else
                puts "[WARN] Couldn't find dependency on #{target.name}"
            end
        end
        
        # Add or remove .appex copy jobs
        embed_extensions_phase = app_target.copy_files_build_phases.find do |copy_phase|
            copy_phase.symbol_dst_subfolder_spec == :plug_ins
        end
        
        return "Couldn't find 'Embed App Extensions' phase" if embed_extensions_phase.nil?
        appex_included = embed_extensions_phase.files_references.include? appex
        
        if mode == 'add'
            if appex_included
                puts "[WARN] App already embeds #{appex.display_name}"
                else
                build_file = embed_extensions_phase.add_file_reference(appex)
                build_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] }
            end
            else
            if appex_included
                embed_extensions_phase.remove_file_reference(appex)
                else
                puts "[WARN] App doesn't seem to embed #{appex.display_name}"
            end
        end
         return "更新依赖完成,update dependency '#{ext}' target in '#{app_target_name}'"
    end
复制代码

四、向target添加或移除framework

Link binary with libraries system libraries, link them.

Embed Frameworks 3rd party libraries, embed them.

  • 添加或移除系统framework
def exsit_framework?(build_phase,name)
        # next !if build_phase.nil?
        build_phase.files_references.each do |ref|
            if ref.name == "#{name}"
                puts "已经存在 #{name}"
                return true
            end
        end
        puts "不存在 #{name}"
        return false
end

def updateSystemFramework(project,target,name, command)
        require 'xcodeproj'
        puts "#{command} #{name} to #{target}"
        build_phase = target.frameworks_build_phase
        framework_group = project.frameworks_group
        if command == :add
            if self.exsit_framework?(build_phase,name)
                return
            end
            systempath = "System/Library/Frameworks/"
            path = "#{systempath}#{name}"
            file_ref = framework_group.new_reference(path)
            file_ref.name = "#{name}"
            file_ref.source_tree = 'SDKROOT'
            build_file = build_phase.add_file_reference(file_ref)
        else
            build_phase.files_references.each do |ref|
                if ref.name == "#{name}"
                    puts "删除 #{name}"
                    build_phase.remove_file_reference(ref)
                    framework_group.children.delete(ref)                    
                    break
                end
            end 
        end
    end
复制代码
  • 添加或移除自定义framework 和lib
def updateCustomFramework(project,target, path,name,command)

        # Get useful variables
        frameworks_group = project.groups.find { |group| group.display_name == 'Frameworks' }
        frameworks_build_phase = target.build_phases.find { |build_phase| build_phase.to_s == 'FrameworksBuildPhase' }
        embed_frameworks_build_phase = nil
        target.build_phases.each do |phase|
            if phase.display_name == 'Embed Frameworks'
                embed_frameworks_build_phase = phase
            end
            # puts phase
        end
        if command == :add
            # Add new "Embed Frameworks" build phase to target
            if embed_frameworks_build_phase.nil?
                embed_frameworks_build_phase = project.new(Xcodeproj::Project::Object::PBXCopyFilesBuildPhase)
                embed_frameworks_build_phase.name = 'Embed Frameworks'
                embed_frameworks_build_phase.symbol_dst_subfolder_spec = :frameworks
                target.build_phases << embed_frameworks_build_phase
            end
           
            # Add framework search path to target
            ['Debug', 'Release'].each do |config|
                paths = ['$(inherited)', path]
                orgpath = target.build_settings(config)['FRAMEWORK_SEARCH_PATHS']
                if orgpath.nil?
                    puts "路径为空----------"
                    target.build_settings(config)['FRAMEWORK_SEARCH_PATHS'] = paths
            else
                    puts "路径非空----------"
                    paths.each do |p|
                        if !orgpath.include?(p)
                            orgpath << p
                        end 
                    end
                end
            end

            # Add framework to target as "Embedded Frameworks"
            framework_ref = frameworks_group.new_file("#{path}#{name}")
            exsit = false
            embed_frameworks_build_phase.files_references.each do |ref|
                if ref.name = name
                    exsit = true
                end
            end
            if !exsit
                build_file = embed_frameworks_build_phase.add_file_reference(framework_ref)
                frameworks_build_phase.add_file_reference(framework_ref)
                build_file.settings = { 'ATTRIBUTES' => ['CodeSignOnCopy'] }
            end
        else
            frameworks_build_phase.files_references.each do |ref|

                if ref.name == "#{name}"
                    puts "删除 #{name}"
                    frameworks_build_phase.remove_file_reference(ref)
                    embed_frameworks_build_phase.remove_file_reference(ref)
                    break
                end
            end
        end

    end
复制代码

五、是否开启SystemCapabilities

例如:AccessWiFi

#从外面传入的参数
wifiFlag = ARGV[0]
project.objects.each do |obj|
    if obj.isa == "PBXProject"
        systemCapabilities = obj.attributes["TargetAttributes"][ta.uuid]["SystemCapabilities"]
        puts systemCapabilities
        systemCapabilities["com.apple.AccessWiFi"] = {"enabled":"#{wifiFlag}"}
    end
end
复制代码

六、动态修改组件依赖

  • 原本思路 通过脚本通过sed命令直接替换字符串实现,如下:
target 'Scene' do
    pod 'iOSExtension/Widgets',:path => '../'
    pod 'XXX'
    pod 'YYY'
    pod 'AAA'
    pod 'BBB'
end
复制代码

使用sed 命令删除包名XXX的指定行

$sed -i '' "/XXX.*/d" filePath
复制代码
  • 优化思路 虽然上面的指定我们达到效果,但是某些场景下面,就显得有些丑了。如:在某些环境下,我们某个模块的所以pod库,如果还是按上面的脚本的话写法应该如下:
$sed -i '' "/XXX.*/d" filePath
$sed -i '' "/YYY.*/d" filePath
$sed -i '' "/AAA.*/d" filePath
$sed -i '' "/BBB.*/d" filePath
复制代码

其实,Podfile 本身也是一个ruby文件,所以在其中可以定义函数。这时候,解决上面移除多个pod库的,可以定义一个函数

def myPodModule(flag)
    if flag == 0
        puts "不--安装myPodModule"
        return
    end
    pod 'XXX'
    pod 'YYY'
    pod 'AAA'
    pod 'BBB'
    puts "安装myPodModule"
end
target 'Scene' do
    pod 'iOSExtension/Widgets',:path => '../'
    #调用
    myPodModule(1)
end
复制代码

脚本如下:

#依赖的脚本
$sed -i "" 's/myPodModule(0)/myPodModule(1)/g' xxx/Podfile
#不依赖的脚本
$sed -i "" 's/myPodModule(1)/myPodModule(0)/g' xxx/Podfile
复制代码

七、多target的组件依赖

原始的Podfile 的结构如下:

target 'Scene' do
    pod 'iOSExtension/Widgets',:path => '../'
end
target 'Widgets' do
    pod 'my/Wiget',:path => '../'
end
复制代码

这时候的脚本让我很难受。其实同样可以采用上面的思路去封装

def widgets(flag)
    if flag == 0
        puts "不--给widgets target安装依赖"
        return
    end
    target 'Widgets' do
        pod 'my/Wiget',:path => '../'
    end
end
target 'Scene' do
    pod 'iOSExtension/Widgets',:path => '../'
end
#调用
widgets(1)
复制代码

脚本如下:

#依赖的脚本
$sed -i "" 's/widgets(0)/widgets(1)/g' xxx/Podfile
#不依赖的脚本
$sed -i "" 's/widgets(1)/widgets(0)/g' xxx/Podfile
复制代码

八、更多Podfile骚操作

post_install do |installer|
    project = installer.aggregate_targets.first.user_project
    
    project.targets.each do |target|
        puts target.name,'名称:'
        end
end

复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

图形程序开发人员指南

图形程序开发人员指南

Michael Abrash / 前导工作室 / 机械工业出版社 / 1998 / 128

Michael Abrash's classic Graphics Programming Black Book is a compilation of Michael's previous writings on assembly language and graphics programming (including from his "Graphics Programming" column......一起来看看 《图形程序开发人员指南》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具