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