CMake,OS X包,以递归方式将目录复制到资源

时间:2016-12-13 12:20:26

标签: macos qt cmake

我正在尝试将我们的Qt应用程序转换为CMake,其中一个目标是OS X应用程序。它需要将某个文件夹放在其our.app/Contents/Resources文件夹中。我尝试使用文件属性添加它,但我只设法复制文件夹本身没有它的内容。如何递归复制?

这是我做的:

set (
  RES_SOURCES
  ${SOURCE_ROOT}/data-folder
)
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SRC} ${RES_SOURCES})
SET_SOURCE_FILES_PROPERTIES(${RES_SOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)

UPD:到目前为止,只是使用execute_process将文件复制到目标目录,但感觉不对。

5 个答案:

答案 0 :(得分:1)

在复制之前使用file(GLOB_RECURSE收集文件列表。

file(GLOB_RECURSE RES_SOURCES "${SOURCE_ROOT}/data-folder/*")
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SRC} ${RES_SOURCES})
SET_SOURCE_FILES_PROPERTIES(${RES_SOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)

答案 1 :(得分:1)

如前所述,您可以使用file(GLOB_RECURSE RES_SOURCES "${SOURCE_ROOT}/data-folder/*")获取目录中所有文件的列表。使用SET_SOURCE_FILES_PROPERTIES(${RES_SOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)为列表${RES_SOURCES}中的每个文件设置相同的位置属性(在这种情况下,将它们全部放入Resources中的平面结构中。)

此命令未考虑data-folder的结构,如果要复制文件和目录结构,则必须自己指定:

#Get a list of all of the files in the data-folder
file(GLOB_RECURSE RES_SOURCES "${SOURCE_ROOT}/data-folder/*")

#Add our executable, and all of the files as "Source Files"
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SRC} ${RES_SOURCES})

#individually set the file's path properties
foreach(RES_FILE ${RES_SOURCES})

  #Get the relative path from the data-folder to the particular file
  file(RELATIVE_PATH RES_PATH "${SOURCE_ROOT}/data-folder" ${RES_FILE})

  #Set it's location inside the app package (under Resources)
  set_property(SOURCE ${RES_FILE} PROPERTY MACOSX_PACKAGE_LOCATION "Resources/${RES_PATH}")

endforeach(RES_FILE)

此代码段会将data-folder的内容复制到应用程序的Resources文件夹中,保留了结构,就像您希望执行复制命令一样。

答案 2 :(得分:0)

没有足够的代表来评论,所以这里是Alex's答案的一种变体。

# Set where all of the resources can be found
set(RESROURCE_ROOT "${CMAKE_SOURCE_DIR}/Resources")

# Get all of the resource files
file(
  GLOB_RECURSE
  RESOURCE_FILES
  "${RESROURCE_ROOT}/*"
)

#Add our executable, and all of the files as "Source Files"
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SRC} ${RESOURCE_FILES})

#individually set the file's path properties
foreach(RES_FILE ${RESOURCE_FILES})

  #Get the relative path from the data-folder to the particular file
  file(RELATIVE_PATH RES_PATH "RESROURCE_ROOT" ${RES_FILE})

  # This is the main difference. It makes it so that files are placed correctly.
  get_filename_component(RESOURCE_SUBDIR ${RES_PATH} DIRECTORY)
  set(RESOURCE_DIRECTORY "Resources/${RESOURCE_SUBDIR}")

  #Set it's location inside the app package (under Resources)
  set_property(
    SOURCE 
    ${RES_FILE} 
    PROPERTY 
    MACOSX_PACKAGE_LOCATION 
    ${RESOURCE_DIRECTORY}
  )
endforeach(RES_FILE)

答案 3 :(得分:0)

我根据 Alex Hamilton 的回答创建了这个 CMake 函数。这将保持文件夹结构完整。

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()

你可以这样运行:

resource(<out-var> <source-path> <destination-path> <glob-pattern>)

一些例子:

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}
    )

但是要小心!对我来说,设置 PROPERTY MACOSX_PACKAGE_LOCATION 仅在我不设置目标属性 RESOURCE 时才有效:

set_target_properties(MyApp PROPERTIES
  RESOURCE ${RESOURCE_FILES}) # Don't! For me this makes everything lose folder structure again...

工作原理: 我们首先使用 file(GLOB_RECURSE ...) 获取资源的完整路径。现在对于每个资源,我们首先使用 get_filename_component 获取包含文件的文件夹的路径。如果此路径与目标路径不同,我们将使用 file(RELATIVE_PATH ...) 获取包含资源的文件夹与源文件夹的相对位置。现在我们可以简单地将它添加到我们的目标路径并使用它来设置属性 MACOSX_PACKAGE_LOCATION。

注意: 这个函数的一个很好的改进可能是使用可选参数来调用具有多种模式的函数。 (*.png *.gif *.jpg)

答案 4 :(得分:0)

2021 年的答案:Alex Hamilton 的解决方案为每个文件生成了冗余文件夹 - 我已经更正了他的代码,以免发生这种情况。我还将这些文件分组到 Xcode 中的“Resources”文件夹中,否则它们将显示为一个平面列表。

# Get a list of all of the files in the data-folder.
file(GLOB_RECURSE RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/data-folder/*")

# Add our executable, and all of the files as "Source Files".
add_executable(YourApp ${RESOURCES})

# Individually set the file's path properties.
foreach (FILE ${RESOURCES})
    # Get the relative path from the data-folder to the particular file.
    file(RELATIVE_PATH NEW_FILE "${CMAKE_CURRENT_SOURCE_DIR}/data-folder" ${FILE})

    # Get the relative path to the file.
    get_filename_component(NEW_FILE_PATH ${NEW_FILE} DIRECTORY)

    # Set it's location inside the app package (under Resources).
    set_property(SOURCE ${FILE} PROPERTY MACOSX_PACKAGE_LOCATION "Resources/${NEW_FILE_PATH}")

    # Optional: Add the file to the 'Resources' folder group in Xcode.
    #           This also preserves folder structure.
    source_group("Resources/${NEW_FILE_PATH}" FILES "${FILE}")
endforeach ()