I created this CMake function based on Alex Hamilton his answer. This will keep the folder structure intact.
function(resource VAR SOURCE_PATH DESTINATION PATTERN)
file(GLOB_RECURSE _LIST CONFIGURE_DEPENDS ${SOURCE_PATH}/${PATTERN})
foreach (RESOURCE ${_LIST})
get_filename_component(_PARENT ${RESOURCE} DIRECTORY)
if (${_PARENT} STREQUAL ${SOURCE_PATH})
set(_DESTINATION ${DESTINATION})
else ()
file(RELATIVE_PATH _DESTINATION ${SOURCE_PATH} ${_PARENT})
set(_DESTINATION ${DESTINATION}/${_DESTINATION})
endif ()
set_property(SOURCE ${RESOURCE} PROPERTY MACOSX_PACKAGE_LOCATION ${_DESTINATION})
endforeach (RESOURCE)
set(${VAR} ${_LIST} PARENT_SCOPE)
endfunction()
You can run it like this:
resource(<out-var> <source-path> <destination-path> <glob-pattern>)
Some examples:
resource(AUDIO ${RESOURCES_PATH}/Audio Resources/Audio *.wav)
resource(IMAGES ${RESOURCES_PATH}/Images Resources/Images *.png)
resource(ANYTHING ${RESOURCES_PATH} Resources *)
resource(ICON ${RESOURCES_PATH} Resources MyApp.icns)
set(RESOURCE_FILES
${AUDIO}
${IMAGES}
${ANYTHING}
${ICON}
)
add_executable( MyApp
MACOSX_BUNDLE
Main.c
MyAppSource.c
${RESOURCE_FILES}
)
But watch out! For me setting the PROPERTY MACOSX_PACKAGE_LOCATION only works if I don't set the target property RESOURCE:
set_target_properties(MyApp PROPERTIES
RESOURCE ${RESOURCE_FILES}) # Don't! For me this makes everything lose folder structure again...
How it works:
We first get the full path of the resources using file(GLOB_RECURSE ...). Now for each resource, we first get the path of the folder containing the file using get_filename_component. If this path is not the same as the destination path, we get the relative location of the folder containing the resource compared to the source, using file(RELATIVE_PATH ...). Now we can simply add that to our destination path and use that to set the property MACOSX_PACKAGE_LOCATION.
Note:
A nice improvement to this function could be to use optional arguments for calling the function with multiple patterns. (*.png *.gif *.jpg)