fix(windows): find and ship external libraries under mingw

LogosModule.cmake's EXT_LIB_NAMES listed only .dylib/.so/.a, so every
module declaring nix.external_libraries failed to cross-compile with
"External library '<x>' ... was not found in .../lib" -- which reads like
a staging bug rather than a missing filename spelling.

On Windows a shared library is TWO files: you LINK the import library
(lib<x>.dll.a under mingw) and SHIP the .dll. Both are now searched.

The runtime copy needed care of its own: the import library's name ends
in ".a", so the existing `NOT MATCHES "\\.a$"` test would classify it as
a static archive and skip the copy -- producing a plugin that links
cleanly and then fails to load with no DLL beside it. When a .dll.a or
.lib was linked, the companion .dll is resolved and copied instead, and
its absence is a hard error rather than a silent omission.

Unblocks logos-package-downloader-module and every other external-library
module under cross.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dario Gabriel Lipicar
2026-08-10 16:24:03 -03:00
co-authored by Claude Opus 5
parent 83b375b2b7
commit 1cc41fa961
+37 -5
View File
@@ -534,8 +534,14 @@ function(logos_module)
set(EXT_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")
endif()
# Find the library (prefer shared, fall back to static)
if(APPLE)
# Find the library (prefer shared, fall back to static).
# On Windows a shared library is TWO files: you LINK against the import
# library (lib<x>.dll.a under mingw) and SHIP the .dll. Neither spelling
# appeared in these lists, so every external-library module failed to
# cross-compile with "was not found in .../lib".
if(WIN32)
set(EXT_LIB_NAMES lib${ext_lib}.dll.a ${ext_lib}.dll.a lib${ext_lib}.lib ${ext_lib}.lib lib${ext_lib}.dll ${ext_lib}.dll lib${ext_lib}.a ${ext_lib}.a)
elseif(APPLE)
set(EXT_LIB_NAMES lib${ext_lib}.dylib lib${ext_lib}.so ${ext_lib}.dylib ${ext_lib}.so lib${ext_lib}.a ${ext_lib}.a)
else()
set(EXT_LIB_NAMES lib${ext_lib}.so lib${ext_lib}.dylib ${ext_lib}.so ${ext_lib}.dylib lib${ext_lib}.a ${ext_lib}.a)
@@ -547,12 +553,38 @@ function(logos_module)
target_link_libraries(${MODULE_NAME}_module_plugin PRIVATE ${${ext_lib}_PATH})
target_include_directories(${MODULE_NAME}_module_plugin PRIVATE ${EXT_INCLUDE_DIR})
# Copy shared libraries to output directory (static archives are linked in, no runtime copy needed)
# Copy shared libraries to output directory (static archives are
# linked in, no runtime copy needed).
#
# Windows needs care: what we just linked is usually the IMPORT
# library lib<x>.dll.a, whose name ends in ".a" and would therefore
# be mistaken for a static archive and skipped -- shipping a plugin
# with no runtime DLL beside it. Resolve the companion .dll and copy
# THAT instead.
get_filename_component(EXT_LIB_FILENAME "${${ext_lib}_PATH}" NAME)
if(NOT EXT_LIB_FILENAME MATCHES "\\.a$")
set(EXT_RUNTIME_LIB "")
if(EXT_LIB_FILENAME MATCHES "\\.dll\\.a$" OR EXT_LIB_FILENAME MATCHES "\\.lib$")
get_filename_component(_ext_dir "${${ext_lib}_PATH}" DIRECTORY)
foreach(_dll_name lib${ext_lib}.dll ${ext_lib}.dll)
if(EXISTS "${_ext_dir}/${_dll_name}")
set(EXT_RUNTIME_LIB "${_ext_dir}/${_dll_name}")
set(EXT_LIB_FILENAME "${_dll_name}")
break()
endif()
endforeach()
if(NOT EXT_RUNTIME_LIB)
message(FATAL_ERROR
"External library '${ext_lib}': linked ${EXT_LIB_FILENAME} but found no "
"companion DLL in ${_ext_dir}. The plugin would build and then fail to "
"load at runtime, so refusing to continue.")
endif()
elseif(NOT EXT_LIB_FILENAME MATCHES "\\.a$")
set(EXT_RUNTIME_LIB "${${ext_lib}_PATH}")
endif()
if(EXT_RUNTIME_LIB)
add_custom_command(TARGET ${MODULE_NAME}_module_plugin PRE_LINK
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${${ext_lib}_PATH}
${EXT_RUNTIME_LIB}
${CMAKE_BINARY_DIR}/modules/${EXT_LIB_FILENAME}
COMMENT "Copying ${EXT_LIB_FILENAME} to modules directory"
)