Использование выражения генератора в команде `cmake -E copy` - PullRequest
2 голосов
/ 03 марта 2020

Я пытаюсь скопировать dll-файлы из папки bin в другую папку. Я хочу скопировать файлы из bin / Debug при сборке в Debug и из bin / Release при сборке в Release. Это то, что я сейчас использую (и которое не работает).

file(GLOB library_files_debug ${outputdirectory_root}/Debug/*.dll)
file(GLOB library_files_release ${outputdirectory_root}/Release/*.dll)

add_custom_target(copy_dlls_to_wheel ALL
    DEPENDS setup.py
    COMMAND ${CMAKE_COMMAND} -E echo "Debug files: $<$<CONFIG:Debug>:${library_files_debug}>"
    COMMAND ${CMAKE_COMMAND} -E echo "Release files: $<$<CONFIG:Release>:${library_files_release}>"
    COMMAND ${CMAKE_COMMAND} -E echo "Destination dir: ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}"
    COMMAND ${CMAKE_COMMAND} -E copy $<$<CONFIG:Debug>:${library_files_debug}> $<$<CONFIG:Release>:${library_files_release}> ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}

    )

Я работаю на Windows 10 и использую Visual Studio для сборки. Когда указанная выше цель copy_dlls_to_wheel встроена в Debug, первый оператор echo выводит правильные dll-файлы, а второй echo пуст. Однако файлы не копируются. Вместо этого я получаю сообщение об ошибке The system cannot find the path specified.

Я также пытался заменить последнюю строку на

COMMAND ${CMAKE_COMMAND} -E copy $<$<CONFIG:Debug>:${library_files_debug}> ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}

, но я получаю тот же результат.

Однако, когда я удаляю выражение генератора и использую

COMMAND ${CMAKE_COMMAND} -E copy ${library_files_debug} ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}

, файлы правильно копируются в мою выходную папку. Я уверен, что выражение моего генератора корректно, так как я получаю ожидаемый результат от команд echo. Выражения генератора не поддерживаются при использовании cmake -E copy, или я что-то не так делаю?

1 Ответ

1 голос
/ 03 марта 2020

Командная строка CMake copy может обрабатывать несколько файлов, когда вы просто предоставляете список , поэтому это работает:

COMMAND ${CMAKE_COMMAND} -E copy ${library_files_debug} ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}

Это расширяется до списка файлов , разделенных пробелами, когда команда copy в конечном итоге выполняется, что является ожидаемым синтаксисом.

cmake.exe -E copy mylib1.dll mylib2.dll /your/binary/dir/python/proj

Однако, когда заключено в выражение генератора, список будет не правильно интерпретироваться CMake. Хотя выражение генератора будет оценено правильно, список будет храниться как список файлов, разделенных точкой с запятой , что является неправильным синтаксисом:

cmake.exe -E copy "mylib1.dll;mylib2.dll" /your/binary/dir/python/proj

Это вызывает copy Сбой команды.

Чтобы обойти эту проблему, вы можете l oop для каждого DLL-файла, который вы хотите скопировать, если их не слишком много. Что-то вроде этого может работать:

# Loop through the Debug files.
foreach(cur_file ${library_files_debug})
    get_filename_component(file_name ${cur_file} NAME)
    add_custom_target(copy_dlls_to_wheel_debug_${file_name} ALL
        DEPENDS setup.py
        COMMAND ${CMAKE_COMMAND} -E echo "DLL file: ${cur_file}"
        COMMAND ${CMAKE_COMMAND} -E echo "Destination dir: ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}"
        COMMAND ${CMAKE_COMMAND} -E copy $<$<CONFIG:Debug>:${cur_file}> ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}
        )
endforeach()
# Loop through the Release files.
foreach(cur_file ${library_files_release})
    get_filename_component(file_name ${cur_file} NAME)
    add_custom_target(copy_dlls_to_wheel_release_${file_name} ALL
        DEPENDS setup.py
        COMMAND ${CMAKE_COMMAND} -E echo "DLL file: ${cur_file}"
        COMMAND ${CMAKE_COMMAND} -E echo "Destination dir: ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}"
        COMMAND ${CMAKE_COMMAND} -E copy $<$<CONFIG:Release>:${cur_file}> ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}
        )
endforeach()

Более быстрое решение может заключаться в том, чтобы связать ваши DLL, используя утилиту командной строки CMake tar, скопировать их, а затем извлечь их, как предложено в this ответ. Команда CMake tar, похоже, также не принимает списки, заключенные в выражения генератора, поэтому список файлов для объединения записывается в файл.

file(GLOB library_files_debug ${outputdirectory_root}/Debug/*.dll)
file(GLOB library_files_release ${outputdirectory_root}/Release/*.dll)

# Write the filenames (not full path) of the files to pack to file
set(debug_content "")
set(release_content "")

foreach(lib_file ${library_files_debug})
    get_filename_component(file_name ${lib_file} NAME)
    set(debug_content "${debug_content}${file_name}\n")
endforeach(lib_file ${library_files_debug})

foreach(lib_file ${library_files_release})
    get_filename_component(file_name ${lib_file} NAME)
    set(release_content "${release_content}${file_name}\n")
endforeach(lib_file ${library_files_release})

set(filenames_debug ${outputdirectory_root}/debug_files.txt)
set(filenames_release ${outputdirectory_root}/release_files.txt)
file(WRITE ${filenames_debug} ${debug_content})
file(WRITE ${filenames_release} ${release_content})

# Read either the list of debug or release files, and pack files
add_custom_command(
    TARGET bdist PRE_BUILD
    COMMAND ${CMAKE_COMMAND} -E tar "cfj" ${outputdirectory_root}/temp.tar --files-from="$<IF:$<CONFIG:Debug>,${filenames_debug},${filenames_release}>"
    WORKING_DIRECTORY ${outputdirectory_root}/$<CONFIG>)

# Unpack the files in the folder building the python wheel
add_custom_command(
    TARGET bdist PRE_BUILD
    COMMAND ${CMAKE_COMMAND} -E rename ${outputdirectory_root}/temp.tar temp.tar
    COMMAND ${CMAKE_COMMAND} -E tar "xfj" temp.tar
    COMMAND ${CMAKE_COMMAND} -E remove temp.tar
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/python/${PROJECT_NAME})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...