From 9b92e68d71153c6dea2bf11ae08791e620c12b6e Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Fri, 29 Mar 2019 10:29:44 +0100 Subject: [PATCH] Add an option to override the namespace used for spirv_cross. This is a pragmatic trick to avoid symbol collision where a project links against SPIRV-Cross statically, while linking to other projects which also use SPIRV-Cross statically. We can end up with very awkward symbol collisions which can resolve themselves silently because SPIRV-Cross is pulled in as necessary. To fix this, we must use different symbols and embed two copies of SPIRV-Cross in this scenario, now with different namespaces, which in turn leads to different symbols. --- CMakeLists.txt | 27 ++++++++++++++++++++++----- main.cpp | 2 +- spirv_cfg.cpp | 2 +- spirv_cfg.hpp | 2 +- spirv_common.hpp | 18 +++++++++++++++++- spirv_cpp.cpp | 2 +- spirv_cpp.hpp | 2 +- spirv_cross.cpp | 8 ++++---- spirv_cross.hpp | 2 +- spirv_cross_c.cpp | 2 +- spirv_cross_parsed_ir.cpp | 2 +- spirv_cross_parsed_ir.hpp | 2 +- spirv_cross_util.cpp | 6 +++--- spirv_cross_util.hpp | 4 ++-- spirv_glsl.cpp | 6 +++--- spirv_glsl.hpp | 2 +- spirv_hlsl.cpp | 2 +- spirv_hlsl.hpp | 2 +- spirv_msl.cpp | 2 +- spirv_msl.hpp | 2 +- spirv_parser.cpp | 2 +- spirv_parser.hpp | 2 +- spirv_reflect.cpp | 2 +- spirv_reflect.hpp | 2 +- 24 files changed, 69 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6547f491..057ed17a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,8 @@ option(SPIRV_CROSS_SANITIZE_MEMORY "Sanitize memory" OFF) option(SPIRV_CROSS_SANITIZE_THREADS "Sanitize threads" OFF) option(SPIRV_CROSS_SANITIZE_UNDEFINED "Sanitize undefined" OFF) +option(SPIRV_CROSS_NAMESPACE_OVERRIDE "" "Override the namespace used in the C++ API.") + if(${CMAKE_GENERATOR} MATCHES "Makefile") if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) message(FATAL_ERROR "Build out of tree to avoid overwriting Makefile") @@ -99,8 +101,8 @@ macro(extract_headers out_abs file_list) endforeach() endmacro() -macro(spirv_cross_add_library name config_name) - add_library(${name} ${ARGN}) +macro(spirv_cross_add_library name config_name library_type) + add_library(${name} ${library_type} ${ARGN}) extract_headers(hdrs "${ARGN}") target_include_directories(${name} PUBLIC $ @@ -109,6 +111,13 @@ macro(spirv_cross_add_library name config_name) PUBLIC_HEADERS "${hdrs}") target_compile_options(${name} PRIVATE ${spirv-compiler-options}) target_compile_definitions(${name} PRIVATE ${spirv-compiler-defines}) + if (SPIRV_CROSS_NAMESPACE_OVERRIDE) + if (${library_type} MATCHES "STATIC") + target_compile_definitions(${name} PUBLIC SPIRV_CROSS_NAMESPACE_OVERRIDE=${SPIRV_CROSS_NAMESPACE_OVERRIDE}) + else() + target_compile_definitions(${name} PRIVATE SPIRV_CROSS_NAMESPACE_OVERRIDE=${SPIRV_CROSS_NAMESPACE_OVERRIDE}) + endif() + endif() install(TARGETS ${name} EXPORT ${config_name}Config RUNTIME DESTINATION bin @@ -184,8 +193,12 @@ if (SPIRV_CROSS_STATIC) endif() if (SPIRV_CROSS_ENABLE_REFLECT) - spirv_cross_add_library(spirv-cross-reflect spirv_cross_reflect STATIC - ${spirv-cross-reflect-sources}) + if (SPIRV_CROSS_ENABLE_GLSL) + spirv_cross_add_library(spirv-cross-reflect spirv_cross_reflect STATIC + ${spirv-cross-reflect-sources}) + else() + message(FATAL_ERROR "Must enable GLSL support to enable JSON reflection support.") + endif() endif() if (SPIRV_CROSS_ENABLE_MSL) @@ -294,7 +307,11 @@ if (SPIRV_CROSS_SHARED) endif() if (SPIRV_CROSS_ENABLE_REFLECT) - target_sources(spirv-cross-c-shared PRIVATE ${spirv-cross-reflect-sources}) + if (SPIRV_CROSS_ENABLE_GLSL) + target_sources(spirv-cross-c-shared PRIVATE ${spirv-cross-reflect-sources}) + else() + message(FATAL_ERROR "Must enable GLSL support to enable JSON reflection support.") + endif() target_compile_definitions(spirv-cross-c-shared PRIVATE SPIRV_CROSS_C_API_REFLECT=1) endif() diff --git a/main.cpp b/main.cpp index 877ce683..45e512ea 100644 --- a/main.cpp +++ b/main.cpp @@ -36,7 +36,7 @@ #endif using namespace spv; -using namespace spirv_cross; +using namespace SPIRV_CROSS_NAMESPACE; using namespace std; #ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS diff --git a/spirv_cfg.cpp b/spirv_cfg.cpp index 4ca9ef56..cee3ee22 100644 --- a/spirv_cfg.cpp +++ b/spirv_cfg.cpp @@ -21,7 +21,7 @@ using namespace std; -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { CFG::CFG(Compiler &compiler_, const SPIRFunction &func_) : compiler(compiler_) diff --git a/spirv_cfg.hpp b/spirv_cfg.hpp index 5e893204..359f8374 100644 --- a/spirv_cfg.hpp +++ b/spirv_cfg.hpp @@ -20,7 +20,7 @@ #include "spirv_common.hpp" #include -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { class Compiler; class CFG diff --git a/spirv_common.hpp b/spirv_common.hpp index dcd27aff..0b549076 100644 --- a/spirv_common.hpp +++ b/spirv_common.hpp @@ -35,7 +35,23 @@ #include #include -namespace spirv_cross +// A bit crude, but allows projects which embed SPIRV-Cross statically to +// effectively hide all the symbols from other projects. +// There is a case where we have: +// - Project A links against SPIRV-Cross statically. +// - Project A links against Project B statically. +// - Project B links against SPIRV-Cross statically (might be a different version). +// This leads to a conflict with extremely bizarre results. +// By overriding the namespace in one of the project builds, we can work around this. +// If SPIRV-Cross is embedded in dynamic libraries, +// prefer using -fvisibility=hidden on GCC/Clang instead. +#ifdef SPIRV_CROSS_NAMESPACE_OVERRIDE +#define SPIRV_CROSS_NAMESPACE SPIRV_CROSS_NAMESPACE_OVERRIDE +#else +#define SPIRV_CROSS_NAMESPACE spirv_cross +#endif + +namespace SPIRV_CROSS_NAMESPACE { #ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS diff --git a/spirv_cpp.cpp b/spirv_cpp.cpp index 1b791ee5..40424857 100644 --- a/spirv_cpp.cpp +++ b/spirv_cpp.cpp @@ -17,7 +17,7 @@ #include "spirv_cpp.hpp" using namespace spv; -using namespace spirv_cross; +using namespace SPIRV_CROSS_NAMESPACE; using namespace std; void CompilerCPP::emit_buffer_block(const SPIRVariable &var) diff --git a/spirv_cpp.hpp b/spirv_cpp.hpp index bcdb669b..414bc5b4 100644 --- a/spirv_cpp.hpp +++ b/spirv_cpp.hpp @@ -21,7 +21,7 @@ #include #include -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { class CompilerCPP : public CompilerGLSL { diff --git a/spirv_cross.cpp b/spirv_cross.cpp index 7ca2fe1a..f3a657f6 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -24,7 +24,7 @@ using namespace std; using namespace spv; -using namespace spirv_cross; +using namespace SPIRV_CROSS_NAMESPACE; Compiler::Compiler(vector ir_) { @@ -3825,7 +3825,7 @@ void Compiler::build_function_control_flow_graphs_and_analyze() } } -Compiler::CFGBuilder::CFGBuilder(spirv_cross::Compiler &compiler_) +Compiler::CFGBuilder::CFGBuilder(Compiler &compiler_) : compiler(compiler_) { } @@ -4109,12 +4109,12 @@ bool Compiler::is_desktop_only_format(spv::ImageFormat format) return false; } -bool Compiler::image_is_comparison(const spirv_cross::SPIRType &type, uint32_t id) const +bool Compiler::image_is_comparison(const SPIRType &type, uint32_t id) const { return type.image.depth || (comparison_ids.count(id) != 0); } -bool Compiler::type_is_opaque_value(const spirv_cross::SPIRType &type) const +bool Compiler::type_is_opaque_value(const SPIRType &type) const { return !type.pointer && (type.basetype == SPIRType::SampledImage || type.basetype == SPIRType::Image || type.basetype == SPIRType::Sampler); diff --git a/spirv_cross.hpp b/spirv_cross.hpp index 4edc8367..9ba43916 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -21,7 +21,7 @@ #include "spirv_cfg.hpp" #include "spirv_cross_parsed_ir.hpp" -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { struct Resource { diff --git a/spirv_cross_c.cpp b/spirv_cross_c.cpp index f41d216e..3ea4c6c3 100644 --- a/spirv_cross_c.cpp +++ b/spirv_cross_c.cpp @@ -63,7 +63,7 @@ #endif using namespace std; -using namespace spirv_cross; +using namespace SPIRV_CROSS_NAMESPACE; struct ScratchMemoryAllocation { diff --git a/spirv_cross_parsed_ir.cpp b/spirv_cross_parsed_ir.cpp index f17c2bec..201121bf 100644 --- a/spirv_cross_parsed_ir.cpp +++ b/spirv_cross_parsed_ir.cpp @@ -21,7 +21,7 @@ using namespace std; using namespace spv; -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { void ParsedIR::set_id_bounds(uint32_t bounds) { diff --git a/spirv_cross_parsed_ir.hpp b/spirv_cross_parsed_ir.hpp index c3c4612e..317405d5 100644 --- a/spirv_cross_parsed_ir.hpp +++ b/spirv_cross_parsed_ir.hpp @@ -22,7 +22,7 @@ #include #include -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { // This data structure holds all information needed to perform cross-compilation and reflection. diff --git a/spirv_cross_util.cpp b/spirv_cross_util.cpp index 58c1ddc2..6d520196 100644 --- a/spirv_cross_util.cpp +++ b/spirv_cross_util.cpp @@ -18,11 +18,11 @@ #include "spirv_common.hpp" using namespace spv; -using namespace spirv_cross; +using namespace SPIRV_CROSS_NAMESPACE; namespace spirv_cross_util { -void rename_interface_variable(spirv_cross::Compiler &compiler, const std::vector &resources, +void rename_interface_variable(Compiler &compiler, const std::vector &resources, uint32_t location, const std::string &name) { for (auto &v : resources) @@ -49,7 +49,7 @@ void rename_interface_variable(spirv_cross::Compiler &compiler, const std::vecto } } -void inherit_combined_sampler_bindings(spirv_cross::Compiler &compiler) +void inherit_combined_sampler_bindings(Compiler &compiler) { auto &samplers = compiler.get_combined_image_samplers(); for (auto &s : samplers) diff --git a/spirv_cross_util.hpp b/spirv_cross_util.hpp index faf0f487..e8eeaf07 100644 --- a/spirv_cross_util.hpp +++ b/spirv_cross_util.hpp @@ -21,9 +21,9 @@ namespace spirv_cross_util { -void rename_interface_variable(spirv_cross::Compiler &compiler, const std::vector &resources, +void rename_interface_variable(SPIRV_CROSS_NAMESPACE::Compiler &compiler, const std::vector &resources, uint32_t location, const std::string &name); -void inherit_combined_sampler_bindings(spirv_cross::Compiler &compiler); +void inherit_combined_sampler_bindings(SPIRV_CROSS_NAMESPACE::Compiler &compiler); } // namespace spirv_cross_util #endif diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index f35c7d8a..c8bf7e0e 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -30,7 +30,7 @@ #include using namespace spv; -using namespace spirv_cross; +using namespace SPIRV_CROSS_NAMESPACE; using namespace std; static bool is_unsigned_opcode(Op op) @@ -11348,7 +11348,7 @@ void CompilerGLSL::unroll_array_from_complex_load(uint32_t target_id, uint32_t s } void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &expr, - const spirv_cross::SPIRType &expr_type) + const SPIRType &expr_type) { auto *var = maybe_get_backing_variable(source_id); if (var) @@ -11396,7 +11396,7 @@ void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &ex } void CompilerGLSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr, - const spirv_cross::SPIRType &expr_type) + const SPIRType &expr_type) { // Only interested in standalone builtin variables. if (!has_decoration(target_id, DecorationBuiltIn)) diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index 33e35475..af61b370 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -24,7 +24,7 @@ #include #include -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { enum PlsFormat { diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index 3f6b6278..0cbf75b2 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -20,7 +20,7 @@ #include using namespace spv; -using namespace spirv_cross; +using namespace SPIRV_CROSS_NAMESPACE; using namespace std; static unsigned image_format_to_components(ImageFormat fmt) diff --git a/spirv_hlsl.hpp b/spirv_hlsl.hpp index 12b8ae11..6d8449f5 100644 --- a/spirv_hlsl.hpp +++ b/spirv_hlsl.hpp @@ -21,7 +21,7 @@ #include #include -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { // Interface which remaps vertex inputs to a fixed semantic name to make linking easier. struct HLSLVertexAttributeRemap diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 41a3aaa6..58c198dc 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -22,7 +22,7 @@ #include using namespace spv; -using namespace spirv_cross; +using namespace SPIRV_CROSS_NAMESPACE; using namespace std; static const uint32_t k_unknown_location = ~0u; diff --git a/spirv_msl.hpp b/spirv_msl.hpp index 38610e15..13364041 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -24,7 +24,7 @@ #include #include -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { // Indicates the format of the vertex attribute. Currently limited to specifying diff --git a/spirv_parser.cpp b/spirv_parser.cpp index fa87fa37..a82d05be 100644 --- a/spirv_parser.cpp +++ b/spirv_parser.cpp @@ -20,7 +20,7 @@ using namespace std; using namespace spv; -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { Parser::Parser(std::vector spirv) { diff --git a/spirv_parser.hpp b/spirv_parser.hpp index cc153152..aff7712e 100644 --- a/spirv_parser.hpp +++ b/spirv_parser.hpp @@ -21,7 +21,7 @@ #include #include -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { class Parser { diff --git a/spirv_reflect.cpp b/spirv_reflect.cpp index c6cd3be3..c93de300 100644 --- a/spirv_reflect.cpp +++ b/spirv_reflect.cpp @@ -19,7 +19,7 @@ #include using namespace spv; -using namespace spirv_cross; +using namespace SPIRV_CROSS_NAMESPACE; using namespace std; namespace simple_json diff --git a/spirv_reflect.hpp b/spirv_reflect.hpp index 13b5b431..899a16e6 100644 --- a/spirv_reflect.hpp +++ b/spirv_reflect.hpp @@ -26,7 +26,7 @@ namespace simple_json class Stream; } -namespace spirv_cross +namespace SPIRV_CROSS_NAMESPACE { class CompilerReflection : public CompilerGLSL {