Search code examples
macosbackwards-compatibility

Mac .app package backwards compatibility error: "You can't use this version of the application "[my app name]" with this version of OS X."


I'm developing a cross-platform game that will be published and distributed through Steam, and having trouble with the Mac version. Everything is written in C++ and built with Xcode on El Capitan using a project file generated by CMake containing a few minor modifications. After the build is complete, I'm using my own build script to put together the .app package, which generates the directory structure, adds the icon file and the binary, along with an Info.plist file which I've written myself following what documentation I can find on what elements are necessary.

The problem is with backwards compatibility. When I try to launch the game .app on my Mac running Yosemite, I get this error message:

You can't use this version of the application "[my app name]" with this version of OS X. You have OS X 10.10.5. The application requires OS X 10.11 or later.

The thing is, in Xcode I specified the build target as OS X 10.7, so I'm perplexed as to why this error is occurring. I can even go inside the package in Finder, navigate to the actual game binary, and run it without a problem. It only fails with this error message when I double-click the .app file (whose icon shows the circle with the slash, indicating that I probably did something wrong in Info.plists or with the package configuration). Things work perfectly when running on El Capitan.

I also tried setting LSMinimumSystemVersion appropriately, but this doesn't fix the problem.

Here's the content of my Info.plist file:

<?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>Contents/MacOS/[binary name]</string>
    <key>CFBundleDisplayName</key>
    <string>[game title]</string>
    <key>CFBundleIconFile</key>
    <string>[icon file]</string>
</dict>
</plist>

I imagine something is missing from Info.plist, but Apple's documentation on required keys isn't helpful as far as figuring out what that might be.

Let me know if you need more info to figure this out, and thanks so much for any help!


Solution

  • So the problem seems to be clang setting a minimum mac version in the data section of the output binary. The reason the binary executes when run directly vs through the .app is because when run with the .app it's actually LaunchServices executing the binary, and it checks the version number embedded into the binary. Here is an example of assembly output by clang:

        .section    __TEXT,__text,regular,pure_instructions
        .macosx_version_min 10, 12
        .globl  _main
        .align  4, 0x90
    _main:                                  ## @main
        .cfi_startproc
    ## BB#0:
        pushq   %rbp
    Ltmp0:
        .cfi_def_cfa_offset 16
    Ltmp1:
        .cfi_offset %rbp, -16
        movq    %rsp, %rbp
    Ltmp2:
        .cfi_def_cfa_register %rbp
        xorl    %eax, %eax
        movl    $0, -4(%rbp)
        movl    %edi, -8(%rbp)
        movq    %rsi, -16(%rbp)
        popq    %rbp
        retq
        .cfi_endproc
    
    
    .subsections_via_symbols
    

    Right at the top there ".macosx_version_min" is the problem. To change this embedded version number you simply need to set a compiler flag:

    $ gcc -mmacosx-version-min=10.7 -S -o main.S main.c
    

    Now when we look at the output assembly:

        .section    __TEXT,__text,regular,pure_instructions
        .macosx_version_min 10, 7
        .globl  _main
        .align  4, 0x90
    _main:                                  ## @main
        .cfi_startproc
    ## BB#0:
        pushq   %rbp
    Ltmp0:
        .cfi_def_cfa_offset 16
    Ltmp1:
        .cfi_offset %rbp, -16
        movq    %rsp, %rbp
    Ltmp2:
        .cfi_def_cfa_register %rbp
        xorl    %eax, %eax
        movl    $0, -4(%rbp)
        movl    %edi, -8(%rbp)
        movq    %rsi, -16(%rbp)
        popq    %rbp
        retq
        .cfi_endproc
    
    
    .subsections_via_symbols
    

    Boom, version number fixed.