2010-09-16 94 views
22

显然这个文件被缓存了,所以只有当它被修改时才会生成。我有环境变量设置为增加我的版本号,等等,并独立于plist更新它们(实际上在项目构建设置中)。是否有脚本可以用作强制Info.plist更新的脚本构建阶段?其他一些方便的方法?如何在每次构建项目时强制Xcode在我的项目中重建Info.plist文件?

+0

我有这个完全相同的问题。我试过触摸它并将其添加为构建脚本的输出。只有Clean和Build才能刷新它。我已经开始赏金了。 – 2011-02-22 19:30:58

回答

11

选择“编辑计划”建立关于选项卡上,然后从左侧的控件中选择“Build”。

rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}" 

这将删除:

然后,添加一个预操作步骤,确保有问题的方案下拉了“从提供构建设置”,然后添加到下面的编辑窗口,这是选择缓存版本Info.plist,导致XCode在您每次构建时重建它。

+0

不要忘记引号:rm“$ {CONFIGURATION_BUILD_DIR}/$ {INFOPLIST_PATH}” – 2014-02-07 20:29:20

+0

谢谢 - 我已经更新了答案 – LeeH 2014-02-08 15:26:00

+3

它在xCode 8.2中不再有效。1 – hsafarya 2016-12-29 13:50:07

12

您可以尝试使用touch命令来更新时间戳,我认为这是Xcode用来确定是否应该重建的时间戳。

$ touch Info.plist 
+1

我试过从Xcode里面触摸,但它什么也没做。实际上对Info.plist进行更改是实现更新的唯一方法。我会尝试从命令行看看它是否有效 – TraxusIV 2010-09-16 21:31:12

+0

好吧,只需“触摸Info.plist”就可以添加Run Script构建阶段,它会在构建时自动更新,但仅限于其他构建。 – TraxusIV 2010-09-16 21:36:05

+0

运行脚本构建步骤是第一个执行? – bosmacs 2010-09-17 13:53:40

1

有目标的获取信息窗口的“生成”选项卡的选项,跌幅在标有“预处理Info.plist文件”,你可以检查“包装”。我相信会更新每个版本的文件。

+0

nope,no-go。它也导致了错误,因为我的版权字符串中有一个URL,并且c预处理器显然不知道如何处理http://中的//。 – TraxusIV 2010-09-16 21:30:00

9

执行此操作的一种方法是创建Run Script构建阶段,以从Info.plist.template文件生成Info.plist,然后在创建包之后生成rm Info.plist。来自评论Dave DeLong的想法发表在他的博客here

如果它的缓存非常严重(即,即使您没有在文件历史记录中打开Info.plist,也要进行缓存),您也可以在此脚本中使用rm缓存版本。

+0

谢谢你来拯救我。这似乎是完美的。 – 2011-03-01 18:50:51

0

确保你也刷新你的plist视图。
在Xcode中查看plist时,只需单击plist中根元素旁边的显示三角形(Information Property List)。然后再次单击以展开它。
您会看到值已刷新。我正在运行一个类似的脚本,并认为它只是间歇性地工作,直到我意识到plist视图根本不令人耳目一新。

5

在Xcode 4中,您可以使用预生成操作来触摸信息plist。

注意:这与运行脚本构建阶段不同。在Xcode检查信息plist之前发生预生成操作,在Xcode已经检查信息plist(这是为什么它每隔一次只能工作)之后似乎发生了运行脚本生成阶段。

  1. 去编辑方案>生成>预动作
  2. 点击“+”按钮,选择“新建运行脚本行动”
  3. 选择你的目标在下拉列表
  4. 了“从提供构建设置”
  5. 在脚本框中添加touch "${SRCROOT}/${INFOPLIST_FILE}"
+1

此预构建操作不适用于我。它仍然以某种方式“缓存”Info.plist。例如如果我做了一个干净的构建(不管这个建议),并使用PlistBuddy从源appTarget-Info.plist或build-dir/Info.plist中提取版本信息,我就能得到我所期望的,但如果我改变了项目中的版本信息在重新构建之前没有进行清理,我得到旧值...即使执行手动PlistBuddy -c打印显示上述两个文件都具有我想要的新值。 – 2012-11-27 22:50:05

0

另一种方法是创建仅具有构建阶段的“聚合”目标。用它来触摸Info.plist文件。使该目标成为构建应用的目标的依赖关系。

因为它是一个独立的目标和你的应用程序目标的依赖关系,所以它会在你的应用程序目标的Info.plist文件被检查之前建立。 (如别处所述,在Info.plist文件的修改时间已被检查后,应用目标本身的构建阶段发生得太迟。)

13

我也自动设置了我的版本号。我创建了一个运行脚本构建阶段。 关键是要更新Info.plist的目标生成目录副本不能建立目录 一。您还需要在复制捆绑阶段之后拥有您的运行脚本。可以直接编辑0​​包文件,因为在代码签名之前。你不想生成重新发明轮子的文件。

这里是我的脚本:

# ---------------------------- IMPORTANT ---------------------------- 
# You must set GITHash to something like 'Set by build script' in the file 
# file '<Project Name>-Info.plist' in the 'Supporting Files' group 
# ------------------------------------------------------------------- 
# 
# Get the version number from the tag in git and the number of commits as the build number 
# 
appVersion=$(git describe --long | cut -f 1 -d "-") 
appBuild=$(git describe --long | cut -f 2 -d "-") 
gitHash=$(git describe --long | cut -f 3 -d "-") 
echo "From GIT Version = $appVersion Build = $appBuild" 

# 
# Set the version info in plist file 
# 
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $appVersion" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}" 
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $appBuild" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}" 
/usr/libexec/PlistBuddy -c "Set :GITHash $gitHash" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}" 
echo "Updated ${TARGET_BUILD_DIR}/${INFOPLIST_PATH}" 

仅供参考我还自动设置版本,并用下面的代码

NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; 
NSString *appDisplayName = infoDictionary[@"CFBundleDisplayName"]; 
NSString *majorVersion = infoDictionary[@"CFBundleShortVersionString"]; 
NSString *minorVersion = infoDictionary[@"CFBundleVersion"]; 

self.appDescription.text = [NSString stringWithFormat:@"Dirty Dog Software\n%@\nVersion: %@(%@)", 
         appDisplayName, majorVersion, minorVersion];       
0

对于那些一直在努力实现自动版本控制的项目,我创建了一个macOS GitHub project,演示如何以非常简单直接的方式实现它,这要感谢@GayleDDS和Daniel Farrelly及其博客的想法版本控制和我自己的一些实现。我认为你可以毫无麻烦地将它翻译成其他平台上的项目。

这里有一个关于如何将它复制到项目中的小指南(Xcode 8)。

  1. 为了减少发生这种错误的几率,请确保您已预先将所有目标添加到您的项目中。
  2. 转到菜单文件>新建文件...,然后向下滚动,然后选择配置设置文件
  3. 将它命名为BuildNumber,不要忘了这个配置文件添加到你想要的所有目标保持同步; CURRENT_PROJECT_VERSION = 1:保存该文件
  4. 你应该可以看到一个名为BuildNumber.xcconfig在您的项目显示
  5. 添加到该文件下面的文字前,通过点击相应的复选框,这样做。如果你愿意,你可以从另一个号码开始。这将会是你的内部版本号,每次构建时都会增加。 请不要更改变量的名称,尽管
  6. 如果你有一个以上的目标,添加下面的脚本由导航建项目第一目标>目标>构建阶段
  7. 导航到菜单编辑>添加构建阶段>添加运行脚本阶段
  8. A 运行脚本阶段应该已经添加到您的目标;所以拖动它直到目标依赖关系(这个细节很重要!)。
  9. 现在到了有趣的部分,我将线几乎行解释脚本:

开始在脚本的第一行创建于PlistBuddy路径:

plistbuddy="/usr/libexec/PlistBuddy" 

添加行2读取配置文件,然后读取5.

OLD_VERSION=`cat "$SRCROOT/BuildNumber.xcconfig" | awk '/CURRENT_PROJECT_VERSION/ { print $3 }'` 

3-11线路设置NEW_VERSION与被撞开您在步骤设置了CURRENT_PROJECT_VERSION变量然后用新的内部版本号保存配置文件;其余线路的营销版本和内部版本号保存到的plist:

NEW_VERSION=`cat "$SRCROOT/BuildNumber.xcconfig" | awk '/CURRENT_PROJECT_VERSION/ { print $3 + 1 }'` 
sed -i '' "s/CURRENT_PROJECT_VERSION = .*/CURRENT_PROJECT_VERSION = $NEW_VERSION/" "$SRCROOT/BuildNumber.xcconfig" 
CURRENT_PROJECT_VERSION=$NEW_VERSION 
BUILD_STR="Build $NEW_VERSION" 
COPYRIGHT_STR="© 2017 MyCompany.net" 
APP_VERSION_STR="1.3.5" 
$plistbuddy -c "Set :CFBundleShortVersionString $APP_VERSION_STR" "${SRCROOT}/$TARGETNAME/Info.plist" 
$plistbuddy -c "Set :CFBundleVersion $BUILD_STR" "${SRCROOT}/$EXECUTABLE_NAME/Info.plist" 
$plistbuddy -c "Set :NSHumanReadableCopyright $COPYRIGHT_STR" "$INFOPLIST_FILE" 

我还显示,8-11行如何使用Xcode中设置其脚本不同的环境变量。您可以添加额外的行来编辑其他目标的info.plist,然后保持主应用程序和助手的版本同步。去GitHub,下载该项目并使用它,然后适应您的需求。使用Xcode进行快速自动版本控制。

0

和Xcode 8.3.2

由@LeeH答案从2013年开始我已经提出了两种解决方案对我来说,重建的Info.plist启发工作。

解决方案1:最简单,最优雅的

最简单的办法是强制的Xcode通过读您的自定义变量触摸你的目标Info.plist

添加构建阶段,见下面的截图(原为screenshotted解决),以及刚加入这一行:

touch $INFOPLIST_FILE 

这就是全部!现在Xcode应该强制将自定义变量重新加载到Info.plist文件中。

此解决方案与@lukelutman建议的相同,但使用Build阶段。预执行脚本不适用于我。

解决方案2:更复杂和哈克

另一种解决方案是删除在build目录的缓存Info.plist

我写了这个超级简单的小bash脚本

#!/bin/bash 
info_plist="$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME.app/Info.plist" 
echo "Removing Info.plist from build dir in order to force rebuild of it and reading of correct xcconfig variables, plist path $info_plist" 
rm "$info_plist" 

然后我救了它,并把它称为从目标构建阶段。我把它作为第一个构建阶段。

enter image description here

背景:

我有三种配置:ConfigAlphaAppStore和我使用的通用连接,推送通知和其他工作人员需要使用的应享权利的文件。但我不想拥有三个授权文件,每个配置文件一个。

我的项目已经非常依赖配置文件(.xcconfig)。我实际上使用自定义配置变量设置了授权文件(MyAppsProductName.entitlements)。

但我想读取相同的配置变量运行时,我想我可以做到这一点,如果他们将被添加到我的目标Info.plist。哪些工作!

但我注意到,当我更改了我的.xcconfig文件中的值时,Info.plist文件没有更改值。我注意到,如果我执行了干净的构建,则Info.plist中的值根据.xcconfig文件中的值得到更新。 Xcode确实缓存了Info.plist文件。

所以上面的这些解决方案解决了这个问题。希望能帮助到你! :)

讨论

我如果解决方案2有任何优势解决方案1 ​​ ...可能不是没有想法?任何人输入?

相关问题