5

I have a macOS application whose executable is a shell script. That is, the file in its Contents/MacOS subdirectory whose name is specified in its CFBundleExecutable property is an executable shell script rather than a binary.

I want the script's process to match the system's architecture by default, and its running architecture matters because the script has some logic in it that does different things depending on the architecture.

Per Apple's documentation, its Info.plist file contains an LSArchitecturePriority key that prioritizes arm64 over x86_64 so that it will run natively on Apple Silicon macs.

However if I launch the app from the Finder, for some reason it's always running as x86_64 instead of arm64.

I confirmed this by making the shell script contain the following:

#!/bin/sh
uname -m >> ~/Desktop/log.txt
sleep 5

...and seeing that the text that gets appended to log.txt is always x86_64 if I launch the app from the Finder. I can also see its architecture is Intel in Activity Monitor.

I know there are other ways of detecting whether the script is running on an arm64 mac, regardless of whether the process itself is arm64 or x86_64, but I want the user to be able to run the app using either architecture (for example by using arch -x86_64 or arch -arm64 when running it from the command line). But it should always default to the system's native architecture when launched from the Finder. This isn't a problem if an app bundle's executable is a universal binary, so it seems to be related to it being a shell script.

Why is it launching as x86_64 instead of arm64? Is there a way to fix it?

I did find one relevant bit of Apple's documentation in Building a Universal macOS Binary:

If an app doesn’t contain an executable binary, the system may run it under Rosetta translation as a precautionary measure to prevent potential runtime issues. For example, the system runs script-only apps under Rosetta translation. If you verified that your app runs correctly on both Apple silicon and Intel-based Mac computers, add the LSArchitecturePriority key to your app’s Info.plist file and list the arm64 architecture first.

Given that using LSArchitecturePriority isn't working, this is looking increasingly like a macOS bug, but I'm curious if there's any workaround or other explanation as to what's going on.

1 Answer 1

3

I've just had the same problem, and it looks like the architecture is cached.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleExecutable</key>
    <string>run</string>
    <key>CFBundleIdentifier</key>
    <string>com.testing</string>
    <key>LSArchitecturePriority</key>
    <array>
        <string>arm64</string>
    </array>
    <key>LSRequiresNativeExecution</key>
    <true/>
</dict>
</plist>

I'd just added the LSArchitecturePriority and LSRequiresNativeExecution, but it didn't seem to work; but by accident I changed the value in the CFBundleIdentifier, and that was enough to make it try again, and run the /Contents/MacOS/run script.

Changing it back caused the error again. I've not found a way to clear the cache.


As an aside, I did see someone mention that arm64 programs needed to be signed, I had been trying to do that with the following (using the ad-hoc identity), but I don't think it's necessary:

codesign --timestamp --options=runtime -s "-" testing.app 

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .