xilinx: declare the Configuration explicit specializations in the header

configuration.cc explicitly specializes
Configuration<Spartan6>::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.
This commit is contained in:
Carlos Venegas Arrabé 2026-07-30 22:10:32 +02:00
parent 132342f7a2
commit 4e14c2d330
No known key found for this signature in database
GPG Key ID: EC73A5348B584C4C
1 changed files with 38 additions and 0 deletions

View File

@ -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<Spartan6> 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<Spartan6>::PacketData
Configuration<Spartan6>::createType2ConfigurationPacketData(
const Frames<Spartan6>::Frames2Data& frames,
absl::optional<Spartan6::Part>& part);
template <>
void Configuration<Spartan6>::createConfigurationPackage(
Spartan6::ConfigurationPackage& out_packets,
const PacketData& packet_data,
absl::optional<Spartan6::Part>& part);
template <>
void Configuration<Series7>::createConfigurationPackage(
Series7::ConfigurationPackage& out_packets,
const PacketData& packet_data,
absl::optional<Series7::Part>& part);
template <>
void Configuration<UltraScale>::createConfigurationPackage(
UltraScale::ConfigurationPackage& out_packets,
const PacketData& packet_data,
absl::optional<UltraScale::Part>& part);
template <>
void Configuration<UltraScalePlus>::createConfigurationPackage(
UltraScalePlus::ConfigurationPackage& out_packets,
const PacketData& packet_data,
absl::optional<UltraScalePlus::Part>& part);
template <typename ArchType>
typename Configuration<ArchType>::PacketData
Configuration<ArchType>::createType2ConfigurationPacketData(