Search code examples
objective-cxcodecmakemetal

Issues with porting Xcode MacOS game template to СMake


I want to integrate basic Objective-C and Metal code to my cross-platform C++ framework to allow MacOS target. I tried to port MacOS Game template to CMake as it is a build system that I use and I have no experience with Metal and Objective-C. I tried to do it manually and using this tool and able to generate similar Xcode project and here the best result that I've got so far.

cmake_minimum_required (VERSION 3.4)
project( ConvertTest C)

set( PROJECT_HEADERS 
ConvertTest/AppDelegate.h
ConvertTest/GameViewController.h
ConvertTest/ShaderTypes.h
ConvertTest/Renderer.h
)

set( SOURCES
ConvertTest/AppDelegate.m
ConvertTest/GameViewController.m
ConvertTest/Renderer.m
ConvertTest/main.m
)

set( STATIC_DEPENDENCIES
)

if( NOT SKIP_FIND_FOUNDATION_LIBRARY)
   find_library( FOUNDATION_LIBRARY Foundation)
   message( STATUS "FOUNDATION_LIBRARY is ${FOUNDATION_LIBRARY}")
endif()

set( DEPENDENCIES
${FOUNDATION_LIBRARY}
)

set( GLOBAL_RESOURCES
ConvertTest/Assets.xcassets
)

set( BASE_RESOURCES
ConvertTest/Base.lproj/Main.storyboard
ConvertTest/Shaders.metal
)

set( RESOURCES
   ${GLOBAL_RESOURCES}
   ${BASE_RESOURCES}
)


##
## ConvertTest
##

add_executable( ConvertTest MACOSX_BUNDLE
${SOURCES}
${PUBLIC_HEADERS}
${PROJECT_HEADERS}
${PRIVATE_HEADERS}
${RESOURCES}
)

target_link_libraries( ConvertTest
${STATIC_DEPENDENCIES}
${DEPENDENCIES}
)

set_source_files_properties(
${RESOURCES}
   PROPERTIES
      MACOSX_PACKAGE_LOCATION
      Resources
)

if (APPLE)
   set_target_properties( ConvertTest PROPERTIES
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/ConvertTest-Info.plist.in"
)

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \
  -framework AppKit \
  -framework Metal \
  -framework MetalKit \
  -framework ModelIO"
)
endif()

And Plist template:

<?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>CFBundleDevelopmentRegion</key>
   <string>English</string>
   <key>CFBundleExecutable</key>
   <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
   <key>CFBundleGetInfoString</key>
   <string>${MACOSX_BUNDLE_INFO_STRING}</string>
   <key>CFBundleIconFile</key>
   <string>${MACOSX_BUNDLE_ICON_FILE}</string>
   <key>CFBundleIdentifier</key>
   <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
   <key>CFBundleInfoDictionaryVersion</key>
   <string>6.0</string>
   <key>CFBundleLongVersionString</key>
   <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
   <key>CFBundleName</key>
   <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
   <key>CFBundleShortVersionString</key>
   <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
   <key>CFBundleSignature</key>
   <string>????</string>
   <key>CFBundleVersion</key>
   <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
   <key>NSHumanReadableCopyright</key>
   <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
   <key>CFBundlePackageType</key>
   <string>APPL</string>
   <key>NSPrincipalClass</key>
   <string>NSApplication</string>
   <key>NSMainStoryboardFile</key>
   <string>Main</string>
</dict>
</plist>

There are 2 differences with CMake-generated project in runtime:

  • In template project NSError *error; pointers are initialised with nil and with garbage value in CMake-generated project. Obviously, I can initialise it manually, but what makes the difference?
  • Then it fails on loading ColorMap texture. It is in Assets.xcassets in both projects and I can't find what is wrong in CMake-generated one. The error message is:

Error creating texture Could not get asset catalog from supplied bundle

Internal structure of bundles looks the same.


Solution

  • Okay, I found solution for the first issue:

    target_compile_options( ConvertTest PUBLIC "-fobjc-arc" )
    

    For the second the culprit was in empty MACOSX_BUNDLE_GUI_IDENTIFIER and MACOSX_BUNDLE_BUNDLE_NAME variables required for plist generation.