Xcode 构建阶段输入文件夹

fab*_*abb 4 xcode ios

我有一个自定义的“运行脚本”构建阶段,它根据文件夹中包含的文件生成一些源文件A。构建阶段在“编译源”构建阶段之前执行。随着源文件的生成,我想避免每次运行时都触发完整的项目重建,我想利用“输入文件”和“输出文件”部分,如本博客文章所述

不幸的是,该文件夹A是文件夹而不是文件。当我提供文件夹路径A作为“输入文件”时,当文件夹中的任何内容都没有更改时,构建阶段不会正确执行。当我重命名某些文件时,构建阶段也会正确执行。但是当更改文件夹内文件中的某些内容时A,不会执行构建阶段

我尝试同时提供不带 的文件夹名称*,也尝试提供***最后。

当给定输入文件夹中的任何文件发生更改(添加、删除、内容修改)时,如何执行构建阶段?

Sta*_*ich 5

有两个极端:喜欢将 Xcode 用于所有事情的人和倾向于避免使用 Xcode 的人,除了只能通过它完成的工作。这是一个不喜欢 Xcode 的所有非 IDE 功能的开发人员的回答:我不知道您确切问题的答案,我什至不想知道,因为我尽量避免将 Xcode 用于超出其范围的任何事情默认能力。

就我得到你的问题而言,你有一些 IN 的东西,你想对它做一些处理,这样处理就会产生一些 OUT 的东西。让我们称之为Subproject:包含 IN、OUT 和处理的东西:IN -> OUT。并且您希望此处理是增量的:如果已经完成,则不要重复相同的工作,即如果 OUT 存在且 IN 未修改,则不要执行处理,IN -> OUT因为结果已经存在。

对于这种任务,我使用 Make(任何其他构建系统都可以,例如 Ninja),它正是完成这项工作的工具:您描述您需要什么,描述您拥有什么以及转换过程,它可以工作并提供你增量处理。

相反,在你运行脚本阶段在Xcode的构建阶段修修补补的你可以把cd Subproject; make和与您的委托一切IN -> OUT处理通过写适当的制作Makefile。Xcode 中唯一保留的是 Run Script 阶段,该阶段将构建规则委托给 Make。

我创建了解决您的问题的示例,并演示了将基于 Make 的子项目集成到 Xcode 项目中的示例:Xcode 和 Make

??? README.md
??? Subproject
?   ??? Generated-Code
?   ?   ??? file1.out
?   ?   ??? file2.out
?   ?   ??? file3.out
?   ??? Makefile
?   ??? Source
?       ??? file1.in
?       ??? file2.in
?       ??? file3.in
??? Xcode-and-Make
    ??? Xcode-and-Make
    ?   ??? main.m
    ??? Xcode-and-Make.xcodeproj
        ??? project.pbxproj
Run Code Online (Sandbox Code Playgroud)

自定义的东西被隔离在子项目文件夹中。此文件夹包含在 Xcode 项目中:Generated-Code .out 文件包含在项目的主要目标中,*.in 文件不包含在内,Makefile 也不包含在内。

在项目的运行脚本阶段,只调用 Make:

cd ../Subproject
make
Run Code Online (Sandbox Code Playgroud)

所有的Source/*.in -> Generated-Code/*.out处理都是在 Makefile 中完成的,它是这样写的:

IN_PATH=./Source
IN_FILES=$(wildcard $(IN_PATH)/*.in)

OUT_PATH=./Generated-Code

OUT_FILES := $(patsubst %, $(OUT_PATH)/%, $(notdir $(IN_FILES)))
OUT_FILES := $(patsubst %.in, %.out, $(OUT_FILES))

default: generate

generate: $(OUT_FILES)

clean:
    rm -rf $(OUT_PATH)

$(OUT_PATH)/%.out: $(OUT_PATH) $(IN_PATH)/%.in
    cp -v $(IN_PATH)/$*.in $(OUT_PATH)/$*.out

$(OUT_PATH):
    mkdir -p $(OUT_PATH)
Run Code Online (Sandbox Code Playgroud)

如果您是 Make 的新手,所有这些表示法一开始可能会令人困惑,但在阅读有关 Make 的教程一天后,您将对 Make 的工作原理有基本的了解。

Makefile是为了给你增量处理而编写的:cp只是简单的演示操作,复制*.in*.out- 在实际应用程序中,它可以是编译器或其他一些工具。

Subprojectmake第一次在文件夹中写入时,您会看到:

Subproject$ make
mkdir -p ./Generated-Code
cp -v ./Source/file1.in ./Generated-Code/file1.out
./Source/file1.in -> ./Generated-Code/file1.out
cp -v ./Source/file2.in ./Generated-Code/file2.out
./Source/file2.in -> ./Generated-Code/file2.out
cp -v ./Source/file3.in ./Generated-Code/file3.out
./Source/file3.in -> ./Generated-Code/file3.out
Run Code Online (Sandbox Code Playgroud)

但是在第二次运行时,您会得到:

Subproject$ make
make: Nothing to be done for `default'.
Run Code Online (Sandbox Code Playgroud)

那是因为 Make 很聪明地理解您没有对任何*.in文件进行任何修改,因此要Make再次执行其处理,您需要实际对*.in文件进行一些更改,而这正是您最初的问题所涉及的。

我认为示例项目是最好的展示,因此请随意决定这种偏离 Xcode 默认设置的做法是否会让您感到舒服,并随时询问您是否有任何其他问题。

免责声明:我已经使用 Make 来(几乎)所有涉及构建 Xcode 无法处理的东西的事情,所以我强烈建议您学习 Make 的基础知识:它可以是非常强大的构建脚本的工具,其中增量处理很适合有。

  • Scaly,我删除了我的答案中您评论为“描述和歧视人”的部分。我绝对不希望以这种方式阅读该部分,所以我希望现在它能得到更好的表述。对于技术部分,人们仍然可能会争辩说,拥有一个由 Git 控制的 Makefile 比在 Xcode 项目结构中执行相同的操作更易于维护。 (2认同)

Sob*_*man 1

我们可以使用该cksum命令来检查文件是否已更改,因此我们将能够运行该diff命令来检查更改。

因此,首先,我们需要列出要校验和的所有文件的列表并将其放入文件中:

find directory_to_search_in -type f -name "*.storyboard" -or -name "*.xib" > $FILE_PATHS
Run Code Online (Sandbox Code Playgroud)

然后我们检查是否曾经运行过这个脚本,如果是的话,我们将获得包含我们找到的文件的初始校验和的文件,下一步 - 我们创建当前文件校验和的新文件并比较它们为了改变。如果它们不相同 - 我们运行脚本。
如果此文件不存在 - 我们将创建它并运行您的脚本。此外,我们在一开始就添加了一个检查,以删除用于存储文件路径和当前文件校验和的文件,以防它们的构建被中断并且脚本没有正确结束,因为我们不需要这些文件徘徊,我们只需要它们来进行检查。这些文件将被删除。

结果如下:

if [ -f $FILE_PATHS ]; then
rm $FILE_PATHS
fi
if [ -f $rm $CURRENT_CHECKSUMS ]; then
rm $CURRENT_CHECKSUMS
fi


find App/Source/UI/ -type f -name "*.storyboard" -or -name "*.xib" > $FILE_PATHS

if [ ! -f $INITIAL_CHECKSUMS ]; then
while read file; do
cksum $file >> $INITIAL_CHECKSUMS
done < $FILE_PATHS

your_generate_script_function_call
else
while read file; do
cksum $file >> $CURRENT_CHECKSUMS
done < $FILE_PATHS
if ! diff $INITIAL_CHECKSUMS $CURRENT_CHECKSUMS > /dev/null ; then
your_generate_script_function_call
cat $CURRENT_CHECKSUMS > $INITIAL_CHECKSUMS
fi

rm $CURRENT_CHECKSUMS
fi

rm $FILE_PATHS
Run Code Online (Sandbox Code Playgroud)