R – CMake: how do you copy private frameworks into the application bundle under OS X

cmakeframeworksmacos

We build several private frameworks that get copied into our application bundle during our Xcode build process. I'm moving the whole build process to CMake, and this is one area that I haven't been able to resolve.

I have found one utility module: CMakeIngestOSXBundleLibraries.cmake but its a little unclear to me how this might be used, or if it does what we want. I would like it to be run every time the app is build just after it is linked. This leads me to believe that I should do something like

IF (APPLE)
 add_custom_command( TargetName  POST_BUILD CMakeIngestOSXBundleLibraries.cmake )
ENDIF (APPLE) 

but I don't think that's quite right. Anyone have any experience with this?

Best Answer

Here's what I'm doing:

1) In my framework CMakeLists.txt file, I have the following:

IF (APPLE)
       SET_TARGET_PROPERTIES( MyFramework PROPERTIES FRAMEWORK true)
       SET_TARGET_PROPERTIES( MyFramework PROPERTIES
           XCODE_ATTRIBUTE_INSTALL_PATH @executable_path/../Frameworks/  )
ENDIF (APPLE)

The second "set_target_properties" line configures the framework to always be looked for in the application bundle in the Frameworks sub-folder.

2) In my top-level CMakeLists.txt file, I add setup a unified binary output directory:

SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Bin)
SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Bin )
SET (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Bin )

3) Then, in my applications' CMakeLists.txt file, I have the following:

IF (APPLE)
       ADD_CUSTOM_COMMAND(
               TARGET MyApp
               POST_BUILD
               COMMAND ${PYTHON_EXECUTABLE}
               ARGS ${CMAKE_HOME_DIRECTORY}/CopyFramework.py
               --binary ${PROJECT_BINARY_DIR}/Bin
               --framework MyFramework.framework
               --app MyApp.app

    )
ENDIF (APPLE)

This calls out to my python script, which does the work of assembling the src and dest paths, and actually copying the Framework.

The final trick is that since this is a Mac only thing, I can rely on an Xcode environment variable within the Python script:

           config= os.environ["CONFIGURATION"]

This allows me to assemble the complete path to the actual binary locations of the framework and the app.

The one thing I wish was that there was a CMake variable that would expand to the current Config within the context of the ADD_CUSTOM_COMMAND... It'd be nice to not have to resort to using the Xcode environment variable.

Related Topic