[CMake] Framework Installation Directory / Framework copying

Mike Jackson mike.jackson at bluequartz.net
Wed Dec 9 16:23:34 EST 2009


On Wed, Dec 9, 2009 at 4:05 PM, Glenn Hughes <ghughes02138 at gmail.com> wrote:
> Thanks Mike,
>
> I pretty much got my build process on the Mac working. The thing that
> took me awhile to understand were the different running contexts that
> bits of the CMake script are processed within. What I want is a little
> different than the standard way that things are done in the CMake way
> of handling Frameworks and bundles. I basically always want the
> Frameworks copied into the app, not just during the install phase.
>
> 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 (thanks Mike!):
>
> 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.
>
> Thanks again
> Glenn

Looks like you generally have a handle on things. The subtle thing
about the Xcode Environment variables is that your CMake Code is run
at "Cmake Time" which will have no idea about the Xcode variables that
are set during a "Build Time". Chicken-and-Egg sort of thing. In the
recent HDF5 Version 1.8 CMake Port/Fork I have the following code that
runs an executable as soon as it is compiled:

SET (CFG_INIT "/${CMAKE_CFG_INTDIR}")
IF (MAKE_SYSTEM)
  SET (CFG_INIT "")
ENDIF (MAKE_SYSTEM)

SET (CMD ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}${CFG_INIT}/H5detect${EXE_EXT})
IF(XCODE)
  SET (CMD "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/\${CONFIGURATION}/H5detect")
ENDIF(XCODE)
ADD_EXECUTABLE(H5detect ${HDF5_SRC_DIR}/H5detect.c)

ADD_CUSTOM_COMMAND(
  OUTPUT ${HDF5_BINARY_DIR}/H5Tinit.c
  COMMAND ${CMD}
  ARGS > ${HDF5_BINARY_DIR}/H5Tinit.c
  DEPENDS H5detect
  )

The part to take away from this is that if you look at the if(XCODE)
section I am picking up the proper Xcode variable that determines the
"Debug/Release" sub directory of "Bin". That is then used in the
"add_custom_command()".

 The other thing you might be able to do would be to "save" the
CMAKE_*_OUTPUT_DIRECTORY variables, set those variables to inside the
MyApp.app bundle for the Framework target, then set them back to the
originals at the bottom of the Frameworks CMakeLists.txt file. This
_should_ end up compiling/generating the framework at the correct spot
in the App bundle.

 You could also use the add_custom_target() command to copy the built
framework into the app bundle after it is compiled:

add_custom_command(TARGET target
                    PRE_BUILD | PRE_LINK | POST_BUILD
             COMMAND command1 [ARGS] [args1...]
            [COMMAND command2 [ARGS] [args2...] ...]
                [WORKING_DIRECTORY dir]
                  [COMMENT comment] [VERBATIM]  )

add_custom_target(${qtlib}-Debug-Copy ALL
                            COMMAND ${CMAKE_COMMAND} -E
copy_if_different ${QT_DLL_PATH_tmp}/${qtlib}${TYPE}4.dll
                            ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/
                            COMMENT "Copying ${qtlib}${TYPE}4.dll to
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/")


The "COMMAND" would be actually using CMake itself to do the copying. Just FYI.
_________________________________________________________
Mike Jackson                  mike.jackson at bluequartz.net
BlueQuartz Software                    www.bluequartz.net
Principal Software Engineer                  Dayton, Ohio


More information about the CMake mailing list