Ignore .metal files when building for iOS Simulator target
As of Xcode 11, Simulator supports Metal when running on macOS Catalina. Metal files are supported during the build, including when running on macOS Mojave or when building with an older deployment target. Metal won't be functional in those scenarios but you no longer need to exclude files from the build. (Of course when running iOS 13 / tvOS 13 simulators on 10.15 Metal actually works).
You can resolve this by precompiling your .metal file into a Metal library during the build step, and removing the .metal source code from your app target.
Remove .metal file from target
Select your .metal file in the project navigator, and uncheck the target that is giving you the warning.
Metal library compile script
Create a bash script called CompileMetalLib.sh in your project, alongside your .metal file, with contents like this:
xcrun -sdk iphoneos metal -c MyShader.metal -o MyShader.air
xcrun -sdk iphoneos metallib MyShader.air -o MyShader.metallib
rm MyShader.air
Make sure to give it executable permissions by running chmod +x CompileMetalLib.sh
.
MyShader.air
is the intermediate compile step, and MyShader.metallib
is the fully compiled metal library. Read all about compiling a Metal file here
If you're compiling for OS X, change iphoneos
to macosx
.
Run compile script during build
Now you'll want to trigger this script in your Build Phases.
Add a New Run Script Phase to your target. The contents should look like this:
cd ${SRCROOT}/path/to/folder/containing/yourshader
./CompileMetalLib.sh
It's important to drag this step so that it happens before the Copy Bundle Resources step.
Change your code to use your compiled Metal library
You'll now load the compiled Metal library from your app bundle.
Here's some pseudo-Swift:
let metalLibPath = Bundle.main.path(forResource: "MyShader", ofType: "metallib")
let myLibrary = try metalDevice.makeLibrary(filepath: metalLibPath)
Result
You are manually compiling your .metal file with an external script, and copying the compiled library into your bundle resources. Your code loads this library. Now that you don't have any .metal files in your target, the simulator will no longer throw a warning about not being able to compile for x86_64.