美文网首页
Mac配置Jenkins三,使用Xcodepro和PlistBu

Mac配置Jenkins三,使用Xcodepro和PlistBu

作者: 独孤流 | 来源:发表于2023-05-24 00:10 被阅读0次

    参考:
    PlistBuddy基本使用方法
    https://github.com/CocoaPods/Xcodeproj
    本文完整代码:https://github.com/h42330789/testplist/tree/main/ReadWriteXcodeproj

    前言,打包过程中,需要读取或修改版本号、bundleId等信息,之前可以使用PlistBuddy读取,现在配置在xcodeproj文件里后,就难以读取和修改,但是使用Xcodeproj可以很方便的读取和修改

    一、使用PlistBuddy读取Info.plist里的配置信息,在之前的项目里可能有,现在的新项目一般都放到了project.pbxproj里
    #### 使用PlistBuddy从Info.plist里读取
    infoPlistPath="/Users/macbookpro/Documents/study/HelloPod/HelloPod/Info.plist"
    bundleDisplayName=`/usr/libexec/PlistBuddy -c "Print CFBundleDisplayName" $infoPlistPath`
    # APP版本号,如1.0.1, 在新版xcode生成的项目里可能是MARKETING_VERSION,或者根本不存在,则需要去project.pbxproj里去读取
    bundleVersion=`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" $infoPlistPath`
    # APP的build版本,一般使用数字,如1,在新版xcode生成的项目里可能是CURRENT_PROJECT_VERSION,或者不存在,则需要去project.pbxproj里去读取
    bundleBuildVersion=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $infoPlistPath`
    # APP的bundleId,如com.ab.xyz 在新版xcode生成的项目里可能是PRODUCT_BUNDLE_IDENTIFIER,或者不存在,则需要去project.pbxproj里去读取
    bundleId=`/usr/libexec/PlistBuddy -c "Print CFBundleIdentifier" $infoPlistPath`
    echo "bundleDisplayName: $bundleDisplayName"
    echo "bundleVersion: $bundleVersion"
    echo "bundleBuildVersion: $bundleBuildVersion"
    echo "bundleId: $bundleId"
    
    二、使用Xcodeproj从project.pbxproj里读取
    2.1 安装xcodeproj
    sudo gem install xcodeproj
    
    2.2 使用xcodeproj读取xcode配置文件

    创建一个以.rb为结尾的文件, 遍历循环target和config,然后从buildSetting里读取

    # 读取里buildSetting里的数据
    def readBuildSetting(xcodeprojPath, findTargetName, findConfigName, findKey)
        # 读取xcode的配置信息, xxx/xxx/xx.xcodeproj
         project = Xcodeproj::Project.open(xcodeprojPath)
        # 遍历target、config是否一直
         project.targets.each do |target|
             targetName = target.name
             target.build_configurations.each do |config|
                 configName = config.name
                 build_settings = config.build_settings
                 if (targetName == findTargetName) && (configName == findConfigName)
                     # 查找到对应的build_settings后,读取对应的key
                     findValue = config.build_settings[findKey]
                     # 将查找的内容,存放到plist里
                     puts "#{findKey}: #{findValue}"
                     return
                 end
             end
         end
     end
    
    2.3 使用xcodeproj修改xcode配置文件

    创建一个以.rb为结尾的文件, 遍历循环target和config,然后从buildSetting里读取

    # 修改里buildSetting里的数据
    def updateBuildSetting(xcodeprojPath, findTargetName, findConfigName, updateKey, updateValue)
        # 读取xcode的配置信息, xxx/xxx/xx.xcodeproj
        project = Xcodeproj::Project.open(xcodeprojPath)
        # 遍历target、config是否一直
        project.targets.each do |target|
            targetName = target.name
            target.build_configurations.each do |config|
                configName = config.name
                build_settings = config.build_settings
                if (targetName == findTargetName) && (configName == findConfigName)
                    # 修改内容
                    config.build_settings[updateKey] = updateValue
                end
            end
        end
       # 保存修改
        project.save()
    end
    

    完整的实现:

    #!/usr/bin/ruby
    # https://github.com/CocoaPods/Xcodeproj
    require 'xcodeproj'
    
    # ruby 非空判断 https://blog.csdn.net/leinminna/article/details/110422744
    # 在 Ruby 中执行 Shell 命令的 6 种方法 https://segmentfault.com/a/1190000000368191
    
    # 增加或修改key对应的value,如果不存在就增加,如果存在不一致就修改
    def changeDict(dict, key, value)
        if (dict.has_key?(key))
            oldValue = dict[key]
            if (oldValue != value)
                dict[key] = value
                return true
            end
        else
            dict[key] = value
            return true
        end
        return false
    end
    
    # 删除key,如果存在才删除
    def deleteDict(dict, key)
        if (dict.has_key?(key))
            dict.delete(key)
            return true
        end
        return false
    end
    
    # bool值取或运输
    def boolOr(a, b)
        if (a == false and b == false)
            return false
        end
        return true
    end
    
    # bool值取与运输
    def boolAnd(a, b)
        if (a == true and b == true)
            return true
        end
        return false
    end
    
    def updateParamPlist(paramPlistPath, key, value)
        oldVale = `/usr/libexec/PlistBuddy -c "Print #{key}" #{paramPlistPath}`
        if oldVale.nil? || oldVale.empty?
            # 之前不存在,则添加
            `/usr/libexec/PlistBuddy -c 'Add :#{key} string #{value}' #{paramPlistPath}`
        else
            # 之前存在,则修改
            `/usr/libexec/PlistBuddy -c 'Set :#{key} #{value}' #{paramPlistPath}`
        end
        puts "read key: #{key} oldVale: #{oldVale} newValue: #{value}"
    end
    
    # 读取xcoceproj里buildSetting里的数据
    def readBuildSetting(xcodeprojPath, findTargetName, findConfigName, findKey, paramPlistPath)
    
        # puts "xcodeprojPath: #{xcodeprojPath}"
        # puts "findTargetName: #{findTargetName}"
        # puts "findConfigName: #{findConfigName}"
        
        project = Xcodeproj::Project.open(xcodeprojPath)
    
        project.targets.each do |target|
            targetName = target.name
            target.build_configurations.each do |config|
                configName = config.name
                build_settings = config.build_settings
                if (targetName == findTargetName) && ((findConfigName == "All") || (configName == findConfigName))
                    findValue = config.build_settings[findKey]
                    # 将查找的内容,存放到plist里
                    updateParamPlist(paramPlistPath, findKey, findValue)
                    puts "----------readBuildSetting---success--end---------------"
                    return
                end
            end
        end
        puts "----------readBuildSetting--error--end-------------"
    end
    
    # 读取xcoceproj里buildSetting里的数据
    def updateBuildSetting(xcodeprojPath, findTargetName, findConfigName, updateKey, updateValue)
    
        isNeedChange = false
        project = Xcodeproj::Project.open(xcodeprojPath)
    
        project.targets.each do |target|
            targetName = target.name
            target.build_configurations.each do |config|
                configName = config.name
                build_settings = config.build_settings
                if (targetName == findTargetName) && ((findConfigName == "All") || (configName == findConfigName))
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, updateKey, updateValue))
                    # 将查找的内容,存放到plist里
                    puts "----------updateBuildSetting---success--end---------------"
                end
            end
        end
       # 保存配置
       if (isNeedChange == true)
        project.save()
        end
    end
    
    # 对项目设置成自动管理
    def updateAutoProfile(xcodeprojPath, findTargetName, findConfigName, newTeamId, newBundleId)
    
        isNeedChange = false
        project = Xcodeproj::Project.open(xcodeprojPath)
    
        project.targets.each do |target|
            targetName = target.name
            target.build_configurations.each do |config|
                configName = config.name
                build_settings = config.build_settings
                if (targetName == findTargetName) && ((findConfigName == "All") || (configName == findConfigName))
                    # 删除手动管理相关的配置
                    isNeedChange = boolOr(isNeedChange, deleteDict(build_settings, "CODE_SIGN_IDENTITY[sdk=iphoneos*]"))
                    isNeedChange = boolOr(isNeedChange, deleteDict(build_settings, "CODE_SIGN_STYLE"))
                    isNeedChange = boolOr(isNeedChange, deleteDict(build_settings, "DEVELOPMENT_TEAM"))
                    isNeedChange = boolOr(isNeedChange, deleteDict(build_settings, "DEVELOPMENT_TEAM[sdk=iphoneos*]"))
                    isNeedChange = boolOr(isNeedChange, deleteDict(build_settings, "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]"))
                    isNeedChange = boolOr(isNeedChange, deleteDict(build_settings, "PROVISIONING_PROFILE_SPECIFIER"))
    
                    # 修改
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "CODE_SIGN_STYLE", "Automatic"))
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "DEVELOPMENT_TEAM", newTeamId))
    
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "PRODUCT_BUNDLE_IDENTIFIER", newBundleId))
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "CODE_SIGN_IDENTITY", "Apple Development"))
                end
            end
        end
        
        
        puts "isNeedChange #{isNeedChange}"
        # 保存配置
        if (isNeedChange == true)
            project.save()
        end
    end
    
    # 对项目设置成手动管理
    def updateManualProfile(xcodeprojPath, findTargetName, findConfigName, newTeamId, newBundleId, newProfileName)
    
        isNeedChange = false
        project = Xcodeproj::Project.open(xcodeprojPath)
    
        project.targets.each do |target|
            targetName = target.name
            target.build_configurations.each do |config|
                configName = config.name
                build_settings = config.build_settings
                if (targetName == findTargetName) && ((findConfigName == "All") || (configName == findConfigName))
                     # 去掉自动管理证书,证书方
                    isNeedChange = boolOr(isNeedChange, deleteDict(build_settings, "CODE_SIGN_IDENTITY"))
                    isNeedChange = boolOr(isNeedChange, deleteDict(build_settings, "CODE_SIGN_STYLE"))
                    # 增加手动管理证书
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "iPhone Distribution"))
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "CODE_SIGN_STYLE", "Manual"))
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "DEVELOPMENT_TEAM[sdk=iphoneos*]", newTeamId))
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "DEVELOPMENT_TEAM", newTeamId))
    
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]", newProfileName))
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "PRODUCT_BUNDLE_IDENTIFIER", newBundleId))
                    isNeedChange = boolOr(isNeedChange, changeDict(build_settings, "CODE_SIGN_IDENTITY", "Apple Distribution"))
                end
            end
        end
        
        
        puts "isNeedChange #{isNeedChange}"
        # 保存配置
        if (isNeedChange == true)
            project.save()
        end
    end
    
    type=ARGV[0]
    if type == "write"
        # 给buildSetting里设置信息
        xcodeprojPath = ARGV[1]
        findTargeName = ARGV[2]
        findConfigName = ARGV[3]
        updateKey = ARGV[4]
        updateValue = ARGV[5]
    
        updateBuildSetting(xcodeprojPath, findTargeName, findConfigName, updateKey, updateValue)
    elsif type == "read"
        # 读取buildSetting里的信息
        xcodeprojPath = ARGV[1]
        findTargeName = ARGV[2]
        findConfigName = ARGV[3]
        findKey = ARGV[4]
        paramPlistPath = ARGV[5]
    
        readBuildSetting(xcodeprojPath, findTargeName, findConfigName, findKey, paramPlistPath)
    elsif type == "autoProfile"
        # 设置自动管理证书
        xcodeprojPath = ARGV[1]
        findTargeName = ARGV[2]
        findConfigName = ARGV[3]
        newTeamId = ARGV[4]
        newBundleId = ARGV[5]
    
        updateAutoProfile(xcodeprojPath, findTargetName, findConfigName, newTeamId, newBundleId)
    elsif type == "manualProfile"
        # 设置手动管理证书
        xcodeprojPath = ARGV[1]
        findTargeName = ARGV[2]
        findConfigName = ARGV[3]
        newTeamId = ARGV[4]
        newBundleId = ARGV[5]
        newProfileName = ARGV[6]
    
        updateManualProfile(xcodeprojPath, findTargetName, findConfigName, newTeamId, newBundleId, newProfileName)
    end
    

    完整的调用示例

    #!/bin/sh
    export LC_ALL=en_US.UTF-8
    
    #### 使用PlistBuddy从Info.plist里读取
    infoPlistPath="/Users/macbookpro/Documents/study/HelloPod/HelloPod/Info.plist"
    bundleDisplayName=`/usr/libexec/PlistBuddy -c "Print CFBundleDisplayName" $infoPlistPath`
    # APP版本号,如1.0.1, 在新版xcode生成的项目里可能是MARKETING_VERSION,或者根本不存在,则需要去project.pbxproj里去读取
    bundleVersion=`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" $infoPlistPath`
    # APP的build版本,一般使用数字,如1,在新版xcode生成的项目里可能是CURRENT_PROJECT_VERSION,或者不存在,则需要去project.pbxproj里去读取
    bundleBuildVersion=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $infoPlistPath`
    # APP的bundleId,如com.ab.xyz 在新版xcode生成的项目里可能是PRODUCT_BUNDLE_IDENTIFIER,或者不存在,则需要去project.pbxproj里去读取
    bundleId=`/usr/libexec/PlistBuddy -c "Print CFBundleIdentifier" $infoPlistPath`
    echo "bundleDisplayName: $bundleDisplayName"
    echo "bundleVersion: $bundleVersion"
    echo "bundleBuildVersion: $bundleBuildVersion"
    echo "bundleId: $bundleId"
    
    
    
    #### 使用xcodeProj从project.pbxproj里读取
    rubyPath=`which ruby`
    rubyScriptPath="/Users/macbookpro/Desktop/test/xcodeprojTool.rb"
    xcodeprojPath="/Users/macbookpro/Documents/study/HelloPod/HelloPod.xcodeproj"
    infoPlistPath="/Users/macbookpro/Documents/study/HelloPod/HelloPod/Info.plist"
    paramPlistPath="./param.plist"
    findTargetName="HelloPod"
    readConfig="Release" # Release Debug All
    writeConfig="All"
    # 读取版本号
    $rubyPath $rubyScriptPath "read" $xcodeprojPath $findTargetName $readConfig "MARKETING_VERSION" $paramPlistPath
    # 读取编译版本号
    $rubyPath $rubyScriptPath "read" $xcodeprojPath $findTargetName $readConfig "CURRENT_PROJECT_VERSION" $paramPlistPath
    # 读取bundleId
    $rubyPath $rubyScriptPath "read" $xcodeprojPath $findTargetName $readConfig "PRODUCT_BUNDLE_IDENTIFIER" $paramPlistPath
    # 读取App名称
    $rubyPath $rubyScriptPath "read" $xcodeprojPath $findTargetName $readConfig "INFOPLIST_KEY_CFBundleDisplayName" $paramPlistPath
    # 修改内容
    
    # 修改版本号
    $rubyPath $rubyScriptPath "write" $xcodeprojPath $findTargetName $writeConfig "MARKETING_VERSION" "1.12.002"
    # 修改编译版本号
    $rubyPath $rubyScriptPath "write" $xcodeprojPath $findTargetName $writeConfig "CURRENT_PROJECT_VERSION" "88"
    # 修改bundleId
    $rubyPath $rubyScriptPath "write" $xcodeprojPath $findTargetName $writeConfig "PRODUCT_BUNDLE_IDENTIFIER" "www.ab.com"
    # 修改App名称
    $rubyPath $rubyScriptPath "write" $xcodeprojPath $findTargetName $writeConfig "INFOPLIST_KEY_CFBundleDisplayName" "bestAp"
    

    相关文章

      网友评论

          本文标题:Mac配置Jenkins三,使用Xcodepro和PlistBu

          本文链接:https://www.haomeiwen.com/subject/kvuzsdtx.html