今天看啥  ›  专栏  ›  知识小集

如何检测 iOS 应用程序是否使用 Swift?

知识小集  · 掘金  ·  · 2019-10-10 06:01
阅读 134

如何检测 iOS 应用程序是否使用 Swift?

原文链接

更多好文,请关注公众号 知识小集 (ID: zsxjtip)

关于 iOS 13.1 中对 Swift 的使用,可参考 Apple 在 iOS 13.1 中使用 Swift 开发的应用程序

朴素的方法是检查应用程序是否在其 Frameworks 文件夹中包含 Swift 库:libswiftCore.dyliblibswiftFoundation.dylib 等。

以下是 macOS 10.12.1 中的 MRT.app 的 Frameworks 文件夹的内容 /System/Library/CoreServices/MRT.app/Contents/Frameworks/

但是,这不是一个好方法,因为 iOS 和 macOS 在 /System/Library/PrivateFrameworks/Swift/ 中包含 Swift 库的私有副本。iOS 和 macOS 中的多个应用程序直接链接到这些系统库。

以下是 macOS 10.12.1 中的 PIPAgent.app 的 Frameworks 文件夹的内容 /System/Library/CoreServices/PIPAgent.app/Contents/Frameworks/

更好的方法是检查二进制文件是否链接到 Swift 库。可以通过命令行工具 otool 中使用 -L 选项轻松完成此操作:

-L 显示目标文件使用的共享库的名称和版本号,以及如果文件是共享库,则显示共享库 ID。

在 PIPAgent 应用程序上运行此命令时:

otool -L /System/Library/CoreServices/PIPAgent.app/Contents/MacOS/PIPAgent | grep swift
复制代码

您将获得以下输出:

/System/Library/PrivateFrameworks/Swift/libswiftAppKit.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCore.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCoreData.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCoreGraphics.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCoreImage.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftDarwin.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftDispatch.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftFoundation.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftIOKit.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftObjectiveC.dylib (compatibility version 1.0.0, current version 800.8.18)
复制代码

建立一个脚本

使用 otool 命令行工具,可以很容易地编写一个 bash 函数来判断文件是否是链接到 Swift 库的二进制文件:

#------------------------------------------------------------------------
# Function to check if a file (passed as argument $1) is using Swift
# It returns the number of occurrences of the string 'swift'
# from the output of otool
#------------------------------------------------------------------------
isFileUsingSwift ()
{
    otool -L $1 2>/dev/null | grep -o swift | wc -l
}
复制代码

如果文件是链接到 Swift 库的二进制文件,则 processFile bash 函数将文件作为参数并打印其路径:

#------------------------------------------------------------------------
# Function to process a file (passed as argument $1).
# It calls the function isFileUsingSwift() to determine
# if this is a binary using Swift and in this case
# print the path of this file.
#------------------------------------------------------------------------
processFile ()
{
    isFileUsingSwift=$( isFileUsingSwift $1 )
    if [ ${isFileUsingSwift} != 0 ]
    then
        # We found a binary using Swift
        echo "   $1"
    fi
}
复制代码

现在遍历文件夹的所有文件仅需一行:

find ${PATH_TO_CHECK} -type f -exec bash -c 'processFile "$0"' {} \;
复制代码

最终脚本

下面是一个完整的 bash 脚本,该脚本循环遍历一个文件夹的所有文件,并显示找到的所有使用 Swift 的二进制文件的路径。

#!/bin/bash
 
#---------------------------------------------------------------------
# Bash script that loops through all the files of a folder and
# print the paths of all the binaries found that use Swift
# Created by Alexandre Colucci on 01.11.2016
# https://blog.timac.org/2016/1101-apples-use-of-swift-in-ios-10-1-and-macos-10-12
#---------------------------------------------------------------------
 
 
#---------------------------------------------------------------------
# Force expand a wildcard pattern into the list of matching pathnames
#---------------------------------------------------------------------
shopt -s nullglob
 
#---------------------------------------------------------------------
# Function to print the usage
#---------------------------------------------------------------------
printUsage ()
{
    echo "Usage: detectSwift.sh PATH"
    echo "PATH: Folder to search for binaries using Swift"
    echo ""
    echo "Examples:"
    echo "  detectSwift.sh /System/Library"
    echo "  detectSwift.sh /System"
    echo "  detectSwift.sh /"
    echo ""
    echo "Note: run as root in order to avoid permission issues."
    echo ""
}
 
#---------------------------------------------------------------------
# Function to check if a file (passed as argument $1) is using Swift
# It returns the number of occurrences of the string 'swift'
# from the output of otool
#---------------------------------------------------------------------
isFileUsingSwift ()
{
    otool -L $1 2>/dev/null | grep -o swift | wc -l
}
 
#---------------------------------------------------------------------
# Function to process a file (passed as argument $1).
# It calls the function isFileUsingSwift() to determine
# if this is a binary using Swift and in this case
# print the path of this file.
#---------------------------------------------------------------------
processFile ()
{
    isFileUsingSwift=$( isFileUsingSwift $1 )
    if [ ${isFileUsingSwift} != 0 ]
    then
        # We found a binary using Swift
        echo "   $1"
    fi
}
 
#---------------------------------------------------------------------
# Check if the script was called with the expected usage
#---------------------------------------------------------------------
PARAMETER_NUMBER=$#
PARAMETER_REQUIRED=1
if [ $PARAMETER_NUMBER != $PARAMETER_REQUIRED ];
then
    printUsage
    exit 1
fi
 
 
#---------------------------------------------------------------------
# Get the folder path
#---------------------------------------------------------------------
PATH_TO_CHECK=$1
 
echo ""
echo "Start time:"
date
echo ""
echo "Apps using Swift in ${PATH_TO_CHECK}"
 
 
#---------------------------------------------------------------------
# Export the functions so that the subshell inherits them
#---------------------------------------------------------------------
export -f isFileUsingSwift
export -f processFile
 
#---------------------------------------------------------------------
# Find all the regular files in all subdirectories
# and call for each the function processFile()
#---------------------------------------------------------------------
 
find ${PATH_TO_CHECK} -type f -exec bash -c 'processFile "$0"' {} \;
 
 
#---------------------------------------------------------------------
# Finalizing
#---------------------------------------------------------------------
echo ""
echo "Completed at:"
date
echo ""
复制代码

运行脚本

该脚本确实很慢:对于每个常规文件,它将创建一个 subshell,分别调用otoolgrepwc

在 iOS 10.1 文件系统上运行此脚本大约需要 30 分钟。

对于 macOS 10.12.1,在 / 路径上运行脚本需要花费数十个小时。 我建议仅在 /System/Applications/usr 上运行此脚本。并行处理这 3 个文件夹大约需要 2 个小时。




原文地址:访问原文地址
快照地址: 访问文章快照