xcodebuild 不会编译项目,除非它至少使用 Xcode 打开一次用于 cocoapods 集成项目

Posted

技术标签:

【中文标题】xcodebuild 不会编译项目,除非它至少使用 Xcode 打开一次用于 cocoapods 集成项目【英文标题】:xcodebuild is not compiling the project unless it is opened using Xcode atleast only once for cocoapods integrated project 【发布时间】:2016-03-30 19:47:42 【问题描述】:

我有一个带有可可豆荚的项目。

这是我用来构建项目的命令。

/usr/bin/xcodebuild -scheme Jenkins -workspace /Users/Shared/Jenkins/Documents/Jenkins/Jenkins2/Jenkins.xcworkspace -configuration Release clean build CONFIGURATION_BUILD_DIR=/Users/Shared/Jenkins/Documents/JenkinsTestNuu/app 'CODE_SIGN_IDENTITY=iPhone 分布:XXXX 耶 (3G5FKTZJ2K)' PRODUCT_BUNDLE_IDENTIFIER=com.XXXX.two PROVISIONING_PROFILE=6e6506e9-8233-4886-9084-ce21e8f8bbae

上述脚本只有在使用 Xcode 打开项目至少一次之后才能正常工作,然后 Xcode 可以关闭没有问题。

如果项目尚未打开,那么如果我运行脚本 车轮在下面旋转,永远没有任何进展,例如下图

如果它打开一次而不是下面的旋转轮,文本将显示在下面

=== CLEAN TARGET XWebView OF PROJECT Pods WITH CONFIGURATION Release ===

检查依赖关系

清洁。删除清洁 /Users/Shared/Jenkins/Documents/JenkinsTestNuu/app/XWebView.framework.dSYM 内置-rm -rf /Users/Shared/Jenkins/Documents/JenkinsTestNuu/app/XWebView.framework.dSYM

清洁。删除清洁 /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/appanme-bqjwbjcqisegldeaonpytprisnig/Build/Intermediates/Pods.build/Release-iphoneos/XWebView.build builtin-rm -rf /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/appanme-bqjwbjcqisegldeaonpytprisnig/Build/Intermediates/Pods.build/Release-iphoneos/XWebView.build

清洁。删除清洁 /Users/Shared/Jenkins/Documents/JenkinsTestNuu/app/XWebView.framework 内置-rm -rf /Users/Shared/Jenkins/Documents/JenkinsTestNuu/app/XWebView.framework

=== CLEAN Target Pods OF PROJECT Pods WITH CONFIGURATION Release ===

检查依赖项 等等……

在任何非 cocoapods 项目中都没有观察到该问题。

那会是什么原因以及如何解决呢?

【问题讨论】:

在开始xcodebuild之前你是否在运行pod install @ChristopherOrr - 在 xcodebuild 解决问题之前运行 pod install @DuraiAmuthan.H - 在这里面临同样的问题。这个修复程序不起作用 xcodebuild 说方案不可用。你还做了什么让它工作?急需请尽快回复 @King - 让我尽快更新您。 @King - .让我检查一下我是否做了任何额外的工作来使它工作.. 【参考方案1】:

为什么会这样?

一个快速的diffMerge工具分析Xcode打开的项目Xcode目前没有打开的同一个项目

从这里我们可以看到很多scheme相关的文件一旦被Xcode在.xcodeproj中打开

所以 xcodebuild 通过使用与方案相关的元数据创建 .app,但由于没有针对其失败构建的方案

如何解决?

由于缺少无法构建的元数据,因此需要打开 Xcode,以便 Xcode 自动创建文件,因此将有一些构建方案。

但是当您打开 Xcode 时,此 Scheme 相关文件会在 xcuserdata 下创建,该文件是针对特定用户的。即每个用户都有自己的文件来保存打开的状态文件夹,最后打开的文件等......

把这个文件留给我们是不明智的。

问题可以通过选中管理方案下的共享复选框来解决

这会将 schemes 从您的个人 xcuserdata 下移到可以通过源代码管理提交的 共享文件夹 中,您可以放心地忽略 em>xcuserdata 并将共享文件夹保存在源代码管理

现在我们可以在不打开 Xcode 的情况下构建代码,即使只打开一次。

品牌推广UI、构建设置和功能

用户界面 应用程序图标和其他图标 iTunes 艺术作品 构建设置 应用名称 包标识符 配置文件 代码签名身份 功能性 品牌特定 URL(登录、注销、资源获取等...)

使用终端

Branding.sh

   #Author: Durai Amuthan(h.duraiamuthan@gmail.com)
#This is to achieve multiple branding of an ios app by configuring the variables below

#************ Configuring the brand starts ************

#Directory path where .xcworkspace or .xcodeproj exists
PathOfProjectDirectory=/Users/Shared/Jenkins/Documents/JenkinsTestNuu/New/

#Path where info.plist exists
PathOfInfoPlist=$PathOfProjectDirectory/XxYyZz

#Path to icons where new iTunesArtwork and application icon exixts
#Note: Make sure proper naming conventions of file has been followed
PathOfNewIcons=/Users/Shared/Jenkins/Documents/icons-two

#Path to asset resource where you have kept your application icon.
PathOfAppIconSet=$PathOfProjectDirectory/XxYyZz/Icon.xcassets/AppIcon.appiconset

#Path where do you want the .app file has to be kept
PathToApp=/Users/Shared/Jenkins/Documents/JenkinsTestNuu/app

#Path where do you want the .ipa file has to kept
PathToIpa=/Users/Shared/Jenkins/Documents/JenkinsTestNuu/ipa

#Cocoapods project or project that involves more than one modules are scheme based
isWorkspaceBased=true

#Path of the Project (.xcodeproj) - applicable for workspace(.xcworkspace) based project
PathofProjectFile=$PathOfProjectDirectory/XxYyZz.xcodeproj

#Path of the Workspace (.xcworkspace)
PathofWorkspaceFile=$PathOfProjectDirectory/XxYyZz.xcworkspace

#Name of the target - applicable only for non-workspace(.xcodeproj)  based projects
Target=XxYyZz

#Scheme of the iOS app
Scheme=XxYyZz

#To ascertain Cocoapods has been used or not
isCocoaPodsBased=true

#Configuration of the app (Debug -(Development) or Release(Adhoc or Distribution))
Config=Release

#For giving access to signing idetity found in KeyChain
LoginKeychainPath=/Users/Shared/Jenkins/Library/Keychains/login.keychain
LoginKeyChainPassword=xxyyzz

#Name of the code signing identity.You can find the name in Keychain or xcode build setting
CodeSigningIdentity='iPhone Distribution: Xx Yy Zz Limited (3Z5MHUYJ2L)'

#Path of the provisioning profile
PathToMobileProvision=/Users/Shared/Jenkins/Desktop/BrandingTest.mobileprovision

#UUID value found inside Provisioning profile has to be given
#Do not forget to install provisiong profile in the system
ProvisioningProfileIdentity=6e6506e9-8233-4886-9084-zf21e8f8bbae

#Bundle identifier of the app
BundleIdentifier=com.xxyy.zz

#AppVersion of the app
AppVersion=2.2.2

#App Name
Appname=Two

#************ Configuring the brand ends ************

#** Creatting the build based on configuration starts **

cd $PathOfInfoPlist
echo "****************** Setting App Name ******************"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $Appname" info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $Appname" info.plist
echo "app name has been set as $Appname"

cd $PathOfProjectDirectory
echo "****************** Setting AppVersion ******************"
/usr/bin/agvtool new-marketing-AppVersion $AppVersion
/usr/bin/agvtool new-AppVersion -all $AppVersion

echo "****************** Changing app icons & iTunes Artwork ******************"
cp -R $PathOfNewIcons/*.png $PathOfAppIconSet
echo "App icons has been changed at $PathOfNewIcons"
cp -R $PathOfNewIcons/iTunesArtwork@2x $PathOfProjectDirectory/XxYyZz
cp -R $PathOfNewIcons/iTunesArtwork $PathOfProjectDirectory/XxYyZz
echo "iTunesArtwork has been changed at $PathOfProjectDirectory"

#Unlock login keychain
security unlock-keychain -p $LoginKeyChainPassword $LoginKeychainPath
if $isCocoaPodsBased == 'true'
then
echo "****************** Installing Cocoapods **********************"
/usr/local/bin/pod install
echo "Cocoapods has been installed"
fi

echo "****************** Creating .app ******************"
if $isWorkspaceBased == 'true'
then
/usr/bin/xcodebuild -scheme $Scheme -workspace $PathofWorkspaceFile -configuration $Config clean build CONFIGURATION_BUILD_DIR=$PathToApp "CODE_SIGN_IDENTITY=$CodeSigningIdentity" "PRODUCT_BUNDLE_IDENTIFIER=$BundleIdentifier" "PROVISIONING_PROFILE=$ProvisioningProfileIdentity"
else
/usr/bin/xcodebuild -target $Target -project $PathofProjectFile -configuration $Config clean build CONFIGURATION_BUILD_DIR=$PathToApp "CODE_SIGN_IDENTITY=$CodeSigningIdentity" "PRODUCT_BUNDLE_IDENTIFIER=$BundleIdentifier" "PROVISIONING_PROFILE=$ProvisioningProfileIdentity"
fi
echo ".app has been generated at $PathToApp"

echo "****************** Creating .ipa *******************"
/usr/bin/xcrun -sdk iphoneos PackageApplication -v $PathToApp/XxYyZz.app -o $PathToIpa/$Appname.ipa --embed $PathToMobileProvision --sign "$CodeSigningIdentity"
echo "$Appname.ipa has been generated at $PathToIpa"

#** Creatting the build based on configuration ends **

该文件具有自我描述性,您可以轻松理解。 只需在文件中配置变量的值并像下面这样调用它

sh Branding.sh

仅供参考:

如果您还想更改 App Icon 和 iTunesArtwork 之外的其他图标 使用cp 命令例如

cp path/to/source path/to/destination

要了解更多信息,请cp man

使用上述文件,您可以为 UI 和构建设置进行品牌推广

对于功能性品牌,您必须保留

品牌特定网址

与品牌相关的其他输入

在单独的 plist 文件中,以便在构建应用程序时也可以根据各自的品牌进行更改

在编码方面,您可以自定义您的应用程序以像这样从 plist 中读取值

函数定义:

func getPlistFile()->Dictionary<String,AnyObject>? 
        var dictPlistFile:Dictionary<String,AnyObject>?
        if let path = NSBundle.mainBundle().pathForResource("plistfile", ofType: "plist") 
            if let dictValue = NSDictionary(contentsOfFile: path) as? Dictionary<String, AnyObject> 
                dictPlistFile=dictValue
            
        
        return dictPlistFile
    

函数调用:

var Value=getPlistFile()?["Key"]

您可以在构建应用程序时使用 PlistBuddy 根据品牌更改键的值

这里是语法

/usr/libexec/PlistBuddy -c "Set :Key Value" plistfile.plist

使用 Jenkins

我们可以在jenkins中有效地重用这里的shell脚本

1.您必须使用 Add Parameter 参数化 jenkins 中的 shell 脚本中的所有变量...就像下面的屏幕截图中我为这样的一个变量所做的那样你必须为所有其他人做这件事

2.在Build Step

中选择Execute shell

3.复制根据配置创建构建开始根据配置创建构建结束之间的脚本并将其粘贴到执行壳牌

注意:

资源规则

在通过非xcode接口构建和打包应用程序时,某些版本的Xcode的ResourceRules存在一个已知错误。

因此,它必须运行一次才能在 xcode 中停用对 资源规则 路径的验证。资源规则路径是已弃用的功能,并且苹果不接受带有资源规则的应用程序,但是如果我们在不使用 Xcode 的情况下构建应用程序,则会出现验证错误说资源规则尚未找到,以反驳我们必须只运行一次脚本.

xcode_fix_PackageApplicationResourceRules.sh

#!/bin/sh
# A script to patch xcrun PackageInstallation so that it doesn't use the deprecated --resource-rules
# See "Do not use the --resource-rules flag or ResourceRules.plist. They have been obsoleted and will be rejected."
#   under https://developer.apple.com/library/mac/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG205
# Reported as Apple bug #19384243
# 
# should be run as a user who can modify the PackageApplication file

xcodedir=$1

function usage 
        # FIXME we cannot parse args properly because 2 are optional...
        echo "USAGE: $0 xcodedir"
        echo "  xcodedir: an install dir like /Application/Xcode6.1.1.app"


if [[ $# -ne 1 ]]; then
        echo "ERROR: invalid number of arguments"
        usage
        exit -1 
fi

pi="$xcodedir/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication"
piorig="$piOrig"

if [[ ! -f "$pi" ]]; then
    echo "$pi file not found. Invalid argument ?"
    usage
    exit -1
fi

grep resource-rules "$pi" 
if [[ $? -ne 0 ]]; then
    echo "PackageApplication doesn't use resource-rules. Skipping"
    exit 0
fi

if [[ -f "$piorig" ]]; then
    echo "Backup file $piorig already exist. Aborting"
    exit -1
fi

perl  -p -i'Orig' -e 'BEGINundef $/; s/,resource-rules(.*sign).*ResourceRules.plist"/$1/smg' "$pi" 
echo $?

解锁钥匙串

每当您在终端中运行 Branding.sh 时,它都会提示用户名和密码作为其访问 系统钥匙串

每当您在 jenkins 中运行作业时,您都会收到“不允许用户交互”错误

所以要解决这个问题,您必须按照以下步骤操作

打开钥匙串访问 右键单击私钥 选择“获取信息” 选择“访问控制”选项卡 点击“允许所有应用程序访问此项目” 点击“保存更改” 输入您的密码

配置文件

如果您收到“未找到匹配的配置文件”,请确保您已双击并通过 Xcode 安装它。

安装后,您会在 ~/Library/MobileDevice/Provisioning Profiles/

中看到 UUID.mobileprovision

此 UUID 是移动配置中的值,表示已安装配置文件。

希望对你有帮助

【讨论】:

感谢详细的回答帮了我很多【参考方案2】:

您需要在构建项目之前运行 pod install,以便在 Jenkins 工作区中的 Podfile 中指定 CocoaPods fetches the Pods。

【讨论】:

是否有必要在每次需要构建时都运行它...因为这可能需要更多时间。

以上是关于xcodebuild 不会编译项目,除非它至少使用 Xcode 打开一次用于 cocoapods 集成项目的主要内容,如果未能解决你的问题,请参考以下文章

来自命令行的 xcodebuild:文件的编译标志

Xcode 7.2 使用 xcodebuild 构建项目失败

Delphi DLL Project在自定义BPL中找不到单元,除非“Link with Runtime Packages”为True

Travis-CI 在我的项目中使用 xcodebuild 构建/链接问题

Xcode build - 停留在编译 Swift 源文件

通过 xcodebuild 命令更改目标属性