diff --git a/README.md b/README.md
index 775d19e0dc555d101feed27bbff15a2152573209..11603003e32abb0c006937a7407b6095f6b9762a 100644
--- a/README.md
+++ b/README.md
@@ -114,11 +114,11 @@ Windows 64 bit binaries are built from a linux system. On arch, install the pack
 Make sure that you have the windows toolchain for 64 bit installed. Run the followinf commands:
 
     (cd utils/arch-pkgs/mingw-w64-shaderc && makepkg -si)
-    yay -Sy mingw-w64-gcc mingw-w64-cmake mingw-w64-make
+    yay -Sy mingw-w64-gcc mingw-w64-cmake mingw-w64-make mingw-w64-dlfcn
     yay -Sy mingw-w64-mpv   # Be sure to install it after building shaderc from source
     yay -Sy mingw-w64-qt6-* # You may specify the packages
     rustup target add x86_64-pc-windows-gnu
-    CMAKE=x86_64-w64-mingw32-cmake CXX=x86_64-w64-mingw32-g++ cargo build --target x86_64-pc-windows-gnu
+    MAKE=x86_64-w64-mingw32-make CMAKE=x86_64-w64-mingw32-cmake CXX=x86_64-w64-mingw32-g++ cargo build --target x86_64-pc-windows-gnu
 
 > Be sure to have the multilib repos and install the bootstrap `minwg-w64-*-bootstrap` packages
 > first, to avoid the circular dependencies... And be sure to have a lot of time to waste.
diff --git a/lektord/build.rs b/lektord/build.rs
index c652ce88b9a0840ccc99bedc230b0f10bdff8530..223372a00831834a12f8abf923234f2663c58b00 100644
--- a/lektord/build.rs
+++ b/lektord/build.rs
@@ -66,6 +66,7 @@ fn main() -> anyhow::Result<()> {
     let cmake_options: Vec<_> = [
         [OsStr::new("-B").to_owned(), build.as_os_str().to_owned()],
         [OsStr::new("-S").to_owned(), source.as_os_str().to_owned()],
+        [OsStr::new("-G").to_owned(), "Unix Makefiles".into()],
         [OsStr::new("-D").to_owned(), version],
     ]
     .into_iter()
@@ -74,29 +75,34 @@ fn main() -> anyhow::Result<()> {
     .collect();
 
     let cmake_bin = std::env::var_os("CMAKE").unwrap_or("cmake".into());
+    let make_bin = std::env::var_os("MAKE").unwrap_or("make".into());
 
     cmd!(cmake_bin => cmake_options);
-    cmd!(cmake_bin => [ OsStr::new("--build"), build.as_os_str() ]);
+    cmd!(make_bin  => [ OsStr::new("-C"), build.as_os_str() ]);
 
-    let path = std::fs::read_dir(&build)
+    let (path, ext) = std::fs::read_dir(&build)
         .expect("failed to read build folder")
         .find_map(|entry| {
             let entry = entry.ok()?.path();
             match (entry.is_file(), entry.extension()) {
-                (true, Some(ext)) if is_dylib(ext) => Some(entry),
+                (true, Some(ext)) if is_dylib(ext) => {
+                    let ext = ext.to_owned();
+                    Some((entry, ext))
+                }
                 _ => None,
             }
         })
         .expect("failed to find the lektor so/dll lib");
     let lib = path.as_os_str().to_string_lossy();
-    let from = lib.rfind("/lib").unwrap();
-    let libfile = &lib[(from + 4)..];
+    let (from, count, prefix) = match lib.rfind("/lib") {
+        Some(from) => (from, 4, "lib"),
+        None => (lib.rfind("/").unwrap(), 1, ""),
+    };
+    let libfile = &lib[(from + count)..];
     let to = libfile.find('.').unwrap();
-    std::fs::copy(
-        &path,
-        build_folder().join(format!("lib{}.so", &libfile[..to])),
-    )
-    .expect("failed to copy the liblektor_c dynamic library");
+    let mut target_file = build_folder().join(format!("{prefix}{}", &libfile[..to]));
+    target_file.set_extension(ext);
+    std::fs::copy(&path, target_file).expect("failed to copy the lektor_c dynamic library");
 
     println!("cargo:rustc-link-search={}", &lib[..from]);
     println!("cargo:rustc-link-lib=dylib={}", &libfile[..to]);
diff --git a/lektord/c/CMakeLists.txt b/lektord/c/CMakeLists.txt
index 3b3b574f6b31ac092deb280cbb1bf2b4f9105276..c296409449e278ef904232e7403e8a5bfc57f7e4 100644
--- a/lektord/c/CMakeLists.txt
+++ b/lektord/c/CMakeLists.txt
@@ -83,7 +83,7 @@ set(GNU_C_FLAGS
 # FIND DEPENDENCIES #
 ###               ###
 
-find_library(MPV_LIBRARY mpv REQUIRED)                              # tested with 0.32.0
+find_library(MPV_LIBRARY mpv REQUIRED)                              # tested with 0.36.0
 find_package(Qt6 COMPONENTS Widgets OpenGL OpenGLWidgets REQUIRED)  # tested with 6.4.0-1
 
 set(CMAKE_AUTOUIC ON)
@@ -93,24 +93,20 @@ set(CMAKE_AUTORCC ON)
 message(STATUS "The installation prefix is ${CMAKE_INSTALL_PREFIX}")
 
 if(WIN32)
-    message(STATUS "You are building on windows, pay attenion to the dependencies")
     set(LKT_OS_WIN 1)
     find_package(dlfcn-win32 REQUIRED)
     add_compile_definitions(LKT_OS_WIN=1 TERMIWIN_DONOTREDEFINE)
 endif()
 if(MSVC OR MSYS OR MINGW)
-    message(STATUS "You are building with a windows compiler")
     set(LKT_OS_MINGW 1)
     find_package(dlfcn-win32 REQUIRED)
     add_compile_definitions(LKT_OS_MINGW=1 TERMIWIN_DONOTREDEFINE)
 endif()
 if(APPLE)
-    message(STATUS "You are building on MacOS X")
     set(LKT_OS_APPLE 1)
     add_compile_definitions(LKT_OS_APPLE=1)
 endif()
 if(UNIX AND NOT APPLE)
-    message(STATUS "You are building on Linux, FreeBSD or any other toaster OS")
     set(LKT_OS_TOASTER 1)
     add_compile_definitions(LKT_OS_TOASTER=1)
 endif()
@@ -123,12 +119,16 @@ endif()
 # THE COMPILATION DIRECTIVES #
 ###                        ###
 
-qt_add_library(lektor_c        SHARED common.cc mainwindow.cc module_qt_window.cc mpvwidget.cc)
-qt_add_library(lektor_c_static STATIC common.cc mainwindow.cc module_qt_window.cc mpvwidget.cc)
+if(WIN32)
+    set(LEKTOR_C_SRC common.cc mainwindow.cc module_qt_window.cc mpvwidget.cc dll.cc)
+else()
+    set(LEKTOR_C_SRC common.cc mainwindow.cc module_qt_window.cc mpvwidget.cc)
+endif()
+qt_add_library(lektor_c SHARED ${LEKTOR_C_SRC})
+qt_set_finalizer_mode(lektor_c ENABLE MODES static_plugins)
 
-foreach(target lektor_c lektor_c_static)
+foreach(target lektor_c)
     set_property(TARGET ${target} PROPERTY CXX_STANDARD 20)
-
     target_include_directories(${target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
     target_compile_definitions(${target} PRIVATE
         LKT_ARCH="${CMAKE_SYSTEM_PROCESSOR}"
@@ -147,18 +147,15 @@ foreach(target lektor_c lektor_c_static)
         ${${CMAKE_BUILD_TYPE}_${CMAKE_C_COMPILER_ID}_C_FLAGS}
         ${${CMAKE_BUILD_TYPE}_${CMAKE_CXX_COMPILER_ID}_C_FLAGS}
     )
+    target_link_libraries(${target} PRIVATE ${MPV_LIBRARY} ${CMAKE_DL_LIBS})
+    target_link_libraries(${target} PRIVATE Qt::Widgets Qt::OpenGL Qt::OpenGLWidgets)
 
-    target_link_options(${target} PRIVATE -Wl,-rpath,. -rdynamic)
-    target_link_libraries(${target}
-        PRIVATE
-        ${MPV_LIBRARY}
-        ${CMAKE_DL_LIBS}
-        Qt::Widgets
-        Qt::OpenGL
-        Qt::OpenGLWidgets
-    )
+    if(UNIX)
+        target_link_options(${target} PRIVATE -Wl,-rpath,. -rdynamic)
+    endif()
     if(WIN32)
-        target_link_libraries(${TARGET} PRIVATE regex dlfcn-win32::dl ws2_32)
+        # target_link_options(${target} PRIVATE -Wl,--export-all-symbols)
+        target_link_libraries(${target} PRIVATE regex dlfcn-win32::dl ws2_32)
     endif()
 endforeach()
 
diff --git a/lektord/c/common.cc b/lektord/c/common.cc
index d1de4bb684bd8e02117e36eb39a044058dda8948..4521462e2508b8a1c0fe0d9c8d2109d51df1aa64 100644
--- a/lektord/c/common.cc
+++ b/lektord/c/common.cc
@@ -89,8 +89,8 @@ safe_strncpy(char *dest, const char *src, size_t n)
 }
 
 extern "C" {
-void ___lkt_log_rs(int, const char *const, const char *const, const char *const, uint64_t,
-                   const char *const);
+DLL_IMPORT void ___lkt_log_rs(int, const char *const, const char *const, const char *const,
+                              uint64_t, const char *const);
 }
 
 void
@@ -107,8 +107,7 @@ ___lkt_log(LOG_LEVEL level, const char *section, const char *func, const char *f
 
     va_list ap;
     va_start(ap, format);
-    const ssize_t count =
-        safe_vsnprintf(line, BUFFER_MAX, format, ap);
+    const ssize_t count = safe_vsnprintf(line, BUFFER_MAX, format, ap);
     va_end(ap);
 
     /* Check for overflow */
diff --git a/lektord/c/common.h b/lektord/c/common.h
index 717202111aae9dd0c4c62974f178aa7cd971705f..7ca898911619c9599574e8885768f4019fc26088 100644
--- a/lektord/c/common.h
+++ b/lektord/c/common.h
@@ -2,7 +2,6 @@
 
 #include <inttypes.h>
 #include <locale.h>
-#include <langinfo.h>
 #include <memory.h>
 #include <regex.h>
 #include <stddef.h>
@@ -22,6 +21,7 @@
 #include <ctype.h>
 
 #if defined(LKT_OS_TOASTER) && (LKT_OS_TOASTER == 1)
+#include <langinfo.h>
 #include <linux/limits.h>
 #include <dirent.h>
 #include <fcntl.h>
@@ -29,6 +29,11 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/time.h>
+#define DLL_IMPORT extern
+
+#elif defined(LKT_OS_MINGW) && (LKT_OS_MINGW == 1)
+#define DLL_IMPORT __declspec(dllimport)
+
 #endif
 
 typedef void (*function_ptr)(void);
@@ -138,7 +143,7 @@ void(___lkt_assert)(const char *file, int line, const char *func, const char *ms
 
 /* Custom defined abort. */
 extern "C" {
-extern EXIT_FUNCTION ___lkt_abort(void);
+DLL_IMPORT EXIT_FUNCTION ___lkt_abort(void);
 #ifdef abort
 #undef abort
 #endif
diff --git a/lektord/c/dll.cc b/lektord/c/dll.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f4928a128731dcbc952c4ab6cc83d935abf02462
--- /dev/null
+++ b/lektord/c/dll.cc
@@ -0,0 +1,47 @@
+#include <windows.h>
+
+void *__imp____lkt_abort;
+void *__imp____lkt_log_rs;
+void *__imp_lkt_toggle_play_state;
+void *__imp_lkt_play_next;
+void *__imp_lkt_play_prev;
+
+#define IMPORT_FUNCTION(name) \
+    *(void **)&__imp_##name = (void *)GetProcAddress(GetModuleHandle(0), "__imp_" #name)
+
+BOOL WINAPI
+DllMain(HINSTANCE hinstDLL, // handle to DLL module
+        DWORD fdwReason,    // reason for calling function
+        LPVOID lpvReserved) // reserved
+{
+    // Perform actions based on the reason for calling.
+    switch (fdwReason) {
+    case DLL_PROCESS_ATTACH:
+        IMPORT_FUNCTION(___lkt_abort);
+        IMPORT_FUNCTION(___lkt_log_rs);
+        IMPORT_FUNCTION(lkt_toggle_play_state);
+        IMPORT_FUNCTION(lkt_play_next);
+        IMPORT_FUNCTION(lkt_play_prev);
+
+        // Initialize once for each new process.
+        // Return FALSE to fail DLL load.
+        break;
+
+    case DLL_THREAD_ATTACH:
+        // Do thread-specific initialization.
+        break;
+
+    case DLL_THREAD_DETACH:
+        // Do thread-specific cleanup.
+        break;
+
+    case DLL_PROCESS_DETACH:
+        if (lpvReserved != nullptr) {
+            break; // do not do cleanup if process termination scenario
+        }
+
+        // Perform any necessary cleanup.
+        break;
+    }
+    return TRUE; // Successful DLL_PROCESS_ATTACH.
+}
diff --git a/lektord/c/module_qt_window.hh b/lektord/c/module_qt_window.hh
index b0a4aee3cf1a072179cbbe3bc9a2ffa3455c4da6..16c5bcbfc6a75008bee7ae7891d6d041cc7b69ec 100644
--- a/lektord/c/module_qt_window.hh
+++ b/lektord/c/module_qt_window.hh
@@ -31,9 +31,9 @@ static inline uint64_t module_font_size           = 0;
 static inline uint64_t module_msg_len_sec         = 0;
 static inline bool module_force_x11               = false;
 
-extern void lkt_toggle_play_state(int);
-extern void lkt_play_next(void);
-extern void lkt_play_prev(void);
+DLL_IMPORT void lkt_toggle_play_state(int);
+DLL_IMPORT void lkt_play_next(void);
+DLL_IMPORT void lkt_play_prev(void);
 
 enum LKT_PLAY_STATE {
     LKT_PLAY_STOP   = 0,