Search code examples
xcodemacoscmakeplist

How to have Info.plist bundled in a MacOSX application with CMake?


I'm developing an application accessing the camera. The project is written in C++ and I'm using CMake to package it.

To deploy the project in a Mac, I use the command below, and then open the project in Xcode:

cmake -G Xcode ../src

It worked fine until last update, when it started complaining about:

[access] This app has crashed because it attempted to access 
privacy-sensitive data without a usage description.  The app's 
Info.plist must contain an NSCameraUsageDescription key with 
a string value explaining to the user how the app uses this data.
Program ended with exit code: 9

So I created a new Info.plist file with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
    <dict>
        <key>CFBundleIconFile</key>
        <string></string>
        <key>NSCameraUsageDescription</key>
        <string>This app requires to access your camera 
            to retrieve images and perform the demo</string>
    </dict>
</plist>

My question is: What should I add in CMakeLists.txt to take this file and put it in the proper place? And... is it possible that cmake -G Xcode would include it correctly in the Xcode project?

EDIT Following recommendations, I tried this:

  # Compile files:
  add_executable(fpv 
    main.cpp

    files.cpp
    files.hpp

    more-files.cpp
    more-files.hpp
 )

# Link files:
target_link_libraries(fpv
   fpv-lib
   ${GTKMM_LIBRARIES}  
   ${OpenCV_LIBS} )

# Lets bundle it:
set_target_properties(fpv PROPERTIES
  FRAMEWORK TRUE
  FRAMEWORK_VERSION C
  MACOSX_FRAMEWORK_IDENTIFIER com.cmake.dynamicFramework
  MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
  # "current version" in semantic format in Mach-O binary file
  VERSION 16.4.0
  # "compatibility version" in semantic format in Mach-O binary file
  SOVERSION 1.0.0
  # XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Jean-Michel Gonet"
)

EDIT To be sure the Info.plist is correct I manually added it in the Xcode project:

  • Added the Info.plist as a source in the project.
  • Selected it in the project navigator.
  • Renamed it (!) to Info.cpp, so that I can include it in the target.
  • Renamed it back to Info.plist.
  • Launched the application, that asked my permission for accessing the camera.

And then it worked.

But I would still like to have project configuration in CMake.


Solution

  • Official Cmake's documentation (see cmake-properties-7) mentions 2 families of MACOSX target properties:

    • FRAMEWORK, FRAMEWORK_VERSION and MACOSX_FRAMEWORK_INFO_PLIST
    • MACOSX_BUNDLE_INFO_PLIST and MACOSX_BUNDLE

    Now, the inclusion of Info.plist is managed by the latter Bundle family.

    To have a complete example, let say your application is called fpv, and your directory structure is:

    /src   <-- Root folder
     /lib  <-- There you may add sources for your application's library
          CMakeLists.txt <-- Library has its own configuration
          more-files.cpp
          lots-of-files.cpp
          etc.cpp
          ...
     /app  <-- This is where executable resides
          CMakeLists.txt <-- This is where you need to configure the bundle
          Info.plist    <-- I've placed the plist file just besides.
          main.cpp
          second.cpp
          more.cpp
    

    This is how your application's CMakeLists.txt could look like:

    # src/app
    project( fpv )
    
    # GTKMM has to be linked/included via pkg_config:
    find_package(PkgConfig)
    pkg_check_modules(GTKMM gtkmm-3.0) # Defines variables GTKMM_INCLUDE_DIRS, GTKMM_LIBRARY_DIRS and GTKMM_LIBRARIES.
    link_directories( ${GTKMM_LIBRARY_DIRS} )
    include_directories( ${GTKMM_INCLUDE_DIRS} )
    
    # OpenCV can be linked as usual:
    find_package( OpenCV REQUIRED )
    
    # Compile files:
    add_executable(fpv 
        main.cpp
    
        main-window.cpp
        main-window.hpp
    
        auto-viseur.cpp
        auto-viseur.hpp
     )
    
    # Link files:
    target_link_libraries(fpv
       fpv-lib
       ${GTKMM_LIBRARIES}  
       ${OpenCV_LIBS} )
    
    # Lets bundle it:
    set_target_properties(fpv PROPERTIES
      MACOSX_BUNDLE TRUE
      MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
    )
    

    To build the XCode project, create a xcode folder besides the main src folder:

    mkdir xcode
    cd xcode
    cmake -G Xcode ../src
    

    Now you can open it as a project from Xcode. To execute in debug mode:

    • Select your application's target (top left-ish side, by default it is set to ALL_BUILD). You'll notice that the icon has changed to a stylized A.
    • Run it.
    • If all went well, you should be requested to allow your application to access camera.
    • Also, you should see the Info.plist file as a resource