From 0621bb32bf0284e458ad9a77bfb13460ad61ba66 Mon Sep 17 00:00:00 2001 From: cadons Date: Sun, 30 Aug 2026 22:57:51 +0200 Subject: [PATCH 1/2] fix(craft): delete copy ops on classes holding unique_ptr maps MSVC's __declspec(dllexport) (DOCRAFT_LIB, active when DOCRAFT_BUILD_SHARED_LIBS is set) forces instantiation of every public member of an exported class, including implicitly-defined copy constructor/assignment. std::unordered_map>'s own copy assignment isn't SFINAE-disabled based on value_type (a pre-C++20 container quirk), so the implicit copy ops on DocraftLoomTagHandlerRegistry and DocraftCraftLanguageParser were never deleted at the type level -- only broken when actually instantiated. GCC/Clang's static-lib builds never instantiate unused implicit members, so this only surfaces on a Windows/MSVC shared-lib build (error C2679 trying to copy-assign the unique_ptr-valued map). Neither class is ever copied (registry is a singleton; the parser is always used as a local) -- explicitly deleting copy ctor/assignment on both fixes the DLL export instantiation without changing any call site. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_015RjTSLobQWMZq8DcFyDZoG --- docraft/include/docraft/craft/docraft_craft_language_parser.h | 3 +++ .../docraft/loom/craft/docraft_loom_tag_handler_registry.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/docraft/include/docraft/craft/docraft_craft_language_parser.h b/docraft/include/docraft/craft/docraft_craft_language_parser.h index cbdfb2b..08b0771 100644 --- a/docraft/include/docraft/craft/docraft_craft_language_parser.h +++ b/docraft/include/docraft/craft/docraft_craft_language_parser.h @@ -49,6 +49,9 @@ namespace docraft::craft { ~DocraftCraftLanguageParser() = default; + DocraftCraftLanguageParser(const DocraftCraftLanguageParser&) = delete; + DocraftCraftLanguageParser& operator=(const DocraftCraftLanguageParser&) = delete; + /** * @brief Parses craft language source (a single root element) as a string. * @param craft_language_source XML source as string. diff --git a/docraft/include/docraft/loom/craft/docraft_loom_tag_handler_registry.h b/docraft/include/docraft/loom/craft/docraft_loom_tag_handler_registry.h index 186db06..d4f9eaf 100644 --- a/docraft/include/docraft/loom/craft/docraft_loom_tag_handler_registry.h +++ b/docraft/include/docraft/loom/craft/docraft_loom_tag_handler_registry.h @@ -37,6 +37,9 @@ namespace docraft::loom::craft { public: static DocraftLoomTagHandlerRegistry& instance(); + DocraftLoomTagHandlerRegistry(const DocraftLoomTagHandlerRegistry&) = delete; + DocraftLoomTagHandlerRegistry& operator=(const DocraftLoomTagHandlerRegistry&) = delete; + void register_handler(const std::string& tag, std::unique_ptr handler); /** From adb79f8aa843647943f07c70938b51bfc863af6b Mon Sep 17 00:00:00 2001 From: cadons Date: Sun, 30 Aug 2026 23:24:20 +0200 Subject: [PATCH 2/2] fix(build): export DocraftLoomPdfCreator and DocraftValidationResult Both were missing the DOCRAFT_LIB annotation entirely, so on a Windows/MSVC shared-lib build their member functions never made it into docraft.dll's export table. docraft_tool.exe -- linked against docraft.lib as a DLL consumer -- then failed with LNK2019 unresolved external symbol on DocraftLoomPdfCreator::create/render and DocraftValidationResult::has_errors/has_warnings. GCC/Clang builds never surfaced this: the project doesn't set hidden visibility, so every symbol is exported by default there regardless of DOCRAFT_LIB. Only an MSVC dllexport/dllimport build depends on the annotation being present on every class whose methods are called across the DLL boundary (here, from docraft_tool's main.cpp). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_015RjTSLobQWMZq8DcFyDZoG --- docraft/include/docraft/loom/docraft_loom_pdf_creator.h | 2 +- docraft/include/docraft/tools/docraft_validator.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docraft/include/docraft/loom/docraft_loom_pdf_creator.h b/docraft/include/docraft/loom/docraft_loom_pdf_creator.h index 50ca666..dbd6fff 100644 --- a/docraft/include/docraft/loom/docraft_loom_pdf_creator.h +++ b/docraft/include/docraft/loom/docraft_loom_pdf_creator.h @@ -24,7 +24,7 @@ namespace docraft::loom { * and re-visited by the rendering pass for each physical page. The body is laid out * as one continuous flow and then split across pages by DocraftLoomPaginationProcessor. */ - class DocraftLoomPdfCreator + class DOCRAFT_LIB DocraftLoomPdfCreator { public: /** diff --git a/docraft/include/docraft/tools/docraft_validator.h b/docraft/include/docraft/tools/docraft_validator.h index a938ab9..5621aec 100644 --- a/docraft/include/docraft/tools/docraft_validator.h +++ b/docraft/include/docraft/tools/docraft_validator.h @@ -45,7 +45,7 @@ namespace docraft::tools { * @brief Aggregated result of DocraftValidator::validate(): every diagnostic found, * in the order they were discovered. */ - struct DocraftValidationResult + struct DOCRAFT_LIB DocraftValidationResult { std::vector issues;