Fix windows MSVC build.
This CL improves the build experience with MSVC:
- It adds the build flag '/bigobj' otherwise the build of
the unit test fails.
- It adds the flag '/wd4267' to suppress signed / unsigned int
conversions (size_t to int).
- It removes the use of std::aligned_storage from FixedArray.
This has been done from the Abseil Team and is in the
absl::FixedArray. Those changes has been ported to ceres.
This fixes the alignemnt for older MSVC versions due to a
bug in the implementation of std::aligned_storage, and
prevents the use of the macro '_ENABLE_EXTENDED_ALIGNED_STORAGE'
for newer MSVC versions, which is problematic as it could affect
user code.
- Fix of the fixed array unit test. Due to the use of std::tuple
instead of absl::tuple in ceres::internal::FixedArray, the
unit test needs to reflect that change as well.
- Replaces 'add_definitions' with 'add_compile_options' for
compiler flags as suggested by the cmake documentation.
Change-Id: I63f08cd6c0a8db8c9931289b909b4deafd75b039
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b25cee3..f11e579 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -527,25 +527,30 @@
# [1] https://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
add_definitions("-D_USE_MATH_DEFINES")
# Disable signed/unsigned int conversion warnings.
- add_definitions("/wd4018")
+ add_compile_options("/wd4018" "/wd4267")
# Disable warning about using struct/class for the same symobl.
- add_definitions("/wd4099")
+ add_compile_options("/wd4099")
# Disable warning about the insecurity of using "std::copy".
- add_definitions("/wd4996")
+ add_compile_options("/wd4996")
# Disable performance warning about int-to-bool conversion.
- add_definitions("/wd4800")
+ add_compile_options("/wd4800")
# Disable performance warning about fopen insecurity.
- add_definitions("/wd4996")
+ add_compile_options("/wd4996")
# Disable warning about int64 to int32 conversion. Disabling
# this warning may not be correct; needs investigation.
# TODO(keir): Investigate these warnings in more detail.
- add_definitions("/wd4244")
+ add_compile_options("/wd4244")
# It's not possible to use STL types in DLL interfaces in a portable and
# reliable way. However, that's what happens with Google Log and Google Flags
# on Windows. MSVC gets upset about this and throws warnings that we can't do
# much about. The real solution is to link static versions of Google Log and
# Google Test, but that seems tricky on Windows. So, disable the warning.
- add_definitions("/wd4251")
+ add_compile_options("/wd4251")
+
+ # Add bigobj flag otherwise the build would fail due to large object files
+ # probably resulting from generated headers (like the fixed-size schur
+ # specializations).
+ add_compile_options("/bigobj")
# Google Flags doesn't have their DLL import/export stuff set up correctly,
# which results in linker warnings. This is irrelevant for Ceres, so ignore
diff --git a/include/ceres/internal/fixed_array.h b/include/ceres/internal/fixed_array.h
index c107dfc..15481f3 100644
--- a/include/ceres/internal/fixed_array.h
+++ b/include/ceres/internal/fixed_array.h
@@ -163,8 +163,7 @@
CopyRange(storage_.alloc(), storage_.begin(), first, last);
}
- // Releases any resources.
- ~FixedArray() {
+ ~FixedArray() noexcept {
for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {
AllocatorTraits::destroy(storage_.alloc(), cur);
}
@@ -358,7 +357,7 @@
// error: call to int __builtin___sprintf_chk(etc...)
// will always overflow destination buffer [-Werror]
//
- template <typename OuterT = value_type,
+ template <typename OuterT,
typename InnerT = typename std::remove_extent<OuterT>::type,
size_t InnerN = std::extent<OuterT>::value>
struct StorageElementWrapper {
@@ -369,9 +368,6 @@
typename std::conditional<std::is_array<value_type>::value,
StorageElementWrapper<value_type>,
value_type>::type;
- using StorageElementBuffer =
- typename std::aligned_storage<sizeof(StorageElement),
- alignof(StorageElement)>::type;
static pointer AsValueType(pointer ptr) { return ptr; }
static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
@@ -381,25 +377,25 @@
static_assert(sizeof(StorageElement) == sizeof(value_type), "");
static_assert(alignof(StorageElement) == alignof(value_type), "");
- struct NonEmptyInlinedStorage {
- StorageElement* data() {
- return reinterpret_cast<StorageElement*>(inlined_storage_.data());
- }
+ class NonEmptyInlinedStorage {
+ public:
+ StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
+ void AnnotateConstruct(size_type) {}
+ void AnnotateDestruct(size_type) {}
// #ifdef ADDRESS_SANITIZER
// void* RedzoneBegin() { return &redzone_begin_; }
// void* RedzoneEnd() { return &redzone_end_ + 1; }
// #endif // ADDRESS_SANITIZER
- void AnnotateConstruct(size_type) {}
- void AnnotateDestruct(size_type) {}
-
+ private:
// ADDRESS_SANITIZER_REDZONE(redzone_begin_);
- std::array<StorageElementBuffer, inline_elements> inlined_storage_;
+ alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
// ADDRESS_SANITIZER_REDZONE(redzone_end_);
};
- struct EmptyInlinedStorage {
+ class EmptyInlinedStorage {
+ public:
StorageElement* data() { return nullptr; }
void AnnotateConstruct(size_type) {}
void AnnotateDestruct(size_type) {}
@@ -460,6 +456,13 @@
Storage storage_;
};
+template <typename T, size_t N, typename A>
+constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
+
+template <typename T, size_t N, typename A>
+constexpr typename FixedArray<T, N, A>::size_type
+ FixedArray<T, N, A>::inline_elements;
+
} // namespace internal
} // namespace ceres
diff --git a/internal/ceres/fixed_array_test.cc b/internal/ceres/fixed_array_test.cc
index 79ae511..95cba7f 100644
--- a/internal/ceres/fixed_array_test.cc
+++ b/internal/ceres/fixed_array_test.cc
@@ -477,8 +477,8 @@
// Simulate the data members of ceres::internal::FixedArray, a pointer and a
// size_t.
struct Data {
+ std::tuple<size_t, std::allocator<double>> size_alloc_;
TooBig* p;
- size_t size;
};
// Make sure TooBig objects are not inlined for 0 or default size.