Skip to content

Commit 5e96b16

Browse files
committed
🏁 Fix Windows-related errors with DLLs
Signed-off-by: burgholzer <burgholzer@me.com>
1 parent 15229aa commit 5e96b16

8 files changed

Lines changed: 147 additions & 7 deletions

File tree

src/qdmi/driver/CMakeLists.txt

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,27 @@ if(NOT TARGET ${TARGET_NAME})
3030
target_compile_definitions(
3131
${TARGET_NAME}
3232
PRIVATE
33-
"DYN_DEV_LIBS=std::array{ std::pair{\"$<TARGET_FILE_NAME:MQT::CoreQDMINaDevice>\", \"MQT_NA\"}, std::pair{\"$<TARGET_FILE_NAME:MQT::CoreQDMIScDevice>\", \"MQT_SC\"}, std::pair{\"$<TARGET_FILE_NAME:MQT::CoreQDMI_DDSIM_Device>\", \"MQT_DDSIM\"} }"
33+
"DYN_DEV_LIBS=std::pair{\"$<TARGET_FILE_NAME:MQT::CoreQDMINaDevice>\", \"MQT_NA\"}, std::pair{\"$<TARGET_FILE_NAME:MQT::CoreQDMIScDevice>\", \"MQT_SC\"}, std::pair{\"$<TARGET_FILE_NAME:MQT::CoreQDMI_DDSIM_Device>\", \"MQT_DDSIM\"}"
3434
)
3535

3636
# Ensure the driver can find the device libraries at runtime
3737
if(WIN32)
38-
# On Windows, ensure the driver depends on the device libraries so they are found when loading
39-
# the driver DLL.
40-
target_link_libraries(${TARGET_NAME} PRIVATE MQT::CoreQDMINaDevice MQT::CoreQDMIScDevice
41-
MQT::CoreQDMI_DDSIM_Device)
38+
# On Windows, we need to copy the device DLLs to the library directory
39+
add_custom_command(
40+
TARGET ${TARGET_NAME}
41+
PRE_BUILD
42+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMIScDevice>
43+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
44+
add_custom_command(
45+
TARGET ${TARGET_NAME}
46+
PRE_BUILD
47+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMINaDevice>
48+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
49+
add_custom_command(
50+
TARGET ${TARGET_NAME}
51+
PRE_BUILD
52+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMI_DDSIM_Device>
53+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
4254
else()
4355
target_link_options(
4456
${TARGET_NAME}

src/qdmi/driver/Driver.cpp

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <qdmi/device.h>
1717
#include <spdlog/spdlog.h>
1818

19+
#include <array>
1920
#include <cassert>
2021
#include <cstddef>
2122
#include <cstring>
@@ -31,13 +32,56 @@
3132

3233
#ifdef _WIN32
3334
#include <windows.h>
35+
36+
#include <filesystem>
3437
#else
3538
#include <dlfcn.h>
3639
#endif // _WIN32
3740

3841
namespace qdmi {
3942
#ifdef _WIN32
40-
#define DL_OPEN(lib) LoadLibraryA((lib))
43+
namespace {
44+
[[nodiscard]] auto getDriverDirectory() -> std::filesystem::path {
45+
HMODULE module = nullptr;
46+
if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
47+
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
48+
reinterpret_cast<LPCWSTR>(&getDriverDirectory),
49+
&module) == 0) {
50+
return {};
51+
}
52+
53+
std::wstring buffer(MAX_PATH, L'\0');
54+
DWORD size = 0;
55+
while (true) {
56+
size = GetModuleFileNameW(module, buffer.data(),
57+
static_cast<DWORD>(buffer.size()));
58+
if (size == 0) {
59+
return {};
60+
}
61+
if (size < buffer.size()) {
62+
buffer.resize(size);
63+
break;
64+
}
65+
buffer.resize(buffer.size() * 2);
66+
}
67+
68+
return std::filesystem::path(buffer).parent_path();
69+
}
70+
71+
[[nodiscard]] auto loadDeviceLibrary(const std::string& libName) -> HMODULE {
72+
const auto requested = std::filesystem::path(libName);
73+
74+
const std::filesystem::path path = requested.has_parent_path()
75+
? requested
76+
: getDriverDirectory() / requested;
77+
78+
return LoadLibraryExW(path.wstring().c_str(), nullptr,
79+
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
80+
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
81+
}
82+
} // namespace
83+
84+
#define DL_OPEN(lib) loadDeviceLibrary((lib))
4185
#define DL_SYM(lib, sym) \
4286
reinterpret_cast<void*>(GetProcAddress(static_cast<HMODULE>((lib)), (sym)))
4387
#define DL_CLOSE(lib) FreeLibrary(static_cast<HMODULE>((lib)))
@@ -337,7 +381,7 @@ auto QDMI_Session_impl_d::querySessionProperty(QDMI_Session_Property prop,
337381

338382
namespace qdmi {
339383
Driver::Driver() {
340-
for (const auto& [lib, prefix] : DYN_DEV_LIBS) {
384+
for (const auto& [lib, prefix] : std::array{DYN_DEV_LIBS}) {
341385
addDynamicDeviceLibrary(lib, prefix);
342386
}
343387
}

test/fomac/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,23 @@ set(TARGET_NAME mqt-core-fomac-test)
1010

1111
if(TARGET MQT::CoreFoMaC)
1212
package_add_test(${TARGET_NAME} MQT::CoreFoMaC test_fomac.cpp)
13+
14+
if(WIN32)
15+
# On Windows, we need to copy the device DLLs to the test directory
16+
add_custom_command(
17+
TARGET ${TARGET_NAME}
18+
PRE_BUILD
19+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMIScDevice>
20+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
21+
add_custom_command(
22+
TARGET ${TARGET_NAME}
23+
PRE_BUILD
24+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMINaDevice>
25+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
26+
add_custom_command(
27+
TARGET ${TARGET_NAME}
28+
PRE_BUILD
29+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMI_DDSIM_Device>
30+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
31+
endif()
1332
endif()

test/na/fomac/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,23 @@ if(TARGET MQT::CoreNAFoMaC)
1414
# Set the device json path
1515
target_compile_definitions(${TARGET_NAME}
1616
PRIVATE NA_DEVICE_JSON="${PROJECT_SOURCE_DIR}/json/na/device.json")
17+
18+
if(WIN32)
19+
# On Windows, we need to copy the device DLLs to the test directory
20+
add_custom_command(
21+
TARGET ${TARGET_NAME}
22+
PRE_BUILD
23+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMIScDevice>
24+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
25+
add_custom_command(
26+
TARGET ${TARGET_NAME}
27+
PRE_BUILD
28+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMINaDevice>
29+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
30+
add_custom_command(
31+
TARGET ${TARGET_NAME}
32+
PRE_BUILD
33+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMI_DDSIM_Device>
34+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
35+
endif()
1736
endif()

test/qdmi/devices/dd/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,13 @@ if(TARGET MQT::CoreQDMI_DDSIM_Device)
3232
# Set the executable path and version information
3333
target_compile_definitions(${TARGET_NAME} PRIVATE MQT_CORE_VERSION="${MQT_CORE_VERSION}")
3434
target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
35+
36+
# On Windows, we need to copy the DLL to the test executable directory
37+
if(WIN32)
38+
add_custom_command(
39+
TARGET ${TARGET_NAME}
40+
PRE_BUILD
41+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMI_DDSIM_Device>
42+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
43+
endif()
3544
endif()

test/qdmi/devices/na/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,13 @@ if(TARGET MQT::CoreQDMINaDeviceGen
2828
PRIVATE EXECUTABLE_PATH="$<TARGET_FILE:MQT::CoreQDMINaDeviceGenerator>"
2929
MQT_CORE_VERSION="${MQT_CORE_VERSION}"
3030
NA_DEVICE_JSON="${PROJECT_SOURCE_DIR}/json/na/device.json")
31+
32+
# On Windows, we need to copy the DLL to the test executable directory
33+
if(WIN32)
34+
add_custom_command(
35+
TARGET ${TARGET_NAME}
36+
PRE_BUILD
37+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMINaDevice>
38+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
39+
endif()
3140
endif()

test/qdmi/devices/sc/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,13 @@ if(TARGET MQT::CoreQDMIScDeviceGen
2828
PRIVATE EXECUTABLE_PATH="$<TARGET_FILE:MQT::CoreQDMIScDeviceGenerator>"
2929
MQT_CORE_VERSION="${MQT_CORE_VERSION}"
3030
SC_DEVICE_JSON="${PROJECT_SOURCE_DIR}/json/sc/device.json")
31+
32+
# On Windows, we need to copy the DLL to the test executable directory
33+
if(WIN32)
34+
add_custom_command(
35+
TARGET ${TARGET_NAME}
36+
PRE_BUILD
37+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMIScDevice>
38+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
39+
endif()
3140
endif()

test/qdmi/driver/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,23 @@ if(TARGET MQT::CoreQDMIDriver)
1515
PRIVATE
1616
"DYN_DEV_LIBS=std::array{ std::pair{\"$<TARGET_FILE_NAME:MQT::CoreQDMINaDevice>\", \"MQT_NA\"}, std::pair{\"$<TARGET_FILE_NAME:MQT::CoreQDMIScDevice>\", \"MQT_SC\"}, std::pair{\"$<TARGET_FILE_NAME:MQT::CoreQDMI_DDSIM_Device>\", \"MQT_DDSIM\"} }"
1717
)
18+
19+
if(WIN32)
20+
# On Windows, we need to copy the device DLLs to the test directory
21+
add_custom_command(
22+
TARGET ${TARGET_NAME}
23+
PRE_BUILD
24+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMIScDevice>
25+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
26+
add_custom_command(
27+
TARGET ${TARGET_NAME}
28+
PRE_BUILD
29+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMINaDevice>
30+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
31+
add_custom_command(
32+
TARGET ${TARGET_NAME}
33+
PRE_BUILD
34+
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MQT::CoreQDMI_DDSIM_Device>
35+
$<TARGET_FILE_DIR:${TARGET_NAME}>)
36+
endif()
1837
endif()

0 commit comments

Comments
 (0)