Suppport for MSVC DLLs. Change-Id: Ibbcc4ba4e59f5bbf1cb91fe81c7d3b9042d03493
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6acedd5..6f56f3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -111,6 +111,17 @@ IF (MSVC) OPTION(MSVC_USE_STATIC_CRT "MS Visual Studio: Use static C-Run Time Library in place of shared." OFF) + + IF ( BUILD_TESTING AND BUILD_SHARED_LIBS) + MESSAGE( + "-- Disabling tests. The flags BUILD_TESTING and BUILD_SHARED_LIBS" + " are incompatible with MSVC." + ) + # Retain the help string associated with the BUILD_TESTING option + # and turn testing off. + GET_PROPERTY(HELP_STRING CACHE BUILD_TESTING PROPERTY HELPSTRING) + SET(BUILD_TESTING OFF CACHE BOOL "${HELP_STRING}" FORCE) + ENDIF (BUILD_TESTING AND BUILD_SHARED_LIBS) ENDIF (MSVC) # Prior to October 2013, Ceres used some non-CMake standardised variables to @@ -474,6 +485,7 @@ IF (BUILD_SHARED_LIBS) MESSAGE("-- Building Ceres as a shared library.") + ADD_DEFINITIONS(-DCERES_BUILDING_SHARED_LIBRARY) ELSE (BUILD_SHARED_LIBS) MESSAGE("-- Building Ceres as a static library.") ENDIF (BUILD_SHARED_LIBS)
diff --git a/docs/source/building.rst b/docs/source/building.rst index 700f41a..14ff68e 100644 --- a/docs/source/building.rst +++ b/docs/source/building.rst
@@ -310,7 +310,9 @@ #. The default build is Debug; consider switching it to release mode. #. Currently ``system_test`` is not working properly. -#. Building Ceres as a DLL is not supported; patches welcome. +#. If you build Ceres as a DLL with Visual Studio (BUILD_SHARED_LIBS), + you have to compile your own code with the flag + CERES_USING_SHARED_LIBRARY. #. CMake puts the resulting test binaries in ``ceres-bin/examples/Debug`` by default. #. The solvers supported on Windows are ``DENSE_QR``, ``DENSE_SCHUR``,
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 60e464d..eda929b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt
@@ -28,6 +28,10 @@ # # Author: keir@google.com (Keir Mierle) +IF (BUILD_SHARED_LIBS) + ADD_DEFINITIONS(-DCERES_USING_SHARED_LIBRARY) +ENDIF() + ADD_EXECUTABLE(helloworld helloworld.cc) TARGET_LINK_LIBRARIES(helloworld ceres)
diff --git a/include/ceres/c_api.h b/include/ceres/c_api.h index add68de..632542e 100644 --- a/include/ceres/c_api.h +++ b/include/ceres/c_api.h
@@ -38,12 +38,14 @@ #ifndef CERES_PUBLIC_C_API_H_ #define CERES_PUBLIC_C_API_H_ +#include "ceres/internal/port.h" + #ifdef __cplusplus extern "C" { #endif /* Init the Ceres private data. Must be called before anything else. */ -void ceres_init(); +CERES_EXPORT void ceres_init(); /* Equivalent to CostFunction::Evaluate() in the C++ API. * @@ -88,23 +90,23 @@ * * See loss_function.h for the details of each loss function. */ -void* ceres_create_huber_loss_function_data(double a); -void* ceres_create_softl1_loss_function_data(double a); -void* ceres_create_cauchy_loss_function_data(double a); -void* ceres_create_arctan_loss_function_data(double a); -void* ceres_create_tolerant_loss_function_data(double a, double b); +CERES_EXPORT void* ceres_create_huber_loss_function_data(double a); +CERES_EXPORT void* ceres_create_softl1_loss_function_data(double a); +CERES_EXPORT void* ceres_create_cauchy_loss_function_data(double a); +CERES_EXPORT void* ceres_create_arctan_loss_function_data(double a); +CERES_EXPORT void* ceres_create_tolerant_loss_function_data(double a, double b); /* Free the given stock loss function data. */ -void ceres_free_stock_loss_function_data(void* loss_function_data); +CERES_EXPORT void ceres_free_stock_loss_function_data(void* loss_function_data); /* This is an implementation of ceres_loss_function_t contained within Ceres * itself, intended as a way to access the various stock Ceres loss functions * from the C API. This should be passed to ceres_add_residual() below, in * combination with a user_data pointer generated by * ceres_create_stock_loss_function() above. */ -void ceres_stock_loss_function(void* user_data, - double squared_norm, - double out[3]); +CERES_EXPORT void ceres_stock_loss_function(void* user_data, + double squared_norm, + double out[3]); /* Equivalent to Problem from the C++ API. */ struct ceres_problem_s; @@ -115,11 +117,11 @@ /* Create and destroy a problem */ /* TODO(keir): Add options for the problem. */ -ceres_problem_t* ceres_create_problem(); -void ceres_free_problem(ceres_problem_t* problem); +CERES_EXPORT ceres_problem_t* ceres_create_problem(); +CERES_EXPORT void ceres_free_problem(ceres_problem_t* problem); /* Add a residual block. */ -ceres_residual_block_id_t* ceres_problem_add_residual_block( +CERES_EXPORT ceres_residual_block_id_t* ceres_problem_add_residual_block( ceres_problem_t* problem, ceres_cost_function_t cost_function, void* cost_function_data, @@ -130,7 +132,7 @@ int* parameter_block_sizes, double** parameters); -void ceres_solve(ceres_problem_t* problem); +CERES_EXPORT void ceres_solve(ceres_problem_t* problem); /* TODO(keir): Figure out a way to pass a config in. */
diff --git a/include/ceres/conditioned_cost_function.h b/include/ceres/conditioned_cost_function.h index 498d36e..2a12ba6 100644 --- a/include/ceres/conditioned_cost_function.h +++ b/include/ceres/conditioned_cost_function.h
@@ -70,7 +70,7 @@ // ccf_residual[i] = f_i(my_cost_function_residual[i]) // // and the Jacobian will be affected appropriately. -class ConditionedCostFunction : public CostFunction { +class CERES_EXPORT ConditionedCostFunction : public CostFunction { public: // Builds a cost function based on a wrapped cost function, and a // per-residual conditioner. Takes ownership of all of the wrapped cost
diff --git a/include/ceres/cost_function.h b/include/ceres/cost_function.h index 722ac77..fee3e73 100644 --- a/include/ceres/cost_function.h +++ b/include/ceres/cost_function.h
@@ -60,7 +60,7 @@ // code inheriting from this class is expected to set these two members with the // corresponding accessors. This information will be verified by the Problem // when added with AddResidualBlock(). -class CostFunction { +class CERES_EXPORT CostFunction { public: CostFunction() : num_residuals_(0) {}
diff --git a/include/ceres/covariance.h b/include/ceres/covariance.h index 83126b5..b6e9a6a 100644 --- a/include/ceres/covariance.h +++ b/include/ceres/covariance.h
@@ -196,9 +196,9 @@ // covariance.GetCovarianceBlock(y, y, covariance_yy) // covariance.GetCovarianceBlock(x, y, covariance_xy) // -class Covariance { +class CERES_EXPORT Covariance { public: - struct Options { + struct CERES_EXPORT Options { Options() #ifndef CERES_NO_SUITESPARSE : algorithm_type(SPARSE_QR),
diff --git a/include/ceres/crs_matrix.h b/include/ceres/crs_matrix.h index 8c470cd..687c958 100644 --- a/include/ceres/crs_matrix.h +++ b/include/ceres/crs_matrix.h
@@ -38,7 +38,7 @@ // A compressed row sparse matrix used primarily for communicating the // Jacobian matrix to the user. -struct CRSMatrix { +struct CERES_EXPORT CRSMatrix { CRSMatrix() : num_rows(0), num_cols(0) {} int num_rows;
diff --git a/include/ceres/internal/port.h b/include/ceres/internal/port.h index e359d65..7bcb1a7 100644 --- a/include/ceres/internal/port.h +++ b/include/ceres/internal/port.h
@@ -31,6 +31,9 @@ #ifndef CERES_PUBLIC_INTERNAL_PORT_H_ #define CERES_PUBLIC_INTERNAL_PORT_H_ +// This file needs to compile as c code. +#ifdef __cplusplus + #include <string> #if defined(CERES_TR1_MEMORY_HEADER) @@ -59,4 +62,16 @@ } // namespace ceres +#endif // __cplusplus + +// A macro to signal wich functions and classes are exported when +// bulding a DLL with MSC. +#if defined(_MSC_VER) && defined(CERES_USING_SHARED_LIBRARY) +# define CERES_EXPORT __declspec(dllimport) +#elif defined(_MSC_VER) && defined(CERES_BUILDING_SHARED_LIBRARY) +# define CERES_EXPORT __declspec(dllexport) +#else +# define CERES_EXPORT +#endif + #endif // CERES_PUBLIC_INTERNAL_PORT_H_
diff --git a/include/ceres/iteration_callback.h b/include/ceres/iteration_callback.h index 5689256..5eca392 100644 --- a/include/ceres/iteration_callback.h +++ b/include/ceres/iteration_callback.h
@@ -41,7 +41,7 @@ // This struct describes the state of the optimizer after each // iteration of the minimization. -struct IterationSummary { +struct CERES_EXPORT IterationSummary { IterationSummary() : iteration(0), step_is_valid(false), @@ -211,7 +211,7 @@ // const bool log_to_stdout_; // }; // -class IterationCallback { +class CERES_EXPORT IterationCallback { public: virtual ~IterationCallback() {} virtual CallbackReturnType operator()(const IterationSummary& summary) = 0;
diff --git a/include/ceres/local_parameterization.h b/include/ceres/local_parameterization.h index c0f7dc7..3ecd959 100644 --- a/include/ceres/local_parameterization.h +++ b/include/ceres/local_parameterization.h
@@ -107,7 +107,7 @@ // // The class LocalParameterization defines the function Plus and its // Jacobian which is needed to compute the Jacobian of f w.r.t delta. -class LocalParameterization { +class CERES_EXPORT LocalParameterization { public: virtual ~LocalParameterization() {} @@ -133,7 +133,7 @@ // Some basic parameterizations // Identity Parameterization: Plus(x, delta) = x + delta -class IdentityParameterization : public LocalParameterization { +class CERES_EXPORT IdentityParameterization : public LocalParameterization { public: explicit IdentityParameterization(int size); virtual ~IdentityParameterization() {} @@ -150,7 +150,7 @@ }; // Hold a subset of the parameters inside a parameter block constant. -class SubsetParameterization : public LocalParameterization { +class CERES_EXPORT SubsetParameterization : public LocalParameterization { public: explicit SubsetParameterization(int size, const vector<int>& constant_parameters); @@ -172,7 +172,7 @@ // with * being the quaternion multiplication operator. Here we assume // that the first element of the quaternion vector is the real (cos // theta) part. -class QuaternionParameterization : public LocalParameterization { +class CERES_EXPORT QuaternionParameterization : public LocalParameterization { public: virtual ~QuaternionParameterization() {} virtual bool Plus(const double* x,
diff --git a/include/ceres/loss_function.h b/include/ceres/loss_function.h index b99c184..5b6bf68 100644 --- a/include/ceres/loss_function.h +++ b/include/ceres/loss_function.h
@@ -82,7 +82,7 @@ namespace ceres { -class LossFunction { +class CERES_EXPORT LossFunction { public: virtual ~LossFunction() {} @@ -128,7 +128,7 @@ // It is not normally necessary to use this, as passing NULL for the // loss function when building the problem accomplishes the same // thing. -class TrivialLoss : public LossFunction { +class CERES_EXPORT TrivialLoss : public LossFunction { public: virtual void Evaluate(double, double*) const; }; @@ -171,7 +171,7 @@ // // The scaling parameter 'a' corresponds to 'delta' on this page: // http://en.wikipedia.org/wiki/Huber_Loss_Function -class HuberLoss : public LossFunction { +class CERES_EXPORT HuberLoss : public LossFunction { public: explicit HuberLoss(double a) : a_(a), b_(a * a) { } virtual void Evaluate(double, double*) const; @@ -187,7 +187,7 @@ // rho(s) = 2 (sqrt(1 + s) - 1). // // At s = 0: rho = [0, 1, -1/2]. -class SoftLOneLoss : public LossFunction { +class CERES_EXPORT SoftLOneLoss : public LossFunction { public: explicit SoftLOneLoss(double a) : b_(a * a), c_(1 / b_) { } virtual void Evaluate(double, double*) const; @@ -204,7 +204,7 @@ // rho(s) = log(1 + s). // // At s = 0: rho = [0, 1, -1]. -class CauchyLoss : public LossFunction { +class CERES_EXPORT CauchyLoss : public LossFunction { public: explicit CauchyLoss(double a) : b_(a * a), c_(1 / b_) { } virtual void Evaluate(double, double*) const; @@ -225,7 +225,7 @@ // rho(s) = a atan(s / a). // // At s = 0: rho = [0, 1, 0]. -class ArctanLoss : public LossFunction { +class CERES_EXPORT ArctanLoss : public LossFunction { public: explicit ArctanLoss(double a) : a_(a), b_(1 / (a * a)) { } virtual void Evaluate(double, double*) const; @@ -264,7 +264,7 @@ // concentrated in the range a - b to a + b. // // At s = 0: rho = [0, ~0, ~0]. -class TolerantLoss : public LossFunction { +class CERES_EXPORT TolerantLoss : public LossFunction { public: explicit TolerantLoss(double a, double b); virtual void Evaluate(double, double*) const; @@ -305,7 +305,7 @@ // function, rho = NULL is a valid input and will result in the input // being scaled by a. This provides a simple way of implementing a // scaled ResidualBlock. -class ScaledLoss : public LossFunction { +class CERES_EXPORT ScaledLoss : public LossFunction { public: // Constructs a ScaledLoss wrapping another loss function. Takes // ownership of the wrapped loss function or not depending on the @@ -362,7 +362,7 @@ // // Solve(options, &problem, &summary) // -class LossFunctionWrapper : public LossFunction { +class CERES_EXPORT LossFunctionWrapper : public LossFunction { public: LossFunctionWrapper(LossFunction* rho, Ownership ownership) : rho_(rho), ownership_(ownership) {
diff --git a/include/ceres/normal_prior.h b/include/ceres/normal_prior.h index 480a074..530e652 100644 --- a/include/ceres/normal_prior.h +++ b/include/ceres/normal_prior.h
@@ -56,7 +56,7 @@ // which would be the case if the covariance matrix S is rank // deficient. -class NormalPrior: public CostFunction { +class CERES_EXPORT NormalPrior: public CostFunction { public: // Check that the number of rows in the vector b are the same as the // number of columns in the matrix A, crash otherwise.
diff --git a/include/ceres/problem.h b/include/ceres/problem.h index b8759eb..5881677 100644 --- a/include/ceres/problem.h +++ b/include/ceres/problem.h
@@ -117,9 +117,9 @@ // problem.AddResidualBlock(new MyBinaryCostFunction(...), x2, x3); // // Please see cost_function.h for details of the CostFunction object. -class Problem { +class CERES_EXPORT Problem { public: - struct Options { + struct CERES_EXPORT Options { Options() : cost_function_ownership(TAKE_OWNERSHIP), loss_function_ownership(TAKE_OWNERSHIP),
diff --git a/include/ceres/solver.h b/include/ceres/solver.h index 3d63951..4fb6e4d 100644 --- a/include/ceres/solver.h +++ b/include/ceres/solver.h
@@ -46,7 +46,7 @@ class Problem; // Interface for non-linear least squares solvers. -class Solver { +class CERES_EXPORT Solver { public: virtual ~Solver(); @@ -55,7 +55,7 @@ // problems; however, better performance is often obtainable with tweaking. // // The constants are defined inside types.h - struct Options { + struct CERES_EXPORT Options { // Default constructor that sets up a generic sparse problem. Options() { minimizer_type = TRUST_REGION; @@ -713,7 +713,7 @@ string solver_log; }; - struct Summary { + struct CERES_EXPORT Summary { Summary(); // A brief one line description of the state of the solver after @@ -951,7 +951,7 @@ }; // Helper function which avoids going through the interface. -void Solve(const Solver::Options& options, +CERES_EXPORT void Solve(const Solver::Options& options, Problem* problem, Solver::Summary* summary);
diff --git a/include/ceres/types.h b/include/ceres/types.h index e3dac3c..47bdb4c 100644 --- a/include/ceres/types.h +++ b/include/ceres/types.h
@@ -402,69 +402,69 @@ SPARSE_QR }; -const char* LinearSolverTypeToString(LinearSolverType type); -bool StringToLinearSolverType(string value, LinearSolverType* type); +CERES_EXPORT const char* LinearSolverTypeToString(LinearSolverType type); +CERES_EXPORT bool StringToLinearSolverType(string value, LinearSolverType* type); -const char* PreconditionerTypeToString(PreconditionerType type); -bool StringToPreconditionerType(string value, PreconditionerType* type); +CERES_EXPORT const char* PreconditionerTypeToString(PreconditionerType type); +CERES_EXPORT bool StringToPreconditionerType(string value, PreconditionerType* type); -const char* VisibilityClusteringTypeToString(VisibilityClusteringType type); -bool StringToVisibilityClusteringType(string value, +CERES_EXPORT const char* VisibilityClusteringTypeToString(VisibilityClusteringType type); +CERES_EXPORT bool StringToVisibilityClusteringType(string value, VisibilityClusteringType* type); -const char* SparseLinearAlgebraLibraryTypeToString( +CERES_EXPORT const char* SparseLinearAlgebraLibraryTypeToString( SparseLinearAlgebraLibraryType type); -bool StringToSparseLinearAlgebraLibraryType( +CERES_EXPORT bool StringToSparseLinearAlgebraLibraryType( string value, SparseLinearAlgebraLibraryType* type); -const char* DenseLinearAlgebraLibraryTypeToString( +CERES_EXPORT const char* DenseLinearAlgebraLibraryTypeToString( DenseLinearAlgebraLibraryType type); -bool StringToDenseLinearAlgebraLibraryType( +CERES_EXPORT bool StringToDenseLinearAlgebraLibraryType( string value, DenseLinearAlgebraLibraryType* type); -const char* TrustRegionStrategyTypeToString(TrustRegionStrategyType type); -bool StringToTrustRegionStrategyType(string value, +CERES_EXPORT const char* TrustRegionStrategyTypeToString(TrustRegionStrategyType type); +CERES_EXPORT bool StringToTrustRegionStrategyType(string value, TrustRegionStrategyType* type); -const char* DoglegTypeToString(DoglegType type); -bool StringToDoglegType(string value, DoglegType* type); +CERES_EXPORT const char* DoglegTypeToString(DoglegType type); +CERES_EXPORT bool StringToDoglegType(string value, DoglegType* type); -const char* MinimizerTypeToString(MinimizerType type); -bool StringToMinimizerType(string value, MinimizerType* type); +CERES_EXPORT const char* MinimizerTypeToString(MinimizerType type); +CERES_EXPORT bool StringToMinimizerType(string value, MinimizerType* type); -const char* LineSearchDirectionTypeToString(LineSearchDirectionType type); -bool StringToLineSearchDirectionType(string value, +CERES_EXPORT const char* LineSearchDirectionTypeToString(LineSearchDirectionType type); +CERES_EXPORT bool StringToLineSearchDirectionType(string value, LineSearchDirectionType* type); -const char* LineSearchTypeToString(LineSearchType type); -bool StringToLineSearchType(string value, LineSearchType* type); +CERES_EXPORT const char* LineSearchTypeToString(LineSearchType type); +CERES_EXPORT bool StringToLineSearchType(string value, LineSearchType* type); -const char* NonlinearConjugateGradientTypeToString( +CERES_EXPORT const char* NonlinearConjugateGradientTypeToString( NonlinearConjugateGradientType type); -bool StringToNonlinearConjugateGradientType( +CERES_EXPORT bool StringToNonlinearConjugateGradientType( string value, NonlinearConjugateGradientType* type); -const char* LineSearchInterpolationTypeToString( +CERES_EXPORT const char* LineSearchInterpolationTypeToString( LineSearchInterpolationType type); -bool StringToLineSearchInterpolationType( +CERES_EXPORT bool StringToLineSearchInterpolationType( string value, LineSearchInterpolationType* type); -const char* CovarianceAlgorithmTypeToString( +CERES_EXPORT const char* CovarianceAlgorithmTypeToString( CovarianceAlgorithmType type); -bool StringToCovarianceAlgorithmType( +CERES_EXPORT bool StringToCovarianceAlgorithmType( string value, CovarianceAlgorithmType* type); -const char* TerminationTypeToString(TerminationType type); +CERES_EXPORT const char* TerminationTypeToString(TerminationType type); -bool IsSchurType(LinearSolverType type); -bool IsSparseLinearAlgebraLibraryTypeAvailable( +CERES_EXPORT bool IsSchurType(LinearSolverType type); +CERES_EXPORT bool IsSparseLinearAlgebraLibraryTypeAvailable( SparseLinearAlgebraLibraryType type); -bool IsDenseLinearAlgebraLibraryTypeAvailable( +CERES_EXPORT bool IsDenseLinearAlgebraLibraryTypeAvailable( DenseLinearAlgebraLibraryType type); } // namespace ceres
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index a9ec1c2..b959768 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -137,7 +137,7 @@ # Primarily for Android, but optionally for others, use the minimal internal # Glog implementation. IF (MINIGLOG) - ADD_LIBRARY(miniglog miniglog/glog/logging.cc) + ADD_LIBRARY(miniglog STATIC miniglog/glog/logging.cc) INSTALL(TARGETS miniglog EXPORT CeresExport RUNTIME DESTINATION bin