From b7bca8663ac86fbade802ce4d7c835f45bb98807 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 28 Nov 2013 23:24:55 +0600 Subject: [PATCH] Made collections port compatible with MSVC2008 The issue was caused by the fact that in this version of MSVC unordered_map class is defined in header file, but this file declares the class int std::tr1 namespace. This confused existing assumption that if there's an existing file then class is declared in std namespace. Added an extra check to CMake which detects whether it's std or std::tr1 which actually contains class of unordered_map. This might be changed/cleaned in the future, for now committing to our repository to solve compilation error on windows. Details of the patch in upstream can be found there: https://ceres-solver-review.googlesource.com/#/c/4371/ --- extern/libmv/third_party/ceres/CMakeLists.txt | 30 ++++++++++++-- extern/libmv/third_party/ceres/SConscript | 9 +++- extern/libmv/third_party/ceres/bundle.sh | 41 +++++++++++++++++-- .../ceres/internal/ceres/collections_port.h | 16 ++++++-- 4 files changed, 85 insertions(+), 11 deletions(-) diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt index a05c424df49..45e1f9b398d 100644 --- a/extern/libmv/third_party/ceres/CMakeLists.txt +++ b/extern/libmv/third_party/ceres/CMakeLists.txt @@ -310,9 +310,33 @@ if(WITH_OPENMP) endif() include(CheckIncludeFileCXX) -CHECK_INCLUDE_FILE_CXX(unordered_map UNORDERED_MAP_IN_STD_NAMESPACE) -if(UNORDERED_MAP_IN_STD_NAMESPACE) - ADD_DEFINITIONS(-DCERES_STD_UNORDERED_MAP) +CHECK_INCLUDE_FILE_CXX(unordered_map HAVE_STD_UNORDERED_MAP_HEADER) +if(HAVE_STD_UNORDERED_MAP_HEADER) + INCLUDE (CheckCXXSourceCompiles) + CHECK_CXX_SOURCE_COMPILES("#include + int main() { + std::unordered_map map; + return 0; + }" + HAVE_UNURDERED_MAP_IN_STD_NAMESPACE) + if(HAVE_UNURDERED_MAP_IN_STD_NAMESPACE) + ADD_DEFINITIONS(-DCERES_STD_UNORDERED_MAP) + else() + CHECK_CXX_SOURCE_COMPILES("#include + int main() { + std::tr1::unordered_map map; + return 0; + }" + HAVE_UNURDERED_MAP_IN_TR1_NAMESPACE) + if(HAVE_UNURDERED_MAP_IN_TR1_NAMESPACE) + ADD_DEFINITIONS(-DCERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) + else() + MESSAGE("-- Found but can not find neither std::unordered_map " + "nor std::tr1::unordered_map.") + MESSAGE("-- Replacing unordered_map/set with map/set (warning: slower!)") + ADD_DEFINITIONS(-DCERES_NO_UNORDERED_MAP) + endif() + endif() else() CHECK_INCLUDE_FILE_CXX("tr1/unordered_map" UNORDERED_MAP_IN_TR1_NAMESPACE) if(UNORDERED_MAP_IN_TR1_NAMESPACE) diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript index e61e979efd2..22960e7b3bd 100644 --- a/extern/libmv/third_party/ceres/SConscript +++ b/extern/libmv/third_party/ceres/SConscript @@ -29,7 +29,14 @@ if env['WITH_BF_OPENMP']: conf = Configure(env) if conf.CheckCXXHeader("unordered_map"): - defs.append('CERES_STD_UNORDERED_MAP') + if conf.CheckType('std::unordered_map', language = 'CXX', includes="#include "): + defs.append('CERES_STD_UNORDERED_MAP') + elif conf.CheckType('std::tr1::unordered_map', language = 'CXX', includes="#include "): + defs.append('CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE') + else: + print("-- Found but can not find neither std::unordered_map nor std::tr1::unordered_map.") + print("-- Replacing unordered_map/set with map/set (warning: slower!)") + defs.append('CERES_NO_UNORDERED_MAP') elif conf.CheckCXXHeader("tr1/unordered_map"): defs.append('CERES_TR1_UNORDERED_MAP') else: diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh index 10c70ec51f7..906c5d3dd48 100755 --- a/extern/libmv/third_party/ceres/bundle.sh +++ b/extern/libmv/third_party/ceres/bundle.sh @@ -175,9 +175,33 @@ if(WITH_OPENMP) endif() include(CheckIncludeFileCXX) -CHECK_INCLUDE_FILE_CXX(unordered_map UNORDERED_MAP_IN_STD_NAMESPACE) -if(UNORDERED_MAP_IN_STD_NAMESPACE) - ADD_DEFINITIONS(-DCERES_STD_UNORDERED_MAP) +CHECK_INCLUDE_FILE_CXX(unordered_map HAVE_STD_UNORDERED_MAP_HEADER) +if(HAVE_STD_UNORDERED_MAP_HEADER) + INCLUDE (CheckCXXSourceCompiles) + CHECK_CXX_SOURCE_COMPILES("#include + int main() { + std::unordered_map map; + return 0; + }" + HAVE_UNURDERED_MAP_IN_STD_NAMESPACE) + if(HAVE_UNURDERED_MAP_IN_STD_NAMESPACE) + ADD_DEFINITIONS(-DCERES_STD_UNORDERED_MAP) + else() + CHECK_CXX_SOURCE_COMPILES("#include + int main() { + std::tr1::unordered_map map; + return 0; + }" + HAVE_UNURDERED_MAP_IN_TR1_NAMESPACE) + if(HAVE_UNURDERED_MAP_IN_TR1_NAMESPACE) + ADD_DEFINITIONS(-DCERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) + else() + MESSAGE("-- Found but can not find neither std::unordered_map " + "nor std::tr1::unordered_map.") + MESSAGE("-- Replacing unordered_map/set with map/set (warning: slower!)") + ADD_DEFINITIONS(-DCERES_NO_UNORDERED_MAP) + endif() + endif() else() CHECK_INCLUDE_FILE_CXX("tr1/unordered_map" UNORDERED_MAP_IN_TR1_NAMESPACE) if(UNORDERED_MAP_IN_TR1_NAMESPACE) @@ -224,7 +248,14 @@ if env['WITH_BF_OPENMP']: conf = Configure(env) if conf.CheckCXXHeader("unordered_map"): - defs.append('CERES_STD_UNORDERED_MAP') + if conf.CheckType('std::unordered_map', language = 'CXX', includes="#include "): + defs.append('CERES_STD_UNORDERED_MAP') + elif conf.CheckType('std::tr1::unordered_map', language = 'CXX', includes="#include "): + defs.append('CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE') + else: + print("-- Found but can not find neither std::unordered_map nor std::tr1::unordered_map.") + print("-- Replacing unordered_map/set with map/set (warning: slower!)") + defs.append('CERES_NO_UNORDERED_MAP') elif conf.CheckCXXHeader("tr1/unordered_map"): defs.append('CERES_TR1_UNORDERED_MAP') else: @@ -232,6 +263,8 @@ else: print("-- Replacing unordered_map/set with map/set (warning: slower!)") defs.append('CERES_NO_UNORDERED_MAP') +env = conf.Finish() + incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags' # work around broken hashtable in 10.5 SDK diff --git a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h index 8f345d4d70a..e37be528ecb 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h +++ b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h @@ -52,8 +52,17 @@ # define CERES_HASH_NAMESPACE_END } #endif -#if !defined(CERES_NO_UNORDERED_MAP) && !defined(CERES_TR1_UNORDERED_MAP) && !defined(CERES_STD_UNORDERED_MAP) -#error One of: CERES_NO_UNORDERED_MAP, CERES_TR1_UNORDERED_MAP, CERES_STD_UNORDERED_MAP must be defined! +#if defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) +# include +# include +# define CERES_HASH_NAMESPACE_START namespace std { namespace tr1 { +# define CERES_HASH_NAMESPACE_END } } +#endif + +#if !defined(CERES_NO_UNORDERED_MAP) && !defined(CERES_TR1_UNORDERED_MAP) && \ + !defined(CERES_STD_UNORDERED_MAP) && !defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT +# error One of: CERES_NO_UNORDERED_MAP, CERES_TR1_UNORDERED_MAP,\ + CERES_STD_UNORDERED_MAP, CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT #endif #include @@ -82,7 +91,8 @@ struct HashSet : set {}; namespace ceres { namespace internal { -#if defined(CERES_TR1_UNORDERED_MAP) +#if defined(CERES_TR1_UNORDERED_MAP) || \ + defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) template struct HashMap : std::tr1::unordered_map {}; template