我有一个自定义"运行脚本"构建阶段,根据文件夹A
中包含的文件生成一些源文件。构建阶段在"编译源"之前执行。建设阶段。在生成源文件时,我想避免每次运行时触发完整的项目重建,我想利用"输入文件"和"输出文件"部分,as described in this blog post。
不幸的是,文件夹A
是一个文件夹而不是文件。当我提供文件夹A
的路径为"输入文件"时,如果文件夹中没有任何内容发生更改,则无法正确执行构建阶段。当我重命名一些文件时,构建阶段也正确执行。 但是当更改文件夹A
内的文件中的内容时,不会执行构建阶段。
我尝试提供的文件夹名称不包含*
,最后也包含*
或**
。
当给定输入文件夹中的任何文件发生更改(添加,删除,修改内容)时,如何执行构建阶段?。
答案 0 :(得分:3)
有两个极端:喜欢使用Xcode的人和那些倾向于避免使用Xcode的人,除了只能通过它完成的工作。这是一个开发人员的答案,他不喜欢所有Xcode的非IDE功能:我不知道你的确切问题的答案,我甚至不想,因为我试图避免使用Xcode来超越它的任何东西默认功能。
就我的问题而言,你有一些你需要对它进行处理的东西,以便处理产生一些OUT的东西。我们称之为Subproject
:包含IN,OUT和处理的内容:IN -> OUT
。并且您希望此处理是增量的:如果已经完成,则不要重复相同的工作,即如果OUT在那里而IN未被修改则不执行处理IN -> OUT
因为结果已经存在。
对于这种任务,我使用Make(任何其他构建系统很好,例如Ninja),这正是完成这项工作的工具:你描述你需要的东西,描述你拥有的东西和转换过程,它可以工作并为您提供增量处理。
您可以通过编写正确的cd Subproject; make
来放置IN -> OUT
并将与Makefile
处理相关的所有内容委托给Make,而不是修改Xcode的“运行脚本”阶段的构建阶段。 Xcode中唯一剩下的就是Run Script阶段,它将你的构建规则的这个委托执行到Make。
我创建了一个示例来解决您的问题并演示了基于Make的子项目与Xcode项目的集成:Xcode and 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
自定义内容在Subproject文件夹中被隔离。此文件夹包含在Xcode项目中:Generated-Code .out文件包含在项目的主目标中,* .in文件不包含在内,Makefile也不包括在内。
在项目的“运行脚本”阶段,只能调用Make:
cd ../Subproject
make
所有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)
如果你是新手,那么所有这些符号一开始可能会让人感到困惑,但是在阅读了一天的教程之后,让你对Make如何运作有基本的了解。
编写此Makefile
是为了进行增量处理:cp
只是简单的演示操作,它将*.in
复制到*.out
- 在实际应用中它可以是编译器或其他一些工具。
在Subproject
文件夹内,您第一次看到make
时会看到:
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
但是在第二轮你会得到:
Subproject$ make
make: Nothing to be done for `default'.
那是因为Make很明白你没有对任何*.in
文件进行任何修改,所以要让Make
再次执行它的处理,你需要在{{1}中实际执行一些更改文件,这正是你原来的问题所在。
我认为示例项目是最好的展示,所以请随意决定是否偏离Xcode的默认设置会让您感到舒服,并随时询问您是否还有其他问题。
免责声明:我已经使用Make 2年(几乎)所有涉及构建Xcode无法处理的东西所以我强烈建议你学习Make的基础知识:它可以是构建脚本的非常强大的工具,其中增量处理很高兴。