xcode 用go build为iPhone模拟器构建静态库

c3frrgcw  于 2023-01-18  发布在  Go
关注(0)|答案(1)|浏览(201)

我正在我的iOS项目中使用以下内容构建一个C存档:
GOOS=ios GOARCH=arm64 CGO_ENABLED=1 SDK=iphonesimulator CGO_CFLAGS="-fembed-bitcode" CC=密码/clangwrap.sh go build -buildmode=c-archive -o libuplink.a
Clangwrap.sh 看起来像这样

#!/bin/sh

# go/clangwrap.sh

SDK_PATH=`xcrun --sdk $SDK --show-sdk-path`
CLANG=`xcrun --sdk $SDK --find clang`

if [ "$GOARCH" == "amd64" ]; then
    CARCH="x86_64"
elif [ "$GOARCH" == "arm64" ]; then
    CARCH="arm64"
fi

exec $CLANG -arch $CARCH -isysroot $SDK_PATH -mios-version-min=10.0 "$@"

但是,当我在XCode中链接它并尝试使用模拟器运行时,我只能在设备本身上运行它:

building for iOS Simulator, but linking in object file built for iOS ... for architecture arm64

如何将Swift项目中使用的静态库的go build模拟器作为目标?

bmvo0sr5

bmvo0sr51#

要求

  • 为iPhone模拟器创建静态库
  • 使用Apple Silicon代替Intel模拟器
  • 能够指定最低版本
    TL;DR

如果选择模拟器作为运行目标,可以执行类似于Xcode的操作。
所以基本上使用类似-target arm64-apple-ios16.2-simulator的东西代替-arch arm64,也可以省略-mios-version-min=10.0,因为实际的最小版本是在-target中编码的(例如16.2),它优先(无论如何,模拟器的正确选项应该是-miphonesimulator-version-min)。
然后作为CGO_LDFLAGS,还指定-target选项加上-syslibroot以及SDK的路径。
您的构建脚本做了一些调整,可能如下所示:
这将模拟器指定为目标,最低版本为15。

版本号.sh

#!/bin/sh
export GOOS=ios
export GOARCH=arm64
export CGO_ENABLED=1
export SDK=iphonesimulator
export CGO_CFLAGS="-fembed-bitcode"
export MIN_VERSION=15

. ./target.sh

export CGO_LDFLAGS="-target ${TARGET} -syslibroot \"${SDK_PATH}\""
CC="$(pwd)/clangwrap.sh"
export CC

go build -buildmode=c-archive -o libuplink.a

目标.sh

#!/bin/sh

SDK_PATH=$(xcrun --sdk "$SDK" --show-sdk-path)
export SDK_PATH

if [ "$GOARCH" = "amd64" ]; then
    CARCH="x86_64"
elif [ "$GOARCH" = "arm64" ]; then
    CARCH="arm64"
fi

if [ "$SDK" = "iphoneos" ]; then
  export TARGET="$CARCH-apple-ios$MIN_VERSION"
elif [ "$SDK" = "iphonesimulator" ]; then
  export TARGET="$CARCH-apple-ios$MIN_VERSION-simulator"
fi

** Package 音.sh**

clangwrap.sh可简化为:

#!/bin/zsh

CLANG=$(xcrun --sdk "$SDK" --find clang)

exec "$CLANG" -target "$TARGET" -isysroot "$SDK_PATH" "$@"

详细信息
不同的SDK

必须为iOS设备和iPhone模拟器指定不同的SDK。您可以在/Applications/Xcode.app/Contents/Developer/Platforms下Xcode支持的其他平台旁边找到它们。例如,在Xcode 14.2中,iPhoneOS平台与iPhoneOS16.2.sdk以及iPhoneSimulator平台与iPhoneSimulator16.2.sdk
在苹果开发者论坛上,有一位苹果员工发了这样一个有趣的帖子:https://developer.apple.com/forums/thread/673387#662260022
要检查生成的静态库以显示load命令,可以调用:

otool -l libuplink.a

生成的用于Apple Silicon模拟器的静态库应显示如下内容:

...
Load command 1
      cmd LC_BUILD_VERSION
  cmdsize 24
 platform 7
    minos 15.0
      sdk 16.2
...

注:platform 7表示模拟器,minos表示最低部署目标,sdk表示实际使用的SDK版本。
请参见包含文件loader.h中的以下部分:

/* Known values for the above platform field. */
#define PLATFORM_UNKNOWN 0
#define PLATFORM_ANY 0xFFFFFF
#define PLATFORM_MACOS 1
#define PLATFORM_IOS 2
#define PLATFORM_TVOS 3
#define PLATFORM_WATCHOS 4
#define PLATFORM_BRIDGEOS 5
#define PLATFORM_MACCATALYST 6
#define PLATFORM_IOSSIMULATOR 7
#define PLATFORM_TVOSSIMULATOR 8
#define PLATFORM_WATCHOSSIMULATOR 9
#define PLATFORM_DRIVERKIT 10

您可以在您的系统上查看它们,如下所示:

cat `xcrun --sdk iphonesimulator --show-sdk-path`/usr/include/mach-o/loader.h

为iPhone设备构建

要为iPhone SDK构建静态库,您需要更改以下内容:

export SDK=iphoneos

在上面的build.sh脚本中。
如果您尝试在模拟器中使用这个库,它将失败,并显示消息building for iOS Simulator, but linking in object file built for iOS, file 'libuplink.a' for architecture arm64
otool -l的输出为:

...
Load command 1
      cmd LC_BUILD_VERSION
  cmdsize 24
 platform 2
    minos 15.0
      sdk 16.2
   ntools 0
...

注:Platform 2代表PLATFORM_IOS,不代表模拟器。
这当然会在设备上完美运行。

相关问题