shell 如何在Xcode 10脚本构建阶段使用文件列表(.xcfilelist)?

nbysray5  于 2022-12-27  发布在  Shell
关注(0)|答案(2)|浏览(192)

从Xcode 10开始,构建脚本阶段可以使用文件列表(.xcfilelist)而不是直接指定输入/输出文件。这些文件似乎支持注解(WWDC示例在顶部显示命令行注解),空行(也在示例中),否则每行需要一个文件路径。如果这些文件包含生成设置(例如$(SRCROOT)),则在调用脚本之前展开这些文件,就像直接将文件路径作为输入/输出文件时展开这些文件一样。
这听起来像是一个很棒的特性,但是在实际的脚本中如何使用这些文件列表呢?
当直接指定文件时,您有shell变量SCRIPT_INPUT_FILE_COUNTSCRIPT_OUTPUT_FILE_COUNT,然后每个输入/输出文件都有一个变量,命名为SCRIPT_INPUT_FILE_#SCRIPT_OUTPUT_FILE_#,其中#用于递增计数。假设您有相同数量的输入/输出文件,此脚本将打印所有文件:

#!/bin/sh
: $((i=0))
while [ $i -lt "$SCRIPT_INPUT_FILE_COUNT" ]
do
    eval fileIn="\$SCRIPT_INPUT_FILE_${i}"
    eval fileOut="\$SCRIPT_OUTPUT_FILE_${i}"
    echo "$fileIn  -->  $fileOut"
    : $((i=i+1))
done

这是一个干净的POSIX兼容的shell脚本,是的,当需要bash时,你可以使它更好,但是上面的代码应该适用于每一个sh兼容的shell(当使用#!/bin/sh而不是#!/bin/bash时,它也承诺)。
但是,当使用文件列表时,SCRIPT_INPUT_FILE_COUNT为0。相反,您得到的是SCRIPT_INPUT_FILE_LIST_COUNTSCRIPT_OUTPUT_FILE_LIST_COUNT,以及变量SCRIPT_INPUT_FILE_LIST_#SCRIPT_OUTPUT_FILE_LIST_#,它们包含预处理文件列表的路径,其中所有注解和空行都已删除,所有构建设置都已展开。
现在,我该如何在我的脚本中使用这些文件列表呢?上面的小示例脚本如何在Xcode中使用文件列表产生相同的输出呢?我并不擅长shell脚本,我正在寻找一个干净的解决方案,除了sh之外,不需要任何其他脚本解释器。

zhte4eai

zhte4eai1#

我不知道有什么方法可以在shellscript中访问文件列表本身。然而,文件列表的概念是,无论文件有多少,理想情况下都有一个文件列表。因此,我通常将其硬编码为与xcode相同的值。它有点重复,但不是很多:

set -e
while read file; do
    EXPANDED=`eval echo "$file"`
    echo "do something with $EXPANDED"
done <"${SRCROOT}/path/to/files.xcfileslist"

作为read设备的一个副作用,我们去掉了空白,并做了一些其他的光线处理。如果你对如何实现这一点很感兴趣,请参见this SO answer
我相信大多数(所有?)构建设置都作为环境变量导出到脚本中,所以通过用eval来计算它们,我们在这里扩展了它们。
使用eval打开了恶意文件列表执行代码的可能性。而且它可能与您正在执行的构建脚本位于同一个位置,所以我不确定这是一个非常实际的问题。其他shell有更安全的方法来处理这个问题,但我不知道vanilla sh和默认macOS有什么方法。

qacovj5a

qacovj5a2#

这将动态地构造SCRIPT_INPUT_FILE_LIST_0SCRIPT_INPUT_FILE_LIST_1等值,并从Xcode传递给脚本的环境变量中访问它们。如果您不想打印xcfilelist中的每一行,请交换出echo "${file_path}"行。

#!/usr/bin/env bash

for index in $(seq $SCRIPT_INPUT_FILE_LIST_COUNT); do
    # 1 => `SCRIPT_INPUT_FILE_LIST_0`
    filelist=SCRIPT_INPUT_FILE_LIST_$((index-1))
    # `SCRIPT_INPUT_FILE_LIST_0` => value in $SCRIPT_INPUT_FILE_LIST_0
    filelist_path=${!filelist}

    while read -r file_path; do
        echo "${file_path}"
    done <$filelist_path
done

相关问题