Compile miniglog into Ceres if enabled on all platforms. - Previously if miniglog was being used (on a non-Android system), we compiled it into a separate library, against which Ceres then linked. - This was unsatisfactory as it required miniglog being built as a static library when building Ceres as a Windows DLL, because miniglog did not use the dllexport/dllimport statements, whilst for other platforms when building Ceres as a shared library, miniglog needed to be compiled as a shared library. - We now compile miniglog into Ceres on all platforms, not just on Android. - miniglog now uses the CERES_EXPORT macro to support Windows DLLs. This means that miniglog now depends on Ceres' internal/port.h (and thus internal/config.h) which define the CERES_EXPORT macro and control its behaviour respectively. - miniglog now also uses localtime_s, not localtime on Windows. Change-Id: Ia55b9af8b4e6decf067eab92f0a5c2d14358a1e9
diff --git a/CMakeLists.txt b/CMakeLists.txt index fba40ce..8606286 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -142,11 +142,11 @@ # to config the cmake. The PLATFORM can be one of OS, SIMULATOR and SIMULATOR64. # Check the documentation in iOS.cmake to find more options. # -# After building, you will get libceres.a and libminiglog.a -# You need to add these two libraries into your xcode project. +# After building, you will get a single library: libceres.a, which +# you need to add to your Xcode project. # # If you use the lapack and blas, then you also need to add Accelerate.framework -# to your xcode project's linking dependency. +# to your Xcode project's linking dependency. IF (IOS) MESSAGE(STATUS "Building Ceres for iOS platform: ${IOS_PLATFORM}") @@ -361,10 +361,9 @@ # MiniGLog. IF (MINIGLOG) - SET(GLOG_LIBRARIES miniglog) - MESSAGE("-- Using minimal Glog substitute (library): ${GLOG_LIBRARIES}") + MESSAGE("-- Compiling minimal glog substitute into Ceres.") SET(GLOG_INCLUDE_DIRS internal/ceres/miniglog) - MESSAGE("-- Using minimal Glog substitute (include): ${GLOG_INCLUDE_DIRS}") + MESSAGE("-- Using minimal glog substitute (include): ${GLOG_INCLUDE_DIRS}") # Mark as advanced (remove from default GUI view) the glog search # variables in case user disables MINIGLOG, FindGlog did not find it, so
diff --git a/docs/source/building.rst b/docs/source/building.rst index eb0cd5b..2c187b9 100644 --- a/docs/source/building.rst +++ b/docs/source/building.rst
@@ -368,13 +368,13 @@ ``SIMULATOR64`` (``x86_64``) separately and use ``LIPO`` to merge them into one static library. See ``cmake/iOS.cmake`` for more options. -After building, you will get ``libceres.a`` and ``libminiglog.a`` -You need to add these two libraries into your XCode project. +After building, you will get a ``libceres.a`` library, which you will need to +add to your Xcode project. The default CMake configuration builds a bare bones version of Ceres -Solver that only depends on Eigen and MINIGLOG, this should be -sufficient for solving small to moderate sized problems (No -``SPARSE_SCHUR``, ``SPARSE_NORMAL_CHOLESKY`` linear solvers and no +Solver that only depends on Eigen (``MINIGLOG`` is compiled into Ceres if it is +used), this should be sufficient for solving small to moderate sized problems +(No ``SPARSE_SCHUR``, ``SPARSE_NORMAL_CHOLESKY`` linear solvers and no ``CLUSTER_JACOBI`` and ``CLUSTER_TRIDIAGONAL`` preconditioners). If you decide to use ``LAPACK`` and ``BLAS``, then you also need to add
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index 89757b3..4d4f873 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -136,24 +136,10 @@ FILE(GLOB CERES_INTERNAL_SCHUR_FILES generated/*_d_d_d.cc) ENDIF (SCHUR_SPECIALIZATIONS) -# Primarily for Android, but optionally for others, use the minimal internal -# Glog implementation. -IF (MINIGLOG) - IF (MSVC) - # Miniglog needs to be built statically with Visual Studio since it - # doesn't export any symbols with dllexport/dllimport. - ADD_LIBRARY(miniglog STATIC miniglog/glog/logging.cc) - ELSE() - ADD_LIBRARY(miniglog miniglog/glog/logging.cc) - ENDIF() - INSTALL(TARGETS miniglog - EXPORT CeresExport - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) -ENDIF (MINIGLOG) - -SET(CERES_LIBRARY_PUBLIC_DEPENDENCIES ${GLOG_LIBRARIES}) +# Build the list of dependencies for Ceres based on the current configuration. +IF (NOT MINIGLOG AND GLOG_FOUND) + LIST(APPEND CERES_LIBRARY_PUBLIC_DEPENDENCIES ${GLOG_LIBRARIES}) +ENDIF (NOT MINIGLOG AND GLOG_FOUND) IF (SUITESPARSE AND SUITESPARSE_FOUND) LIST(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES ${SUITESPARSE_LIBRARIES}) @@ -180,6 +166,12 @@ ${CERES_INTERNAL_HDRS} ${CERES_INTERNAL_SCHUR_FILES}) +# Primarily for Android, but optionally for others, compile the minimal +# glog implementation into Ceres. +IF (MINIGLOG) + LIST(APPEND CERES_LIBRARY_SOURCE miniglog/glog/logging.cc) +ENDIF (MINIGLOG) + ADD_LIBRARY(ceres ${CERES_LIBRARY_SOURCE}) SET_TARGET_PROPERTIES(ceres PROPERTIES VERSION ${CERES_VERSION} @@ -215,8 +207,15 @@ numeric_diff_test_utils.cc test_util.cc) - TARGET_LINK_LIBRARIES(gtest ${GFLAGS_LIBRARIES} ${GLOG_LIBRARIES}) - TARGET_LINK_LIBRARIES(test_util ceres gtest ${GLOG_LIBRARIES}) + IF (MINIGLOG) + # When using miniglog, it is compiled into Ceres, thus Ceres becomes + # the library against which other libraries should link for logging. + TARGET_LINK_LIBRARIES(gtest ${GFLAGS_LIBRARIES} ceres) + TARGET_LINK_LIBRARIES(test_util ceres gtest) + ELSE (MINIGLOG) + TARGET_LINK_LIBRARIES(gtest ${GFLAGS_LIBRARIES} ${GLOG_LIBRARIES}) + TARGET_LINK_LIBRARIES(test_util ceres gtest ${GLOG_LIBRARIES}) + ENDIF (MINIGLOG) MACRO (CERES_TEST NAME) ADD_EXECUTABLE(${NAME}_test ${NAME}_test.cc)
diff --git a/internal/ceres/miniglog/glog/logging.h b/internal/ceres/miniglog/glog/logging.h index e43d05e..e9c0dff 100644 --- a/internal/ceres/miniglog/glog/logging.h +++ b/internal/ceres/miniglog/glog/logging.h
@@ -105,6 +105,10 @@ #include <string> #include <vector> +// For appropriate definition of CERES_EXPORT macro. +#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" + // Log severity level constants. const int FATAL = -3; const int ERROR = -2; @@ -125,7 +129,7 @@ // added, all log output is also sent to each sink through the send function. // In this implementation, WaitTillSent() is called immediately after the send. // This implementation is not thread safe. -class LogSink { +class CERES_EXPORT LogSink { public: virtual ~LogSink() {} virtual void send(LogSeverity severity, @@ -139,7 +143,7 @@ }; // Global set of log sinks. The actual object is defined in logging.cc. -extern std::set<LogSink *> log_sinks_global; +extern CERES_EXPORT std::set<LogSink *> log_sinks_global; inline void InitGoogleLogging(char *argv) { // Do nothing; this is ignored. @@ -164,7 +168,7 @@ // defined, output is directed to std::cerr. This class should not // be directly instantiated in code, rather it should be invoked through the // use of the log macros LG, LOG, or VLOG. -class MessageLogger { +class CERES_EXPORT MessageLogger { public: MessageLogger(const char *file, int line, const char *tag, int severity) : file_(file), line_(line), tag_(tag), severity_(severity) { @@ -223,10 +227,18 @@ private: void LogToSinks(int severity) { time_t rawtime; - struct tm* timeinfo; - time (&rawtime); + + struct tm* timeinfo; +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + // On Windows, use secure localtime_s not localtime. + struct tm windows_timeinfo; + timeinfo = &windows_timeinfo; + localtime_s(timeinfo, &rawtime); +#else timeinfo = localtime(&rawtime); +#endif + std::set<google::LogSink*>::iterator iter; // Send the log message to all sinks. for (iter = google::log_sinks_global.begin(); @@ -271,7 +283,7 @@ // This class is used to explicitly ignore values in the conditional // logging macros. This avoids compiler warnings like "value computed // is not used" and "statement has no effect". -class LoggerVoidify { +class CERES_EXPORT LoggerVoidify { public: LoggerVoidify() { } // This has to be an operator with a precedence lower than << but @@ -409,4 +421,6 @@ CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val)) #endif // NDEBUG +#include "ceres/internal/reenable_warnings.h" + #endif // CERCES_INTERNAL_MINIGLOG_GLOG_LOGGING_H_