From 4e14c2d330e8e3db2aaf0f5ae0a2c218fa9e8e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Venegas=20Arrab=C3=A9?= Date: Thu, 30 Jul 2026 22:10:32 +0200 Subject: [PATCH] xilinx: declare the Configuration explicit specializations in the header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit configuration.cc explicitly specializes Configuration::createType2ConfigurationPacketData and Configuration<...>::createConfigurationPackage (Spartan6, Series7, UltraScale, UltraScalePlus), but none of those specializations were declared in configuration.h. The standard requires an explicit specialization to be declared in every translation unit that uses it ([temp.expl.spec]); without the declaration, a TU calling createType2ConfigurationPacketData for Spartan6 instantiates the primary template — which is defined in this header — and emits its own COMDAT copy of the symbol. That copy collides with the strong definition from configuration.cc when linking xc7frames2bit/xc7patch with mingw-w64 ld ("multiple definition of ...createType2ConfigurationPacketData..."), which is why Windows builds needed -Wl,--allow-multiple-definition. ELF linkers happen to resolve the collision silently in favour of the strong symbol, so Linux builds never noticed. Declare all five specializations in the header so every user references the single definition in configuration.cc. Verified with a mingw-w64 cross build: the tools now link without the workaround linker flag. No behaviour change on ELF. --- lib/include/prjxray/xilinx/configuration.h | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/include/prjxray/xilinx/configuration.h b/lib/include/prjxray/xilinx/configuration.h index 0a883547..4721f8db 100644 --- a/lib/include/prjxray/xilinx/configuration.h +++ b/lib/include/prjxray/xilinx/configuration.h @@ -75,6 +75,44 @@ class Configuration { FrameMap frames_; }; +// The explicit specializations below are defined in configuration.cc. +// They must be declared before use in every translation unit +// ([temp.expl.spec]): without these declarations, a TU that calls +// createType2ConfigurationPacketData instantiates the primary +// template defined further down in this header, and that COMDAT copy +// collides with the strong definition from configuration.cc when linking +// with mingw-w64 ld ("multiple definition"); ELF linkers silently +// resolve the collision in favour of the strong symbol. +template <> +Configuration::PacketData +Configuration::createType2ConfigurationPacketData( + const Frames::Frames2Data& frames, + absl::optional& part); + +template <> +void Configuration::createConfigurationPackage( + Spartan6::ConfigurationPackage& out_packets, + const PacketData& packet_data, + absl::optional& part); + +template <> +void Configuration::createConfigurationPackage( + Series7::ConfigurationPackage& out_packets, + const PacketData& packet_data, + absl::optional& part); + +template <> +void Configuration::createConfigurationPackage( + UltraScale::ConfigurationPackage& out_packets, + const PacketData& packet_data, + absl::optional& part); + +template <> +void Configuration::createConfigurationPackage( + UltraScalePlus::ConfigurationPackage& out_packets, + const PacketData& packet_data, + absl::optional& part); + template typename Configuration::PacketData Configuration::createType2ConfigurationPacketData(