如何在Metal文件中导入Swift Package中的C头文件?
我有一个定义C枚举的C头文件,该枚举同时用于Swift代码和Metal着色器代码。此文件在Swift Package中的配置如下:
import PackageDescription let package = Package( name: "COREAPI", platforms: [ .iOS("12.0"), .macOS("10.10"), .tvOS("9.0"), .watchOS("2.0") ], products: [ .library( name: "COREAPI", targets: ["COREAPI"]), ], dependencies: [], targets: [ .systemLibrary( name: "SharedOpcodes", path: "Sources/SharedOpcodes" ), .target( name: "COREAPI", dependencies: ["SharedOpcodes"], path: "Sources/COREAPI" ), .testTarget( name: "COREAPITests", dependencies: ["COREAPI"]), ] )
目录结构大致如下:
COREAPI --Package file --SOURCES ----COREApi ------**此处为所有Swift代码,可正常访问共享C头文件 ----SharedOpCodes ------module.modulemap ------sharedopcodes.h
将该Package添加到其他项目后,我可通过简单的import语句访问SharedOpcodes,但在Metal着色器中却无法导入。尝试将其添加到Metal编译器的头文件搜索路径,但指向Derived Data目录中Package的环境变量均指向产物目录,而头文件仅存在于源码目录。尝试通过运行脚本变通,但Xcode的严格沙盒机制阻止了符号链接、目录创建和文件复制操作。请问有什么方法能让Metal编译器识别到Swift Package中的这个头文件?
方法1:调整Swift Package配置,主动暴露头文件到产物目录
将SharedOpcodes的systemLibrary目标改为普通target,并添加publicHeadersPath配置,让Package构建时把头文件复制到产物目录,Metal编译器就能通过标准搜索路径找到它。修改后的Package配置片段如下:
targets: [ .target( name: "SharedOpcodes", path: "Sources/SharedOpcodes", publicHeadersPath: "." // 将当前目录下的头文件设为公开产物 ), // 其他目标保持不变 ]
同时确保module.modulemap内容正确:
module SharedOpcodes { header "sharedopcodes.h" export * }
方法2:主项目中添加Package源码路径到Metal头搜索路径
在主项目的Build Settings中,找到Metal Compiler - Preprocessing分类下的Header Search Paths,添加Package中头文件所在的源码路径:
$(SRCROOT)/../PATH_TO_YOUR_COREAPI_PACKAGE/Sources/SharedOpcodes
提示:路径需根据Package实际位置调整,若Package是作为Git子模块添加,可写成
$(SRCROOT)/Submodules/COREAPI/Sources/SharedOpcodes这类相对路径。
方法3:通过脚本复制头文件到主项目可访问目录
提前在主项目中创建MetalHeaders目录并添加到项目中,然后添加一个Run Script Phase(放在Compile Sources之前),脚本内容如下:
# 替换为你的Package实际路径 SOURCE_HEADER_PATH="$SRCROOT/../PATH_TO_COREAPI/Sources/SharedOpcodes/sharedopcodes.h" DEST_HEADER_PATH="$SRCROOT/MetalHeaders/sharedopcodes.h" # 仅当源文件更新时才复制,避免重复操作 if [ "$SOURCE_HEADER_PATH" -nt "$DEST_HEADER_PATH" ]; then cp "$SOURCE_HEADER_PATH" "$DEST_HEADER_PATH" fi
之后在Metal的Header Search Paths中添加$(SRCROOT)/MetalHeaders即可。
内容的提问来源于stack exchange,提问作者chartman

