From 17e72133958c3fcaef59a9e93db713fa4f46565e Mon Sep 17 00:00:00 2001 From: Geoff Phillips Date: Mon, 26 Jun 2023 14:52:33 +0200 Subject: [PATCH] Fix template class instantiation - For Windows DLL, export definition of template class instantiation directly in the header using __declspec(dllexport). - For other builds (including Windows static lib), declare as extern in the header and define in the cpp. This change is required to fix 'multiple definition of typeinfo' linker errors seen with some compilers, e.g. GCC for 32-bit armhf arm-linux-gnueabihf-gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1). --- .../include/aws/core/Core_EXPORTS.h | 3 +++ .../core/endpoint/DefaultEndpointProvider.h | 10 ++++++++-- .../aws/core/endpoint/EndpointProviderBase.h | 6 ++++-- .../endpoint/DefaultEndpointProvider.cpp | 8 ++++++-- .../source/endpoint/EndpointProviderBase.cpp | 7 +++++-- .../velocity/cpp/ServiceExportHeader.vm | 3 +++ .../cpp/endpoint/EndpointProviderHeader.vm | 7 ++++--- .../cpp/endpoint/EndpointProviderSource.vm | 18 ++++++++++++++++++ 8 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/aws-cpp-sdk-core/include/aws/core/Core_EXPORTS.h b/src/aws-cpp-sdk-core/include/aws/core/Core_EXPORTS.h index 1d3e312a607..ecd5a39db7b 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/Core_EXPORTS.h +++ b/src/aws-cpp-sdk-core/include/aws/core/Core_EXPORTS.h @@ -18,12 +18,15 @@ #else // AWS_CORE_EXPORTS #define AWS_CORE_API __declspec(dllimport) #endif // AWS_CORE_EXPORTS + #define AWS_CORE_EXTERN #else // USE_IMPORT_EXPORT #define AWS_CORE_API + #define AWS_CORE_EXTERN extern #endif // USE_IMPORT_EXPORT #define AWS_CORE_LOCAL #else // defined (USE_WINDOWS_DLL_SEMANTICS) || defined (_WIN32) #define AWS_CORE_API + #define AWS_CORE_EXTERN extern #if __GNUC__ >= 4 #define AWS_CORE_LOCAL __attribute__((visibility("hidden"))) #else diff --git a/src/aws-cpp-sdk-core/include/aws/core/endpoint/DefaultEndpointProvider.h b/src/aws-cpp-sdk-core/include/aws/core/endpoint/DefaultEndpointProvider.h index d4d5cdd941c..cc2bef156c8 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/endpoint/DefaultEndpointProvider.h +++ b/src/aws-cpp-sdk-core/include/aws/core/endpoint/DefaultEndpointProvider.h @@ -110,7 +110,13 @@ namespace Aws BuiltInParametersT m_builtInParameters; }; - // Export symbol from the DLL: - template class AWS_CORE_API DefaultEndpointProvider >; + /** + * Export endpoint provider symbols for Windows DLL, otherwise declare as extern + */ + AWS_CORE_EXTERN template class AWS_CORE_API DefaultEndpointProvider, + Aws::Endpoint::BuiltInParameters, + Aws::Endpoint::ClientContextParameters>; + + AWS_CORE_EXTERN template class AWS_CORE_API DefaultEndpointProvider>; } // namespace Endpoint } // namespace Aws diff --git a/src/aws-cpp-sdk-core/include/aws/core/endpoint/EndpointProviderBase.h b/src/aws-cpp-sdk-core/include/aws/core/endpoint/EndpointProviderBase.h index 29b67626e38..df841a8f001 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/endpoint/EndpointProviderBase.h +++ b/src/aws-cpp-sdk-core/include/aws/core/endpoint/EndpointProviderBase.h @@ -70,7 +70,9 @@ namespace Aws virtual ResolveEndpointOutcome ResolveEndpoint(const EndpointParameters& endpointParameters) const = 0; }; - // Export symbol from the DLL: - template class AWS_CORE_API EndpointProviderBase >; + /** + * Export endpoint provider symbols for Windows DLL, otherwise declare as extern + */ + AWS_CORE_EXTERN template class AWS_CORE_API EndpointProviderBase>; } // namespace Endpoint } // namespace Aws diff --git a/src/aws-cpp-sdk-core/source/endpoint/DefaultEndpointProvider.cpp b/src/aws-cpp-sdk-core/source/endpoint/DefaultEndpointProvider.cpp index 58370cd4256..6f1fefb775c 100644 --- a/src/aws-cpp-sdk-core/source/endpoint/DefaultEndpointProvider.cpp +++ b/src/aws-cpp-sdk-core/source/endpoint/DefaultEndpointProvider.cpp @@ -12,13 +12,17 @@ namespace Aws namespace Endpoint { +#ifndef AWS_CORE_EXPORTS // Except for Windows DLL /** - * Export endpoint provider symbols from DLL + * Instantiate endpoint providers */ -template class AWS_CORE_API DefaultEndpointProvider, +template class DefaultEndpointProvider, Aws::Endpoint::BuiltInParameters, Aws::Endpoint::ClientContextParameters>; +template class DefaultEndpointProvider>; +#endif + char CharToDec(const char c) { if(c >= '0' && c <= '9') diff --git a/src/aws-cpp-sdk-core/source/endpoint/EndpointProviderBase.cpp b/src/aws-cpp-sdk-core/source/endpoint/EndpointProviderBase.cpp index 0928186839a..92f51df1cf3 100644 --- a/src/aws-cpp-sdk-core/source/endpoint/EndpointProviderBase.cpp +++ b/src/aws-cpp-sdk-core/source/endpoint/EndpointProviderBase.cpp @@ -9,12 +9,15 @@ namespace Aws { namespace Endpoint { +#ifndef AWS_CORE_EXPORTS // Except for Windows DLL /** - * Export endpoint provider symbols from DLL + * Instantiate endpoint providers */ -template class AWS_CORE_API EndpointProviderBase, +template class EndpointProviderBase, Aws::Endpoint::BuiltInParameters, Aws::Endpoint::ClientContextParameters>; +template class EndpointProviderBase>; +#endif } // namespace Endpoint } // namespace Aws diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ServiceExportHeader.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ServiceExportHeader.vm index 9b8f76827c6..e11421d2de1 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ServiceExportHeader.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/ServiceExportHeader.vm @@ -21,9 +21,12 @@ \#else $define ${api} __declspec(dllimport) #endif /* AWS_${metadata.classNamePrefix.toUpperCase()}_EXPORTS */ + $define AWS_${metadata.classNamePrefix.toUpperCase()}_EXTERN \#else $define ${api} + $define AWS_${metadata.classNamePrefix.toUpperCase()}_EXTERN extern #endif // USE_IMPORT_EXPORT \#else // defined (USE_WINDOWS_DLL_SEMANTICS) || defined (WIN32) $define ${api} + $define AWS_${metadata.classNamePrefix.toUpperCase()}_EXTERN extern #endif // defined (USE_WINDOWS_DLL_SEMANTICS) || defined (WIN32) diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/endpoint/EndpointProviderHeader.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/endpoint/EndpointProviderHeader.vm index 4d79e28f56f..5937fabb1f7 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/endpoint/EndpointProviderHeader.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/endpoint/EndpointProviderHeader.vm @@ -7,6 +7,7 @@ #set($epContextClassName = "${metadata.classNamePrefix}ClientContextParameters") #set($epBuiltInClassName = "${metadata.classNamePrefix}BuiltInParameters") #set($exportMacro = "${CppViewHelper.computeExportValue($metadata.classNamePrefix)}") +#set($externMacro = "AWS_${metadata.classNamePrefix.toUpperCase()}_EXTERN") #pragma once \#include #if($serviceModel.metadata.serviceId == "S3" || $serviceModel.metadata.serviceId == "S3 Control") @@ -101,12 +102,12 @@ using ${metadata.classNamePrefix}DefaultEpProviderBase = namespace Endpoint { /** - * Export endpoint provider symbols from DLL + * Export endpoint provider symbols for Windows DLL, otherwise declare as extern */ -template class ${exportMacro} +${externMacro} template class ${exportMacro} Aws::Endpoint::EndpointProviderBase<${serviceNamespace}::Endpoint::${metadata.classNamePrefix}ClientConfiguration, ${serviceNamespace}::Endpoint::${epBuiltInClassName}, ${serviceNamespace}::Endpoint::${epContextClassName}>; -template class ${exportMacro} +${externMacro} template class ${exportMacro} Aws::Endpoint::DefaultEndpointProvider<${serviceNamespace}::Endpoint::${metadata.classNamePrefix}ClientConfiguration, ${serviceNamespace}::Endpoint::${epBuiltInClassName}, ${serviceNamespace}::Endpoint::${epContextClassName}>; } // namespace Endpoint diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/endpoint/EndpointProviderSource.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/endpoint/EndpointProviderSource.vm index 402a7bb457a..0c8c6184703 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/endpoint/EndpointProviderSource.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/endpoint/EndpointProviderSource.vm @@ -10,6 +10,24 @@ namespace ${rootNamespace} { +#if($serviceModel.metadata.serviceId == "S3" || $serviceModel.metadata.serviceId == "S3 Control" || $serviceModel.clientContextParams) +#ifndef AWS_${metadata.classNamePrefix.toUpperCase()}_EXPORTS // Except for Windows DLL +namespace Endpoint +{ +/** + * Instantiate endpoint providers + */ +template class Aws::Endpoint::EndpointProviderBase<${serviceNamespace}::Endpoint::${metadata.classNamePrefix}ClientConfiguration, + ${serviceNamespace}::Endpoint::${epBuiltInClassName}, + ${serviceNamespace}::Endpoint::${epContextClassName}>; + +template class Aws::Endpoint::DefaultEndpointProvider<${serviceNamespace}::Endpoint::${metadata.classNamePrefix}ClientConfiguration, + ${serviceNamespace}::Endpoint::${epBuiltInClassName}, + ${serviceNamespace}::Endpoint::${epContextClassName}>; +} // namespace Endpoint +#endif + +#end namespace ${serviceNamespace} { namespace Endpoint