Last active
November 18, 2024 08:49
-
-
Save val-ms/5d98ac8548b429309ec5a35bca9366da to your computer and use it in GitHub Desktop.
An example using CMake/CTest to collect runtime DLL dependencies prior to testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lib/lib.h: | |
lib/lib_private.h: | |
lib/lib.c: | |
# | |
# Assume some C library that makes use of OpenSSL | |
# | |
lib/CMakeLists.txt: | |
# | |
# Test executables | |
# | |
add_library(library_obj OBJECT) | |
target_sources(library_obj | |
PRIVATE | |
lib.c | |
lib_private.h | |
PUBLIC | |
lib.h) | |
target_include_directories(library_obj | |
PRIVATE ${CMAKE_BINARY_DIR} # For access to the generated config.h | |
) | |
add_library(library SHARED) | |
target_sources(library PUBLIC lib.h) | |
target_link_libraries(library | |
PUBLIC | |
library_obj | |
OpenSSL::SSL | |
OpenSSL::Crypto) | |
if(WIN32) | |
install( TARGETS library DESTINATION ${CMAKE_INSTALL_PREFIX} ) | |
# Also install shared library (DLL) dependencies | |
install( CODE [[ | |
file(GET_RUNTIME_DEPENDENCIES | |
LIBRARIES | |
$<TARGET_FILE:library> | |
RESOLVED_DEPENDENCIES_VAR _r_deps | |
UNRESOLVED_DEPENDENCIES_VAR _u_deps | |
DIRECTORIES | |
$<TARGET_FILE_DIR:OpenSSL::SSL> | |
$<TARGET_FILE_DIR:OpenSSL::Crypto> | |
) | |
foreach(_file ${_r_deps}) | |
string(TOLOWER ${_file} _file_lower) | |
if(NOT ${_file_lower} MATCHES "c:[\\/]windows[\\/]system32.*") | |
file(INSTALL | |
DESTINATION "${CMAKE_INSTALL_PREFIX}" | |
TYPE SHARED_LIBRARY | |
FOLLOW_SYMLINK_CHAIN | |
FILES "${_file}" | |
) | |
endif() | |
endforeach() | |
#message("UNRESOLVED_DEPENDENCIES_VAR: ${_u_deps}") | |
]] ) | |
else() | |
install( TARGETS library DESTINATION ${CMAKE_INSTALL_LIBDIR} ) | |
endif() | |
test/CMakeLists.txt: | |
# | |
# Test executables | |
# | |
add_executable(check_program) | |
target_sources(check_program | |
PRIVATE | |
check_program.h | |
check_program.c) | |
target_link_libraries(check_program | |
PRIVATE | |
libcheck::check | |
OpenSSL::SSL | |
OpenSSL::Crypto) | |
target_include_directories(check_program PRIVATE | |
${PROJECT_SOURCE_DIR}/lib # For access to private lib headers (these are unit tests, after all) | |
${CMAKE_BINARY_DIR} # For access to the generated config.h | |
) | |
target_compile_definitions(check_program PUBLIC OBJDIR="${CMAKE_CURRENT_BINARY_DIR}" BUILDDIR="${CMAKE_CURRENT_BINARY_DIR}" SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}") | |
if(WIN32) | |
# | |
# Generate GetLibs-$<CONFIG>.ctest which will collect check_program DLL dependencies | |
# | |
set(GEN_SCRIPT [[ | |
file(GET_RUNTIME_DEPENDENCIES | |
EXECUTABLES | |
$<TARGET_FILE:check_program> | |
RESOLVED_DEPENDENCIES_VAR _r_deps | |
UNRESOLVED_DEPENDENCIES_VAR _u_deps | |
DIRECTORIES | |
$<TARGET_FILE_DIR:libcheck::check> | |
$<TARGET_FILE_DIR:OpenSSL::SSL> | |
$<TARGET_FILE_DIR:OpenSSL::Crypto> | |
CONFLICTING_DEPENDENCIES_PREFIX CTEST_CONFLICTING_DEPENDENCIES | |
) | |
foreach(_file ${_r_deps}) | |
string(TOLOWER ${_file} _file_lower) | |
if(NOT ${_file_lower} MATCHES "c:[\\/]windows[\\/]system32.*") | |
message("DEPENDENCY: ${_file}") | |
file(COPY ${_file} DESTINATION $<TARGET_FILE_DIR:check_program>) | |
endif() | |
endforeach() | |
#message("UNRESOLVED_DEPENDENCIES_VAR: ${_u_deps}") | |
# Collect our libs | |
file(COPY $<TARGET_FILE:library> DESTINATION $<TARGET_FILE_DIR:check_program>) | |
# Collect our apps | |
# No apps in this example | |
#file(COPY $<TARGET_FILE:myapp> DESTINATION $<TARGET_FILE_DIR:check_program>) | |
]]) | |
file(GENERATE OUTPUT GetLibs-$<CONFIG>.ctest CONTENT ${GEN_SCRIPT}) | |
endif() | |
# | |
# The Tests, run with `ctest` | |
# | |
add_test(NAME library_tests COMMAND check_program) | |
set_property(TEST library_tests PROPERTY ENVIRONMENT CK_FORK=no) | |
if(WIN32) | |
set_directory_properties(PROPERTIES TEST_INCLUDE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Run-GetLibs.ctest) | |
endif() | |
tests/Run-GetLibs.ctest: | |
include(copy_runtime_dependencies-${CTEST_CONFIGURATION_TYPE}.ctest) |
That could be better.
I use the same GET_RUNTIME_DEPENDENCIES
technique to copy dependency DLL's at install time to build install packages that have everything you need.
It's been a while since I wrote this. I suspect I didn't consider setting PATH
as you suggest, and just copy-pasted something that I knew worked.
Here is that mean for installing the external DLL dependencies: https://github.com/Cisco-Talos/clamav/blob/main/libclamav/CMakeLists.txt#L472-L504
Well, it's just a long time ago, I understand 😃
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What about using
tests_properties
instead copying dlls? Something like that: