kelin
kelin

Reputation: 12001

How to add uncompiled .mlmodel to Xcode UnitTests bundle

I need to add a .mlmodel file to my Unit Tests in order to check programmatic model compilation in my framework. But, since version 12, Xcode automatically compiles any .mlmodel file added to the project and replaces it with .mlmodelc which is unwanted in this context.

So, if I add a TestModel.mlmodel to the project, I can't get a resource URL:

NSBundle *bundle = [NSBundle bundleForClass:ModelTest.class];

// modelURL is nil
NSURL *modelURL = [bundle URLForResource:@"TestModel" 
                           withExtension:@"mlmodel"];

If I open the compiled bundle package I can see TestModel.mlmodelc there.

How can I disable automatic CoreML model compilation in Xcode?

Upvotes: 1

Views: 693

Answers (3)

davidisdk
davidisdk

Reputation: 3804

Xcode will try to compile the mlmodel file, no matter in which build phase it is. To copy a non compiled model (which is useful for testing), you can:

  • open the project in Xcode,
  • select the project in the Project Navigator,
  • choose your target in the list,
  • select the "Built Phases" tab,
  • make sure your mlmodel file is present in the "Copy Bundle Resources" phase or in "Compile Sources",
  • select the "Build Rules" tab,
  • filter for "ML",
  • find "CoreML Machine Learning Model" and press its "Copy to Target" button,
  • if needed, for "Using" choose "Custom script",
  • for the script enter cp "${SCRIPT_INPUT_FILE}" "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/${INPUT_FILE_NAME}",
  • for "Output Files", add ${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/${INPUT_FILE_NAME}.

Xcode will then copy CoreML models instead of compiling them. To restore the standard behavior, simply delete the build rule.

Upvotes: 2

Why do not you load it directly? https://developer.apple.com/documentation/coreml/downloading_and_compiling_a_model_on_the_user_s_device

static func loadModel(from path: URL, demo: Bool = false) async throws -> MLModel? {
    let modelConfiguration = MLModelConfiguration()
    // the file is already handled by copying resources in Xcode: -> mlmodelc (compiled)
    let compiledModelURL = demo ? path : try await MLModel.compileModel(at: path)

    return try MLModel(contentsOf: compiledModelURL, configuration: modelConfiguration)
}

Upvotes: -1

dspr
dspr

Reputation: 2433

When the project is selected in the Project navigator, all compiled files can be found in the Compile Source section of the Build Phases tab. Can you find the file there ? If yes, you can just remove it.

When the file is selected in the Project navigator, you can do the same from the Target Membership section of the File Inspector : if the box beside the name of your target is checked, uncheck it.

Finally if you want this file to be added to the resources of your application, you probably have to add it to the Copy Bundle Resource section of the Build Phase tab (or you can create a specific Copy File Phase for it)

Upvotes: 0

Related Questions