Como copiar arquivos DLL para a mesma pasta que o executável usando CMake?
98
Usamos CMake para gerar os arquivos do Visual Studio de nossas fontes em nosso SVN. Agora minha ferramenta requer que alguns arquivos DLL estejam na mesma pasta que o executável. Os arquivos DLL estão em uma pasta ao lado da fonte.
Como posso alterar o meu de CMakeLists.txtmodo que o projeto do Visual Studio gerado já tenha os arquivos DLL específicos nas pastas de liberação / depuração ou os copie durante a compilação?
Se você precisar copiar dlls diferentes dependendo da configuração (Release, Debug, por exemplo), você pode tê-los em subdiretórios nomeados com a configuração correspondente:, /libs/Releasee /libs/Debug. Em seguida, você precisa injetar o tipo de configuração no caminho para a dll na add_custom_commandchamada, assim:
Nota rápida sobre o que funcionou no meu caso, caso isso ajude alguém no futuro: Eu tenho um projeto de biblioteca estática ao qual o executável principal se vincula opcionalmente e essa biblioteca requer que uma DLL seja copiada, se adicionada. Portanto, no arquivo CMakeLists.txt daquela biblioteca, usei ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>como destino. Caso contrário, ele iria copiá-lo para o caminho de construção da biblioteca, o que era inútil.
AberrantWolf de
não é o objetivo das install()diretivas cmake montar os binários? Ou talvez cmake LIBRARYcoisas? Eu realmente não conheço o conjunto de ferramentas.
Sandburg
1
$<TARGET_FILE_DIR:MyTest>- O que é isso? Como imprimir informações, o que exatamente significa
ilw
A menos que eu tenha esquecido algo quando estava integrando o comando, esse método não funciona para bibliotecas adicionadas com IMPORTED_LIBRARIES. Ele reclama por não ser capaz de executar um comando pós-construção quando nada foi construído.
Tzalumen de
2
Após testar e estimular meu cmake: Se você estiver usando IMPORTEDbibliotecas e precisar realocar as DLLs, será necessário usar um comando variante. Se você adicionou sua IMPORTEDbiblioteca como MyImportedLibusaria COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MyImportedLib> $<TARGET_FILE_DIR:MyTest>Observe que para executar vários comandos pós-compilação, você precisa de todos eles vinculados a um comando personalizado, por exemploadd_custom_command(TARGET MyTest POST_BUILD COMMAND #your first command# COMMAND #Your second command#)
Tzalumen
24
Coloquei essas linhas em meu arquivo CMakeLists.txt de nível superior. Todas as bibliotecas e executáveis compilados pelo CMake serão colocados no nível superior do diretório de compilação para que os executáveis possam encontrar as bibliotecas e seja fácil executar tudo.
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
Observe que isso não resolve o problema do OP de copiar binários pré-compilados do diretório de origem do projeto.
Tive esse problema hoje quando tentei fazer uma compilação do meu programa para Windows. E acabei fazendo algumas pesquisas sozinho, uma vez que todas essas respostas não me satisfizeram. Havia três problemas principais:
Queria que compilações de depuração fossem vinculadas a versões de depuração de bibliotecas e compilações de lançamento fossem vinculadas a compilações de lançamento de bibliotecas, respectivamente.
Além disso, eu queria que as versões corretas dos arquivos DLL (Debug / Release) fossem copiadas para os diretórios de saída.
E eu queria conseguir tudo isso sem escrever scripts complexos e frágeis.
Depois de navegar alguns manuais do CMake e alguns projetos multiplataforma no github, encontrei esta solução:
Declare sua biblioteca como um destino com o atributo "IMPORTED", faça referência a sua depuração e libere os arquivos .lib e .dll.
Vincule este destino ao seu projeto como de costume
target_link_libraries(YourProg sdl2 ...)
Faça uma etapa de compilação personalizada para copiar o arquivo dll para seu destino se ele tiver sido alterado de alguma forma desde a compilação anterior
Um adendo à resposta aceita, adicionado como uma resposta separada para obter a formatação do código:
Se você estiver construindo suas dlls no mesmo projeto, elas geralmente estarão nos diretórios Release, Debug, etc. Você terá que usar as variáveis de ambiente do Visual Studio para copiá-las corretamente. por exemplo:
Você não pode usar a variável CMake CMAKE_BUILD_TYPE para a configuração, pois ela é resolvida no momento da geração do projeto VS e sempre será o padrão.
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
${PROJECT_SOURCE_DIR}/lib CACHE
PATH "Directory where all the .lib files are dumped." FORCE)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY
${PROJECT_SOURCE_DIR}/bin CACHE
PATH "Directory where .exe and .dll files are dumped." FORCE)
Sou um iniciante em CMake, mas ainda assim queria compartilhar minha experiência. No meu caso, eu precisava de uma cópia pós-instalação para que todos os meus binários estivessem dentro. No caso de binários de terceiros que podem ser importados dentro do CMake, o seguinte funciona para mim:
find_package( dependency REQUIRED )
if( MSVC )
# If done properly and if the dependency has a correct config file, IMPORTED_LOCATION_RELEASE should be defined
get_target_property( DEP_SHARED_LIB_PATH dependency IMPORTED_LOCATION_RELEASE )
# Create a bin directory in the install folder
add_custom_command(TARGET BGS POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_INSTALL_PREFIX}/bin/)
# Copy the shared lib file
add_custom_command(TARGET BGS POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${DEP_SHARED_LIB_PATH} ${CMAKE_INSTALL_PREFIX}/bin/)
endif()
Obviamente, IMPORTED_LOCATION_RELEASE pode ter variantes, dependendo de como a biblioteca compartilhada foi construída / instalada. Pode ser IMPORTED_LOCATION_DEBUG.
Talvez haja uma maneira melhor de obter esse nome de propriedade, não sei.
Movendo arquivos durante a construção usando install
Tive esse problema ao tentar seguir o tutorial oficial do CMake na Etapa 9 . Este era o local do arquivo que eu queria mover:
src
|_build
|_Debug
- `MathFunctions.dll`
Este era o local onde eu queria que o arquivo estivesse:
src
|_build
|_install
|_bin
- `MathFunctions.dll`
Uma vez que esta DLL foi gerado como uma biblioteca compartilhada, tudo o que fiz foi a de incluir esta linha no CMakeLists.txtno subdiretório que continha o código fonte para a bibliotecasrc/Mathfunctions/CMakeLists.txt
Graças às suas respostas, pude pensar sobre este. É apenas uma linha, então acho que está tudo bem. O $<CONFIG>pode ter dois valores Debug ou Release Dependendo de como o projeto é construído, conforme a pergunta original exigia.
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>
como destino. Caso contrário, ele iria copiá-lo para o caminho de construção da biblioteca, o que era inútil.install()
diretivas cmake montar os binários? Ou talvez cmakeLIBRARY
coisas? Eu realmente não conheço o conjunto de ferramentas.$<TARGET_FILE_DIR:MyTest>
- O que é isso? Como imprimir informações, o que exatamente significaIMPORTED_LIBRARIES
. Ele reclama por não ser capaz de executar um comando pós-construção quando nada foi construído.IMPORTED
bibliotecas e precisar realocar as DLLs, será necessário usar um comando variante. Se você adicionou suaIMPORTED
biblioteca comoMyImportedLib
usariaCOMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MyImportedLib> $<TARGET_FILE_DIR:MyTest>
Observe que para executar vários comandos pós-compilação, você precisa de todos eles vinculados a um comando personalizado, por exemploadd_custom_command(TARGET MyTest POST_BUILD COMMAND #your first command# COMMAND #Your second command#)
Coloquei essas linhas em meu arquivo CMakeLists.txt de nível superior. Todas as bibliotecas e executáveis compilados pelo CMake serão colocados no nível superior do diretório de compilação para que os executáveis possam encontrar as bibliotecas e seja fácil executar tudo.
Observe que isso não resolve o problema do OP de copiar binários pré-compilados do diretório de origem do projeto.
fonte
Tive esse problema hoje quando tentei fazer uma compilação do meu programa para Windows. E acabei fazendo algumas pesquisas sozinho, uma vez que todas essas respostas não me satisfizeram. Havia três problemas principais:
Queria que compilações de depuração fossem vinculadas a versões de depuração de bibliotecas e compilações de lançamento fossem vinculadas a compilações de lançamento de bibliotecas, respectivamente.
Além disso, eu queria que as versões corretas dos arquivos DLL (Debug / Release) fossem copiadas para os diretórios de saída.
E eu queria conseguir tudo isso sem escrever scripts complexos e frágeis.
Depois de navegar alguns manuais do CMake e alguns projetos multiplataforma no github, encontrei esta solução:
Declare sua biblioteca como um destino com o atributo "IMPORTED", faça referência a sua depuração e libere os arquivos .lib e .dll.
Vincule este destino ao seu projeto como de costume
Faça uma etapa de compilação personalizada para copiar o arquivo dll para seu destino se ele tiver sido alterado de alguma forma desde a compilação anterior
fonte
Um adendo à resposta aceita, adicionado como uma resposta separada para obter a formatação do código:
Se você estiver construindo suas dlls no mesmo projeto, elas geralmente estarão nos diretórios Release, Debug, etc. Você terá que usar as variáveis de ambiente do Visual Studio para copiá-las corretamente. por exemplo:
para a fonte e
para o destino. Observe o escape!
Você não pode usar a variável CMake CMAKE_BUILD_TYPE para a configuração, pois ela é resolvida no momento da geração do projeto VS e sempre será o padrão.
fonte
$<CONFIGURATION>
Você também pode usar o comando find_library:
Com um EXECUTABLE_PATH definido, por exemplo:
você pode mover os arquivos .dll de que seu executável precisa, com
fonte
Isso é útil para um deles
fonte
Você provavelmente precisará adicionar um destino personalizado e torná-lo dependente de um de seus destinos executáveis.
Para copiar o arquivo usando a função acima, use:
fonte
Sou um iniciante em CMake, mas ainda assim queria compartilhar minha experiência. No meu caso, eu precisava de uma cópia pós-instalação para que todos os meus binários estivessem dentro. No caso de binários de terceiros que podem ser importados dentro do CMake, o seguinte funciona para mim:
Obviamente, IMPORTED_LOCATION_RELEASE pode ter variantes, dependendo de como a biblioteca compartilhada foi construída / instalada. Pode ser IMPORTED_LOCATION_DEBUG.
Talvez haja uma maneira melhor de obter esse nome de propriedade, não sei.
fonte
Movendo arquivos durante a construção usando
install
Tive esse problema ao tentar seguir o tutorial oficial do CMake na Etapa 9 . Este era o local do arquivo que eu queria mover:
Este era o local onde eu queria que o arquivo estivesse:
Uma vez que esta DLL foi gerado como uma biblioteca compartilhada, tudo o que fiz foi a de incluir esta linha no
CMakeLists.txt
no subdiretório que continha o código fonte para a bibliotecasrc/Mathfunctions/CMakeLists.txt
Graças às suas respostas, pude pensar sobre este. É apenas uma linha, então acho que está tudo bem. O
$<CONFIG>
pode ter dois valores Debug ou Release Dependendo de como o projeto é construído, conforme a pergunta original exigia.fonte