12

Whenever I build a project that includes a metal shader to an x86_64 target (iOS simulator), I get a dependency analysis warning:

warning: no rule to process file '[File Path]/Shaders.metal' of type sourcecode.metal for architecture x86_64

I know this isn't a huge issue but I like to keep my projects free from warnings when I build, so that when a real issue does arise, I actually notice the yellow warning triangle.

Any quick way to get Xcode to ignore metal files for simulator targets?

Tricky
  • 7,025
  • 5
  • 33
  • 43
  • I'm curious about what your setup is, that you have a Metal app that can run on the Simulator. Do you fall back to OpenGL ES? – Nicolas Miari Sep 21 '17 at 01:27
  • 1
    @NicolasMiari *That* would be the ultimate solution – a metal app that runs in the simulator! But no, I rely on UIKit mostly, I have an MTKView for a particular feature and I switch it off in the simulator and test around it. I imagine this issue would still exist if you were to fall back to OpenGL though. – Tricky Sep 21 '17 at 10:34
  • 2
    An ugly workaround would be to have two separate targets: One for device, containing all source files, and another for simulator, that excludes the .metal files (file's Target Membership checkbox off). Then, setup two schemes (one to build each target)... – Nicolas Miari Sep 21 '17 at 10:37
  • I think you can achieve that setup with build settings of each target (supported architectures?) – Nicolas Miari Sep 21 '17 at 10:38
  • 2
    Yeah, that would work but I was hoping for something simpler. Like a flag I could pass in my build settings, or even a compiler flag on the shader file in the 'compile sources' build phase. – Tricky Sep 21 '17 at 10:47

2 Answers2

4

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.

Liam Don
  • 139
  • 2
  • 5
1

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).

russbishop
  • 16,587
  • 7
  • 61
  • 74