Unify symbol visibility configuration for all compilers

This makes it possible to build unit tests with shared libraries on MSVC.

Change-Id: I1db66a80b2c78c4f3d354e35235244d17bac9809
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c707d35..ea7e9b8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -182,14 +182,8 @@
 if (MSVC)
   option(MSVC_USE_STATIC_CRT
     "MS Visual Studio: Use static C-Run Time Library in place of shared." OFF)
+endif()
 
-  if (BUILD_TESTING AND BUILD_SHARED_LIBS)
-    message(
-      "-- Disabling tests. The flags BUILD_TESTING and BUILD_SHARED_LIBS"
-      " are incompatible with MSVC.")
-    update_cache_variable(BUILD_TESTING OFF)
-  endif (BUILD_TESTING AND BUILD_SHARED_LIBS)
-endif (MSVC)
 # Allow user to specify a suffix for the library install directory, the only
 # really sensible option (other than "") being "64", such that:
 # ${CMAKE_INSTALL_PREFIX}/lib -> ${CMAKE_INSTALL_PREFIX}/lib64.
@@ -482,7 +476,7 @@
   # The CERES_BUILDING_SHARED_LIBRARY compile definition is NOT stored in
   # CERES_COMPILE_OPTIONS as it must only be defined when Ceres is compiled
   # not when it is used as it controls the CERES_EXPORT macro which provides
-  # dllimport/export support in MSVC.
+  # symbol import/export support.
   add_definitions(-DCERES_BUILDING_SHARED_LIBRARY)
   list(APPEND CERES_COMPILE_OPTIONS CERES_USING_SHARED_LIBRARY)
 else (BUILD_SHARED_LIBS)
diff --git a/include/ceres/internal/port.h b/include/ceres/internal/port.h
index 080121e..040a1ef 100644
--- a/include/ceres/internal/port.h
+++ b/include/ceres/internal/port.h
@@ -69,22 +69,42 @@
 #endif
 
 // A macro to signal which functions and classes are exported when
-// building a DLL with MSVC.
-//
-// Note that the ordering here is important, CERES_BUILDING_SHARED_LIBRARY
-// is only defined locally when Ceres is compiled, it is never exported to
-// users.  However, in order that we do not have to configure config.h
-// separately for building vs installing, if we are using MSVC and building
-// a shared library, then both CERES_BUILDING_SHARED_LIBRARY and
-// CERES_USING_SHARED_LIBRARY will be defined when Ceres is compiled.
-// Hence it is important that the check for CERES_BUILDING_SHARED_LIBRARY
-// happens first.
-#if defined(_MSC_VER) && defined(CERES_BUILDING_SHARED_LIBRARY)
-#define CERES_EXPORT __declspec(dllexport)
-#elif defined(_MSC_VER) && defined(CERES_USING_SHARED_LIBRARY)
-#define CERES_EXPORT __declspec(dllimport)
+// building a shared library.
+#if defined(_MSC_VER)
+#define CERES_API_SHARED_IMPORT __declspec(dllimport)
+#define CERES_API_SHARED_EXPORT __declspec(dllexport)
+#elif defined(__GNUC__)
+#define CERES_API_SHARED_IMPORT __attribute__((visibility("default")))
+#define CERES_API_SHARED_EXPORT __attribute__((visibility("default")))
 #else
+#define CERES_API_SHARED_IMPORT
+#define CERES_API_SHARED_EXPORT
+#endif
+
+// CERES_BUILDING_SHARED_LIBRARY is only defined locally when Ceres itself is
+// compiled as a shared library, it is never exported to users.  In order that
+// we do not have to configure config.h separately when building Ceres as either
+// a static or dynamic library, we define both CERES_USING_SHARED_LIBRARY and
+// CERES_BUILDING_SHARED_LIBRARY when building as a shared library.
+#if defined(CERES_USING_SHARED_LIBRARY)
+#if defined(CERES_BUILDING_SHARED_LIBRARY)
+// Compiling Ceres itself as a shared library.
+#define CERES_EXPORT CERES_API_SHARED_EXPORT
+#else
+// Using Ceres as a shared library.
+#define CERES_EXPORT CERES_API_SHARED_IMPORT
+#endif
+#else
+// Ceres was compiled as a static library, export everything.
 #define CERES_EXPORT
 #endif
 
+// Unit tests reach in and test internal functionality so we need a way to make
+// those symbols visible
+#ifdef CERES_EXPORT_INTERNAL_SYMBOLS
+#define CERES_EXPORT_INTERNAL CERES_EXPORT
+#else
+#define CERES_EXPORT_INTERNAL
+#endif
+
 #endif  // CERES_PUBLIC_INTERNAL_PORT_H_
diff --git a/include/ceres/local_parameterization.h b/include/ceres/local_parameterization.h
index be4fb46..1931a89 100644
--- a/include/ceres/local_parameterization.h
+++ b/include/ceres/local_parameterization.h
@@ -306,6 +306,7 @@
  public:
   ProductParameterization(const ProductParameterization&) = delete;
   ProductParameterization& operator=(const ProductParameterization&) = delete;
+  virtual ~ProductParameterization() {}
   //
   // NOTE: The constructor takes ownership of the input local
   // parameterizations.
@@ -341,7 +342,8 @@
   bool Plus(const double* x,
             const double* delta,
             double* x_plus_delta) const override;
-  bool ComputeJacobian(const double* x, double* jacobian) const override;
+  bool ComputeJacobian(const double* x,
+                       double* jacobian) const override;
   int GlobalSize() const override { return global_size_; }
   int LocalSize() const override { return local_size_; }
 
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt
index 1ff9217..6dc7262 100644
--- a/internal/ceres/CMakeLists.txt
+++ b/internal/ceres/CMakeLists.txt
@@ -233,6 +233,23 @@
 set_target_properties(ceres PROPERTIES
   VERSION ${CERES_VERSION}
   SOVERSION ${CERES_VERSION_MAJOR})
+if (BUILD_SHARED_LIBS)
+  set_target_properties(ceres PROPERTIES
+    # Set the default symbol visibility to hidden to unify the behavior among
+    # the various compilers and to get smaller binaries
+    C_VISIBILITY_PRESET hidden
+    CXX_VISIBILITY_PRESET hidden)
+endif()
+
+# When building as a shared libarary with testing enabled, we need to export
+# internal symbols needed by the unit tests
+if (BUILD_TESTING)
+  target_compile_definitions(ceres
+    PUBLIC
+      CERES_EXPORT_INTERNAL_SYMBOLS
+    )
+endif()
+
 
 # The ability to specify a minimum language version via cxx_std_[11,14,17]
 # requires CMake >= 3.8.  Prior to that we have to specify the compiler features
diff --git a/internal/ceres/array_utils.h b/internal/ceres/array_utils.h
index b068721..68feca5 100644
--- a/internal/ceres/array_utils.h
+++ b/internal/ceres/array_utils.h
@@ -52,20 +52,22 @@
 
 // Fill the array x with an impossible value that the user code is
 // never expected to compute.
-void InvalidateArray(int size, double* x);
+CERES_EXPORT_INTERNAL void InvalidateArray(int size, double* x);
 
 // Check if all the entries of the array x are valid, i.e. all the
 // values in the array should be finite and none of them should be
 // equal to the "impossible" value used by InvalidateArray.
-bool IsArrayValid(int size, const double* x);
+CERES_EXPORT_INTERNAL bool IsArrayValid(int size, const double* x);
 
 // If the array contains an invalid value, return the index for it,
 // otherwise return size.
-int FindInvalidValue(const int size, const double* x);
+CERES_EXPORT_INTERNAL int FindInvalidValue(const int size, const double* x);
 
 // Utility routine to print an array of doubles to a string. If the
 // array pointer is NULL, it is treated as an array of zeros.
-void AppendArrayToString(const int size, const double* x, std::string* result);
+CERES_EXPORT_INTERNAL void AppendArrayToString(const int size,
+                                               const double* x,
+                                               std::string* result);
 
 // This routine takes an array of integer values, sorts and uniques
 // them and then maps each value in the array to its position in the
@@ -80,7 +82,7 @@
 // gets mapped to
 //
 // [1 0 2 3 0 1 3]
-void MapValuesToContiguousRange(int size, int* array);
+CERES_EXPORT_INTERNAL void MapValuesToContiguousRange(int size, int* array);
 
 }  // namespace internal
 }  // namespace ceres
diff --git a/internal/ceres/block_jacobi_preconditioner.h b/internal/ceres/block_jacobi_preconditioner.h
index 4ede9b9..18f7495 100644
--- a/internal/ceres/block_jacobi_preconditioner.h
+++ b/internal/ceres/block_jacobi_preconditioner.h
@@ -34,6 +34,7 @@
 #include <memory>
 
 #include "ceres/block_random_access_diagonal_matrix.h"
+#include "ceres/internal/port.h"
 #include "ceres/preconditioner.h"
 
 namespace ceres {
@@ -52,7 +53,8 @@
 // update the matrix by running Update(A, D). The values of the matrix A are
 // inspected to construct the preconditioner. The vector D is applied as the
 // D^TD diagonal term.
-class BlockJacobiPreconditioner : public BlockSparseMatrixPreconditioner {
+class CERES_EXPORT_INTERNAL BlockJacobiPreconditioner
+    : public BlockSparseMatrixPreconditioner {
  public:
   // A must remain valid while the BlockJacobiPreconditioner is.
   explicit BlockJacobiPreconditioner(const BlockSparseMatrix& A);
diff --git a/internal/ceres/block_random_access_dense_matrix.h b/internal/ceres/block_random_access_dense_matrix.h
index be67f34..9e55524 100644
--- a/internal/ceres/block_random_access_dense_matrix.h
+++ b/internal/ceres/block_random_access_dense_matrix.h
@@ -50,7 +50,8 @@
 // pair.
 //
 // ReturnCell is a nop.
-class BlockRandomAccessDenseMatrix : public BlockRandomAccessMatrix {
+class CERES_EXPORT_INTERNAL BlockRandomAccessDenseMatrix
+    : public BlockRandomAccessMatrix {
  public:
   // blocks is a vector of block sizes. The resulting matrix has
   // blocks.size() * blocks.size() cells.
diff --git a/internal/ceres/block_random_access_diagonal_matrix.h b/internal/ceres/block_random_access_diagonal_matrix.h
index 4d3e1cc..3fe7c1e 100644
--- a/internal/ceres/block_random_access_diagonal_matrix.h
+++ b/internal/ceres/block_random_access_diagonal_matrix.h
@@ -46,7 +46,8 @@
 
 // A thread safe block diagonal matrix implementation of
 // BlockRandomAccessMatrix.
-class BlockRandomAccessDiagonalMatrix : public BlockRandomAccessMatrix {
+class CERES_EXPORT_INTERNAL BlockRandomAccessDiagonalMatrix
+    : public BlockRandomAccessMatrix {
  public:
   // blocks is an array of block sizes.
   explicit BlockRandomAccessDiagonalMatrix(const std::vector<int>& blocks);
diff --git a/internal/ceres/block_random_access_matrix.h b/internal/ceres/block_random_access_matrix.h
index 6fcf0dc..f190622 100644
--- a/internal/ceres/block_random_access_matrix.h
+++ b/internal/ceres/block_random_access_matrix.h
@@ -35,6 +35,8 @@
 
 #include <mutex>
 
+#include "ceres/internal/port.h"
+
 namespace ceres {
 namespace internal {
 
@@ -91,7 +93,7 @@
   std::mutex m;
 };
 
-class BlockRandomAccessMatrix {
+class CERES_EXPORT_INTERNAL BlockRandomAccessMatrix {
  public:
   virtual ~BlockRandomAccessMatrix();
 
diff --git a/internal/ceres/block_random_access_sparse_matrix.h b/internal/ceres/block_random_access_sparse_matrix.h
index ca04163..0e58bbb 100644
--- a/internal/ceres/block_random_access_sparse_matrix.h
+++ b/internal/ceres/block_random_access_sparse_matrix.h
@@ -51,7 +51,8 @@
 // BlockRandomAccessMatrix. Internally a TripletSparseMatrix is used
 // for doing the actual storage. This class augments this matrix with
 // an unordered_map that allows random read/write access.
-class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix {
+class CERES_EXPORT_INTERNAL BlockRandomAccessSparseMatrix
+    : public BlockRandomAccessMatrix {
  public:
   // blocks is an array of block sizes. block_pairs is a set of
   // <row_block_id, col_block_id> pairs to identify the non-zero cells
diff --git a/internal/ceres/block_sparse_matrix.h b/internal/ceres/block_sparse_matrix.h
index fa9e4ed..e5b3634 100644
--- a/internal/ceres/block_sparse_matrix.h
+++ b/internal/ceres/block_sparse_matrix.h
@@ -38,6 +38,7 @@
 
 #include "ceres/block_structure.h"
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/sparse_matrix.h"
 
 namespace ceres {
@@ -53,7 +54,7 @@
 //
 //   internal/ceres/block_structure.h
 //
-class BlockSparseMatrix : public SparseMatrix {
+class CERES_EXPORT_INTERNAL BlockSparseMatrix : public SparseMatrix {
  public:
   // Construct a block sparse matrix with a fully initialized
   // CompressedRowBlockStructure objected. The matrix takes over
diff --git a/internal/ceres/canonical_views_clustering.h b/internal/ceres/canonical_views_clustering.h
index 630adfe..465233d 100644
--- a/internal/ceres/canonical_views_clustering.h
+++ b/internal/ceres/canonical_views_clustering.h
@@ -45,6 +45,7 @@
 #include <vector>
 
 #include "ceres/graph.h"
+#include "ceres/internal/port.h"
 
 namespace ceres {
 namespace internal {
@@ -94,13 +95,13 @@
 // It is possible depending on the configuration of the clustering
 // algorithm that some of the vertices may not be assigned to any
 // cluster. In this case they are assigned to a cluster with id = -1;
-void ComputeCanonicalViewsClustering(
+CERES_EXPORT_INTERNAL void ComputeCanonicalViewsClustering(
     const CanonicalViewsClusteringOptions& options,
     const WeightedGraph<int>& graph,
     std::vector<int>* centers,
     std::unordered_map<int, int>* membership);
 
-struct CanonicalViewsClusteringOptions {
+struct CERES_EXPORT_INTERNAL CanonicalViewsClusteringOptions {
   // The minimum number of canonical views to compute.
   int min_views = 3;
 
diff --git a/internal/ceres/compressed_col_sparse_matrix_utils.h b/internal/ceres/compressed_col_sparse_matrix_utils.h
index 8e56519..d442e1a 100644
--- a/internal/ceres/compressed_col_sparse_matrix_utils.h
+++ b/internal/ceres/compressed_col_sparse_matrix_utils.h
@@ -48,7 +48,7 @@
 // and column block j, then it is expected that A contains at least
 // one non-zero entry corresponding to the top left entry of c_ij,
 // as that entry is used to detect the presence of a non-zero c_ij.
-void CompressedColumnScalarMatrixToBlockMatrix(
+CERES_EXPORT_INTERNAL void CompressedColumnScalarMatrixToBlockMatrix(
     const int* scalar_rows,
     const int* scalar_cols,
     const std::vector<int>& row_blocks,
@@ -59,9 +59,10 @@
 // Given a set of blocks and a permutation of these blocks, compute
 // the corresponding "scalar" ordering, where the scalar ordering of
 // size sum(blocks).
-void BlockOrderingToScalarOrdering(const std::vector<int>& blocks,
-                                   const std::vector<int>& block_ordering,
-                                   std::vector<int>* scalar_ordering);
+CERES_EXPORT_INTERNAL void BlockOrderingToScalarOrdering(
+    const std::vector<int>& blocks,
+    const std::vector<int>& block_ordering,
+    std::vector<int>* scalar_ordering);
 
 // Solve the linear system
 //
diff --git a/internal/ceres/compressed_row_sparse_matrix.h b/internal/ceres/compressed_row_sparse_matrix.h
index 203c7ea..0a1b945 100644
--- a/internal/ceres/compressed_row_sparse_matrix.h
+++ b/internal/ceres/compressed_row_sparse_matrix.h
@@ -46,7 +46,7 @@
 
 class TripletSparseMatrix;
 
-class CompressedRowSparseMatrix : public SparseMatrix {
+class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix {
  public:
   enum StorageType {
     UNSYMMETRIC,
diff --git a/internal/ceres/conjugate_gradients_solver.h b/internal/ceres/conjugate_gradients_solver.h
index d89383e..f79ca49 100644
--- a/internal/ceres/conjugate_gradients_solver.h
+++ b/internal/ceres/conjugate_gradients_solver.h
@@ -34,6 +34,7 @@
 #ifndef CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_
 #define CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_
 
+#include "ceres/internal/port.h"
 #include "ceres/linear_solver.h"
 
 namespace ceres {
@@ -54,7 +55,7 @@
 // For more details see the documentation for
 // LinearSolver::PerSolveOptions::r_tolerance and
 // LinearSolver::PerSolveOptions::q_tolerance in linear_solver.h.
-class ConjugateGradientsSolver : public LinearSolver {
+class CERES_EXPORT_INTERNAL ConjugateGradientsSolver : public LinearSolver {
  public:
   explicit ConjugateGradientsSolver(const LinearSolver::Options& options);
   Summary Solve(LinearOperator* A,
diff --git a/internal/ceres/context_impl.h b/internal/ceres/context_impl.h
index 90ba344..574d1ef 100644
--- a/internal/ceres/context_impl.h
+++ b/internal/ceres/context_impl.h
@@ -45,7 +45,7 @@
 namespace ceres {
 namespace internal {
 
-class ContextImpl : public Context {
+class CERES_EXPORT_INTERNAL ContextImpl : public Context {
  public:
   ContextImpl() {}
   ContextImpl(const ContextImpl&) = delete;
diff --git a/internal/ceres/corrector.h b/internal/ceres/corrector.h
index a5b03dd..3e11cdc 100644
--- a/internal/ceres/corrector.h
+++ b/internal/ceres/corrector.h
@@ -35,6 +35,8 @@
 #ifndef CERES_INTERNAL_CORRECTOR_H_
 #define CERES_INTERNAL_CORRECTOR_H_
 
+#include "ceres/internal/port.h"
+
 namespace ceres {
 namespace internal {
 
@@ -46,7 +48,7 @@
 // gauss newton approximation and then take its square root to get the
 // corresponding corrections to the residual and jacobian.  For the
 // full expressions see Eq. 10 and 11 in BANS by Triggs et al.
-class Corrector {
+class CERES_EXPORT_INTERNAL Corrector {
  public:
   // The constructor takes the squared norm, the value, the first and
   // second derivatives of the LossFunction. It precalculates some of
diff --git a/internal/ceres/covariance_impl.h b/internal/ceres/covariance_impl.h
index a26763a..394a04b 100644
--- a/internal/ceres/covariance_impl.h
+++ b/internal/ceres/covariance_impl.h
@@ -38,6 +38,7 @@
 #include <vector>
 
 #include "ceres/covariance.h"
+#include "ceres/internal/port.h"
 #include "ceres/problem_impl.h"
 #include "ceres/suitesparse.h"
 
@@ -46,7 +47,7 @@
 
 class CompressedRowSparseMatrix;
 
-class CovarianceImpl {
+class CERES_EXPORT_INTERNAL CovarianceImpl {
  public:
   explicit CovarianceImpl(const Covariance::Options& options);
   ~CovarianceImpl();
diff --git a/internal/ceres/dense_qr_solver.h b/internal/ceres/dense_qr_solver.h
index a30cd1c..980243b 100644
--- a/internal/ceres/dense_qr_solver.h
+++ b/internal/ceres/dense_qr_solver.h
@@ -33,6 +33,7 @@
 #define CERES_INTERNAL_DENSE_QR_SOLVER_H_
 
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/linear_solver.h"
 
 namespace ceres {
@@ -78,7 +79,7 @@
 // library. This solver always returns a solution, it is the user's
 // responsibility to judge if the solution is good enough for their
 // purposes.
-class DenseQRSolver : public DenseSparseMatrixSolver {
+class CERES_EXPORT_INTERNAL DenseQRSolver : public DenseSparseMatrixSolver {
  public:
   explicit DenseQRSolver(const LinearSolver::Options& options);
 
diff --git a/internal/ceres/dense_sparse_matrix.h b/internal/ceres/dense_sparse_matrix.h
index 34a3be2..94064b3 100644
--- a/internal/ceres/dense_sparse_matrix.h
+++ b/internal/ceres/dense_sparse_matrix.h
@@ -34,6 +34,7 @@
 #define CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_
 
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/sparse_matrix.h"
 #include "ceres/types.h"
 
@@ -42,7 +43,7 @@
 
 class TripletSparseMatrix;
 
-class DenseSparseMatrix : public SparseMatrix {
+class CERES_EXPORT_INTERNAL DenseSparseMatrix : public SparseMatrix {
  public:
   // Build a matrix with the same content as the TripletSparseMatrix
   // m. This assumes that m does not have any repeated entries.
diff --git a/internal/ceres/detect_structure.h b/internal/ceres/detect_structure.h
index 602581c..0624230 100644
--- a/internal/ceres/detect_structure.h
+++ b/internal/ceres/detect_structure.h
@@ -32,6 +32,7 @@
 #define CERES_INTERNAL_DETECT_STRUCTURE_H_
 
 #include "ceres/block_structure.h"
+#include "ceres/internal/port.h"
 
 namespace ceres {
 namespace internal {
@@ -55,11 +56,11 @@
 // Note: The structure of rows without any e-blocks has no effect on
 // the values returned by this function. It is entirely possible that
 // the f_block_size and row_blocks_size is not constant in such rows.
-void DetectStructure(const CompressedRowBlockStructure& bs,
-                     const int num_eliminate_blocks,
-                     int* row_block_size,
-                     int* e_block_size,
-                     int* f_block_size);
+void CERES_EXPORT DetectStructure(const CompressedRowBlockStructure& bs,
+                                  const int num_eliminate_blocks,
+                                  int* row_block_size,
+                                  int* e_block_size,
+                                  int* f_block_size);
 
 }  // namespace internal
 }  // namespace ceres
diff --git a/internal/ceres/dogleg_strategy.h b/internal/ceres/dogleg_strategy.h
index 9616ffe..cc3778e 100644
--- a/internal/ceres/dogleg_strategy.h
+++ b/internal/ceres/dogleg_strategy.h
@@ -31,6 +31,7 @@
 #ifndef CERES_INTERNAL_DOGLEG_STRATEGY_H_
 #define CERES_INTERNAL_DOGLEG_STRATEGY_H_
 
+#include "ceres/internal/port.h"
 #include "ceres/linear_solver.h"
 #include "ceres/trust_region_strategy.h"
 
@@ -52,7 +53,7 @@
 // DoglegStrategy follows the approach by Shultz, Schnabel, Byrd.
 // This finds the exact optimum over the two-dimensional subspace
 // spanned by the two Dogleg vectors.
-class DoglegStrategy : public TrustRegionStrategy {
+class CERES_EXPORT_INTERNAL DoglegStrategy : public TrustRegionStrategy {
  public:
   explicit DoglegStrategy(const TrustRegionStrategy::Options& options);
   virtual ~DoglegStrategy() {}
diff --git a/internal/ceres/dynamic_compressed_row_sparse_matrix.h b/internal/ceres/dynamic_compressed_row_sparse_matrix.h
index ad41da7..d06c36e 100644
--- a/internal/ceres/dynamic_compressed_row_sparse_matrix.h
+++ b/internal/ceres/dynamic_compressed_row_sparse_matrix.h
@@ -44,11 +44,13 @@
 #include <vector>
 
 #include "ceres/compressed_row_sparse_matrix.h"
+#include "ceres/internal/port.h"
 
 namespace ceres {
 namespace internal {
 
-class DynamicCompressedRowSparseMatrix : public CompressedRowSparseMatrix {
+class CERES_EXPORT_INTERNAL DynamicCompressedRowSparseMatrix
+    : public CompressedRowSparseMatrix {
  public:
   // Set the number of rows and columns for the underlyig
   // `CompressedRowSparseMatrix` and set the initial number of maximum non-zero
diff --git a/internal/ceres/evaluator.h b/internal/ceres/evaluator.h
index a668445..9cf4259 100644
--- a/internal/ceres/evaluator.h
+++ b/internal/ceres/evaluator.h
@@ -55,7 +55,7 @@
 // function that is useful for an optimizer that wants to minimize the least
 // squares objective. This insulates the optimizer from issues like Jacobian
 // storage, parameterization, etc.
-class Evaluator {
+class CERES_EXPORT_INTERNAL Evaluator {
  public:
   virtual ~Evaluator();
 
diff --git a/internal/ceres/evaluator_test_utils.h b/internal/ceres/evaluator_test_utils.h
index 7401f04..d47b6fa 100644
--- a/internal/ceres/evaluator_test_utils.h
+++ b/internal/ceres/evaluator_test_utils.h
@@ -31,6 +31,8 @@
 //
 // Test utils used for evaluation testing.
 
+#include "ceres/internal/port.h"
+
 namespace ceres {
 namespace internal {
 
@@ -45,16 +47,16 @@
 };
 
 // Compare two evaluations.
-void CompareEvaluations(int expected_num_rows,
-                        int expected_num_cols,
-                        double expected_cost,
-                        const double* expected_residuals,
-                        const double* expected_gradient,
-                        const double* expected_jacobian,
-                        const double actual_cost,
-                        const double* actual_residuals,
-                        const double* actual_gradient,
-                        const double* actual_jacobian);
+CERES_EXPORT_INTERNAL void CompareEvaluations(int expected_num_rows,
+                                              int expected_num_cols,
+                                              double expected_cost,
+                                              const double* expected_residuals,
+                                              const double* expected_gradient,
+                                              const double* expected_jacobian,
+                                              const double actual_cost,
+                                              const double* actual_residuals,
+                                              const double* actual_gradient,
+                                              const double* actual_jacobian);
 
 }  // namespace internal
 }  // namespace ceres
diff --git a/internal/ceres/file.h b/internal/ceres/file.h
index 30c0225..c0015df 100644
--- a/internal/ceres/file.h
+++ b/internal/ceres/file.h
@@ -46,7 +46,8 @@
 
 // Join two path components, adding a slash if necessary.  If basename is an
 // absolute path then JoinPath ignores dirname and simply returns basename.
-std::string JoinPath(const std::string& dirname, const std::string& basename);
+CERES_EXPORT_INTERNAL std::string JoinPath(const std::string& dirname,
+                                           const std::string& basename);
 
 }  // namespace internal
 }  // namespace ceres
diff --git a/internal/ceres/function_sample.h b/internal/ceres/function_sample.h
index 8889f76..3bcea1b 100644
--- a/internal/ceres/function_sample.h
+++ b/internal/ceres/function_sample.h
@@ -34,6 +34,7 @@
 #include <string>
 
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 
 namespace ceres {
 namespace internal {
@@ -46,7 +47,7 @@
 // line/direction. FunctionSample contains the information in two
 // ways. Information in the ambient space and information along the
 // direction of search.
-struct FunctionSample {
+struct CERES_EXPORT_INTERNAL FunctionSample {
   FunctionSample();
   FunctionSample(double x, double value);
   FunctionSample(double x, double value, double gradient);
diff --git a/internal/ceres/gradient_checking_cost_function.h b/internal/ceres/gradient_checking_cost_function.h
index ab6e9f8..ea6e9b3 100644
--- a/internal/ceres/gradient_checking_cost_function.h
+++ b/internal/ceres/gradient_checking_cost_function.h
@@ -36,6 +36,7 @@
 #include <string>
 
 #include "ceres/cost_function.h"
+#include "ceres/internal/port.h"
 #include "ceres/iteration_callback.h"
 #include "ceres/local_parameterization.h"
 
@@ -46,7 +47,8 @@
 
 // Callback that collects information about gradient checking errors, and
 // will abort the solve as soon as an error occurs.
-class GradientCheckingIterationCallback : public IterationCallback {
+class CERES_EXPORT_INTERNAL GradientCheckingIterationCallback
+    : public IterationCallback {
  public:
   GradientCheckingIterationCallback();
 
@@ -71,7 +73,7 @@
 // with finite differences. This API is only intended for unit tests that intend
 // to  check the functionality of the GradientCheckingCostFunction
 // implementation directly.
-CostFunction* CreateGradientCheckingCostFunction(
+CERES_EXPORT_INTERNAL CostFunction* CreateGradientCheckingCostFunction(
     const CostFunction* cost_function,
     const std::vector<const LocalParameterization*>* local_parameterizations,
     double relative_step_size,
@@ -100,7 +102,7 @@
 // jacobians obtained by numerically differentiating them. See the
 // documentation of 'numeric_derivative_relative_step_size' in solver.h for a
 // better explanation.
-ProblemImpl* CreateGradientCheckingProblemImpl(
+CERES_EXPORT_INTERNAL ProblemImpl* CreateGradientCheckingProblemImpl(
     ProblemImpl* problem_impl,
     double relative_step_size,
     double relative_precision,
diff --git a/internal/ceres/implicit_schur_complement.h b/internal/ceres/implicit_schur_complement.h
index cc22f24..e83892a 100644
--- a/internal/ceres/implicit_schur_complement.h
+++ b/internal/ceres/implicit_schur_complement.h
@@ -37,6 +37,7 @@
 #include <memory>
 
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/linear_operator.h"
 #include "ceres/linear_solver.h"
 #include "ceres/partitioned_matrix_view.h"
@@ -87,7 +88,7 @@
 // RightMultiply (and the LeftMultiply) methods are not thread safe as
 // they depend on mutable arrays used for the temporaries needed to
 // compute the product y += Sx;
-class ImplicitSchurComplement : public LinearOperator {
+class CERES_EXPORT_INTERNAL ImplicitSchurComplement : public LinearOperator {
  public:
   // num_eliminate_blocks is the number of E blocks in the matrix
   // A.
diff --git a/internal/ceres/inner_product_computer.h b/internal/ceres/inner_product_computer.h
index 73073f8..04ec1d1 100644
--- a/internal/ceres/inner_product_computer.h
+++ b/internal/ceres/inner_product_computer.h
@@ -36,6 +36,7 @@
 
 #include "ceres/block_sparse_matrix.h"
 #include "ceres/compressed_row_sparse_matrix.h"
+#include "ceres/internal/port.h"
 
 namespace ceres {
 namespace internal {
@@ -60,7 +61,7 @@
 // This is not a problem as sparse linear algebra libraries can ignore
 // these entries with ease and the space used is minimal/linear in the
 // size of the matrices.
-class InnerProductComputer {
+class CERES_EXPORT_INTERNAL InnerProductComputer {
  public:
   // Factory
   //
diff --git a/internal/ceres/is_close.h b/internal/ceres/is_close.h
index d0b5e6b..b781a44 100644
--- a/internal/ceres/is_close.h
+++ b/internal/ceres/is_close.h
@@ -33,6 +33,8 @@
 #ifndef CERES_INTERNAL_IS_CLOSE_H_
 #define CERES_INTERNAL_IS_CLOSE_H_
 
+#include "ceres/internal/port.h"
+
 namespace ceres {
 namespace internal {
 // Returns true if x and y have a relative (unsigned) difference less than
@@ -40,11 +42,11 @@
 // difference in relative/absolute_error if non-NULL. If one of the two values
 // is exactly zero, the absolute difference will be compared, and relative_error
 // will be set to the absolute difference.
-bool IsClose(double x,
-             double y,
-             double relative_precision,
-             double* relative_error,
-             double* absolute_error);
+CERES_EXPORT_INTERNAL bool IsClose(double x,
+                                   double y,
+                                   double relative_precision,
+                                   double* relative_error,
+                                   double* absolute_error);
 }  // namespace internal
 }  // namespace ceres
 
diff --git a/internal/ceres/iterative_refiner.h b/internal/ceres/iterative_refiner.h
index b2c39b5..08f8d67 100644
--- a/internal/ceres/iterative_refiner.h
+++ b/internal/ceres/iterative_refiner.h
@@ -57,7 +57,7 @@
 // Definite linear systems.
 //
 // The above iterative loop is run until max_num_iterations is reached.
-class IterativeRefiner {
+class CERES_EXPORT_INTERNAL IterativeRefiner {
  public:
   // max_num_iterations is the number of refinement iterations to
   // perform.
diff --git a/internal/ceres/iterative_schur_complement_solver.h b/internal/ceres/iterative_schur_complement_solver.h
index ca002d2..37606b3 100644
--- a/internal/ceres/iterative_schur_complement_solver.h
+++ b/internal/ceres/iterative_schur_complement_solver.h
@@ -34,6 +34,7 @@
 #include <memory>
 
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/linear_solver.h"
 #include "ceres/types.h"
 
@@ -68,7 +69,8 @@
 // a proof of this fact and others related to this solver please see
 // the section on Domain Decomposition Methods in Saad's book
 // "Iterative Methods for Sparse Linear Systems".
-class IterativeSchurComplementSolver : public BlockSparseMatrixSolver {
+class CERES_EXPORT_INTERNAL IterativeSchurComplementSolver
+    : public BlockSparseMatrixSolver {
  public:
   explicit IterativeSchurComplementSolver(const LinearSolver::Options& options);
   IterativeSchurComplementSolver(const IterativeSchurComplementSolver&) =
diff --git a/internal/ceres/levenberg_marquardt_strategy.h b/internal/ceres/levenberg_marquardt_strategy.h
index 43b0bfd..12cd463 100644
--- a/internal/ceres/levenberg_marquardt_strategy.h
+++ b/internal/ceres/levenberg_marquardt_strategy.h
@@ -32,6 +32,7 @@
 #define CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_
 
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/trust_region_strategy.h"
 
 namespace ceres {
@@ -42,7 +43,8 @@
 // K. Madsen, H.B. Nielsen and O. Tingleff. Available to download from
 //
 // http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
-class LevenbergMarquardtStrategy : public TrustRegionStrategy {
+class CERES_EXPORT_INTERNAL LevenbergMarquardtStrategy
+    : public TrustRegionStrategy {
  public:
   explicit LevenbergMarquardtStrategy(
       const TrustRegionStrategy::Options& options);
diff --git a/internal/ceres/line_search_preprocessor.h b/internal/ceres/line_search_preprocessor.h
index 12ccb53..bd426c7 100644
--- a/internal/ceres/line_search_preprocessor.h
+++ b/internal/ceres/line_search_preprocessor.h
@@ -31,12 +31,13 @@
 #ifndef CERES_INTERNAL_LINE_SEARCH_PREPROCESSOR_H_
 #define CERES_INTERNAL_LINE_SEARCH_PREPROCESSOR_H_
 
+#include "ceres/internal/port.h"
 #include "ceres/preprocessor.h"
 
 namespace ceres {
 namespace internal {
 
-class LineSearchPreprocessor : public Preprocessor {
+class CERES_EXPORT_INTERNAL LineSearchPreprocessor : public Preprocessor {
  public:
   virtual ~LineSearchPreprocessor();
   bool Preprocess(const Solver::Options& options,
diff --git a/internal/ceres/linear_least_squares_problems.h b/internal/ceres/linear_least_squares_problems.h
index 939c2b4..cddaa9f 100644
--- a/internal/ceres/linear_least_squares_problems.h
+++ b/internal/ceres/linear_least_squares_problems.h
@@ -43,7 +43,7 @@
 
 // Structure defining a linear least squares problem and if possible
 // ground truth solutions. To be used by various LinearSolver tests.
-struct LinearLeastSquaresProblem {
+struct CERES_EXPORT_INTERNAL LinearLeastSquaresProblem {
   LinearLeastSquaresProblem() : num_eliminate_blocks(0) {}
 
   std::unique_ptr<SparseMatrix> A;
@@ -60,7 +60,8 @@
 };
 
 // Factories for linear least squares problem.
-LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id);
+CERES_EXPORT_INTERNAL LinearLeastSquaresProblem*
+CreateLinearLeastSquaresProblemFromId(int id);
 
 LinearLeastSquaresProblem* LinearLeastSquaresProblem0();
 LinearLeastSquaresProblem* LinearLeastSquaresProblem1();
diff --git a/internal/ceres/linear_operator.h b/internal/ceres/linear_operator.h
index 6463fb5..9c59fc3 100644
--- a/internal/ceres/linear_operator.h
+++ b/internal/ceres/linear_operator.h
@@ -33,6 +33,7 @@
 #ifndef CERES_INTERNAL_LINEAR_OPERATOR_H_
 #define CERES_INTERNAL_LINEAR_OPERATOR_H_
 
+#include "ceres/internal/port.h"
 #include "ceres/types.h"
 
 namespace ceres {
@@ -40,7 +41,7 @@
 
 // This is an abstract base class for linear operators. It supports
 // access to size information and left and right multiply operators.
-class LinearOperator {
+class CERES_EXPORT_INTERNAL LinearOperator {
  public:
   virtual ~LinearOperator();
 
diff --git a/internal/ceres/linear_solver.h b/internal/ceres/linear_solver.h
index 47684e7..49c6527 100644
--- a/internal/ceres/linear_solver.h
+++ b/internal/ceres/linear_solver.h
@@ -45,6 +45,7 @@
 #include "ceres/context_impl.h"
 #include "ceres/dense_sparse_matrix.h"
 #include "ceres/execution_summary.h"
+#include "ceres/internal/port.h"
 #include "ceres/triplet_sparse_matrix.h"
 #include "ceres/types.h"
 #include "glog/logging.h"
@@ -100,7 +101,7 @@
 // The Options struct configures the LinearSolver object for its
 // lifetime. The PerSolveOptions struct is used to specify options for
 // a particular Solve call.
-class LinearSolver {
+class CERES_EXPORT_INTERNAL LinearSolver {
  public:
   struct Options {
     LinearSolverType type = SPARSE_NORMAL_CHOLESKY;
diff --git a/internal/ceres/minimizer.h b/internal/ceres/minimizer.h
index 69416b3..246550d 100644
--- a/internal/ceres/minimizer.h
+++ b/internal/ceres/minimizer.h
@@ -49,7 +49,7 @@
 class LinearSolver;
 
 // Interface for non-linear least squares solvers.
-class Minimizer {
+class CERES_EXPORT_INTERNAL Minimizer {
  public:
   // Options struct to control the behaviour of the Minimizer. Please
   // see solver.h for detailed information about the meaning and
diff --git a/internal/ceres/numeric_diff_test_utils.h b/internal/ceres/numeric_diff_test_utils.h
index 462553c..392636e 100644
--- a/internal/ceres/numeric_diff_test_utils.h
+++ b/internal/ceres/numeric_diff_test_utils.h
@@ -32,6 +32,7 @@
 #define CERES_INTERNAL_NUMERIC_DIFF_TEST_UTILS_H_
 
 #include "ceres/cost_function.h"
+#include "ceres/internal/port.h"
 #include "ceres/sized_cost_function.h"
 #include "ceres/types.h"
 
@@ -47,7 +48,7 @@
 // y1 = x1'x2      -> dy1/dx1 = x2,               dy1/dx2 = x1
 // y2 = (x1'x2)^2  -> dy2/dx1 = 2 * x2 * (x1'x2), dy2/dx2 = 2 * x1 * (x1'x2)
 // y3 = x2'x2      -> dy3/dx1 = 0,                dy3/dx2 = 2 * x2
-class EasyFunctor {
+class CERES_EXPORT_INTERNAL EasyFunctor {
  public:
   bool operator()(const double* x1, const double* x2, double* residuals) const;
   void ExpectCostFunctionEvaluationIsNearlyCorrect(
@@ -71,14 +72,15 @@
 //
 // dy1/dx1 =  x2 * cos(x1'x2),            dy1/dx2 =  x1 * cos(x1'x2)
 // dy2/dx1 = -x2 * exp(-x1'x2 / 10) / 10, dy2/dx2 = -x2 * exp(-x1'x2 / 10) / 10
-class TranscendentalFunctor {
+class CERES_EXPORT TranscendentalFunctor {
  public:
   bool operator()(const double* x1, const double* x2, double* residuals) const;
   void ExpectCostFunctionEvaluationIsNearlyCorrect(
       const CostFunction& cost_function, NumericDiffMethodType method) const;
 };
 
-class TranscendentalCostFunction : public SizedCostFunction<2, 5, 5> {
+class CERES_EXPORT_INTERNAL TranscendentalCostFunction
+    : public SizedCostFunction<2, 5, 5> {
  public:
   bool Evaluate(double const* const* parameters,
                 double* residuals,
@@ -91,7 +93,7 @@
 };
 
 // y = exp(x), dy/dx = exp(x)
-class ExponentialFunctor {
+class CERES_EXPORT_INTERNAL ExponentialFunctor {
  public:
   bool operator()(const double* x1, double* residuals) const;
   void ExpectCostFunctionEvaluationIsNearlyCorrect(
@@ -113,7 +115,7 @@
 // Test adaptive numeric differentiation by synthetically adding random noise
 // to a functor.
 // y = x^2 + [random noise], dy/dx ~ 2x
-class RandomizedFunctor {
+class CERES_EXPORT_INTERNAL RandomizedFunctor {
  public:
   RandomizedFunctor(double noise_factor, unsigned int random_seed)
       : noise_factor_(noise_factor), random_seed_(random_seed) {}
@@ -127,7 +129,8 @@
   unsigned int random_seed_;
 };
 
-class RandomizedCostFunction : public SizedCostFunction<1, 1> {
+class CERES_EXPORT_INTERNAL RandomizedCostFunction
+    : public SizedCostFunction<1, 1> {
  public:
   RandomizedCostFunction(double noise_factor, unsigned int random_seed)
       : functor_(noise_factor, random_seed) {}
diff --git a/internal/ceres/parallel_for.h b/internal/ceres/parallel_for.h
index 2da2320..b64bd31 100644
--- a/internal/ceres/parallel_for.h
+++ b/internal/ceres/parallel_for.h
@@ -34,6 +34,7 @@
 #include <functional>
 
 #include "ceres/context_impl.h"
+#include "ceres/internal/port.h"
 
 namespace ceres {
 namespace internal {
@@ -45,22 +46,24 @@
 // Execute the function for every element in the range [start, end) with at most
 // num_threads. It will execute all the work on the calling thread if
 // num_threads is 1.
-void ParallelFor(ContextImpl* context,
-                 int start,
-                 int end,
-                 int num_threads,
-                 const std::function<void(int)>& function);
+CERES_EXPORT_INTERNAL void ParallelFor(
+    ContextImpl* context,
+    int start,
+    int end,
+    int num_threads,
+    const std::function<void(int)>& function);
 
 // Execute the function for every element in the range [start, end) with at most
 // num_threads. It will execute all the work on the calling thread if
 // num_threads is 1.  Each invocation of function() will be passed a thread_id
 // in [0, num_threads) that is guaranteed to be distinct from the value passed
 // to any concurrent execution of function().
-void ParallelFor(ContextImpl* context,
-                 int start,
-                 int end,
-                 int num_threads,
-                 const std::function<void(int thread_id, int i)>& function);
+CERES_EXPORT_INTERNAL void ParallelFor(
+    ContextImpl* context,
+    int start,
+    int end,
+    int num_threads,
+    const std::function<void(int thread_id, int i)>& function);
 }  // namespace internal
 }  // namespace ceres
 
diff --git a/internal/ceres/parallel_utils.h b/internal/ceres/parallel_utils.h
index 1291428..89d2110 100644
--- a/internal/ceres/parallel_utils.h
+++ b/internal/ceres/parallel_utils.h
@@ -31,6 +31,8 @@
 #ifndef CERES_INTERNAL_PARALLEL_UTILS_H_
 #define CERES_INTERNAL_PARALLEL_UTILS_H_
 
+#include "ceres/internal/port.h"
+
 namespace ceres {
 namespace internal {
 
@@ -59,7 +61,10 @@
 //    });
 // which in each iteration will produce i and j satisfying
 // 0 <= i <= j < n
-void LinearIndexToUpperTriangularIndex(int k, int n, int* i, int* j);
+CERES_EXPORT_INTERNAL void LinearIndexToUpperTriangularIndex(int k,
+                                                             int n,
+                                                             int* i,
+                                                             int* j);
 
 }  // namespace internal
 }  // namespace ceres
diff --git a/internal/ceres/parameter_block_ordering.h b/internal/ceres/parameter_block_ordering.h
index 7b58afd..82ab75d 100644
--- a/internal/ceres/parameter_block_ordering.h
+++ b/internal/ceres/parameter_block_ordering.h
@@ -34,6 +34,7 @@
 #include <vector>
 
 #include "ceres/graph.h"
+#include "ceres/internal/port.h"
 #include "ceres/ordered_groups.h"
 #include "ceres/types.h"
 
@@ -56,33 +57,34 @@
 // ordering = [independent set,
 //             complement of the independent set,
 //             fixed blocks]
-int ComputeSchurOrdering(const Program& program,
-                         std::vector<ParameterBlock*>* ordering);
+CERES_EXPORT_INTERNAL int ComputeSchurOrdering(
+    const Program& program, std::vector<ParameterBlock*>* ordering);
 
 // Same as above, except that ties while computing the independent set
 // ordering are resolved in favour of the order in which the parameter
 // blocks occur in the program.
-int ComputeStableSchurOrdering(const Program& program,
-                               std::vector<ParameterBlock*>* ordering);
+CERES_EXPORT_INTERNAL int ComputeStableSchurOrdering(
+    const Program& program, std::vector<ParameterBlock*>* ordering);
 
 // Use an approximate independent set ordering to decompose the
 // parameter blocks of a problem in a sequence of independent
 // sets. The ordering covers all the non-constant parameter blocks in
 // the program.
-void ComputeRecursiveIndependentSetOrdering(const Program& program,
-                                            ParameterBlockOrdering* ordering);
+CERES_EXPORT_INTERNAL void ComputeRecursiveIndependentSetOrdering(
+    const Program& program, ParameterBlockOrdering* ordering);
 
 // Builds a graph on the parameter blocks of a Problem, whose
 // structure reflects the sparsity structure of the Hessian. Each
 // vertex corresponds to a parameter block in the Problem except for
 // parameter blocks that are marked constant. An edge connects two
 // parameter blocks, if they co-occur in a residual block.
-Graph<ParameterBlock*>* CreateHessianGraph(const Program& program);
+CERES_EXPORT_INTERNAL Graph<ParameterBlock*>* CreateHessianGraph(
+    const Program& program);
 
 // Iterate over each of the groups in order of their priority and fill
 // summary with their sizes.
-void OrderingToGroupSizes(const ParameterBlockOrdering* ordering,
-                          std::vector<int>* group_sizes);
+CERES_EXPORT_INTERNAL void OrderingToGroupSizes(
+    const ParameterBlockOrdering* ordering, std::vector<int>* group_sizes);
 
 }  // namespace internal
 }  // namespace ceres
diff --git a/internal/ceres/partitioned_matrix_view.h b/internal/ceres/partitioned_matrix_view.h
index b8ac3b2..9f204ee 100644
--- a/internal/ceres/partitioned_matrix_view.h
+++ b/internal/ceres/partitioned_matrix_view.h
@@ -42,6 +42,7 @@
 
 #include "ceres/block_structure.h"
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/linear_solver.h"
 #include "ceres/small_blas.h"
 #include "glog/logging.h"
@@ -59,7 +60,7 @@
 // block structure of the matrix does not satisfy the requirements of
 // the Schur complement solver it will result in unpredictable and
 // wrong output.
-class PartitionedMatrixViewBase {
+class CERES_EXPORT_INTERNAL PartitionedMatrixViewBase {
  public:
   virtual ~PartitionedMatrixViewBase() {}
 
diff --git a/internal/ceres/polynomial.h b/internal/ceres/polynomial.h
index 40e4150..20071f2 100644
--- a/internal/ceres/polynomial.h
+++ b/internal/ceres/polynomial.h
@@ -66,13 +66,13 @@
 // On failure, a more detailed message will be written to LOG(ERROR).
 // If real is not NULL, the real parts of the roots will be returned in it.
 // Likewise, if imaginary is not NULL, imaginary parts will be returned in it.
-bool FindPolynomialRoots(const Vector& polynomial,
-                         Vector* real,
-                         Vector* imaginary);
+CERES_EXPORT_INTERNAL bool FindPolynomialRoots(const Vector& polynomial,
+                                               Vector* real,
+                                               Vector* imaginary);
 
 // Return the derivative of the given polynomial. It is assumed that
 // the input polynomial is at least of degree zero.
-Vector DifferentiatePolynomial(const Vector& polynomial);
+CERES_EXPORT_INTERNAL Vector DifferentiatePolynomial(const Vector& polynomial);
 
 // Find the minimum value of the polynomial in the interval [x_min,
 // x_max]. The minimum is obtained by computing all the roots of the
@@ -80,11 +80,11 @@
 // interval [x_min, x_max] are considered as well as the end points
 // x_min and x_max. Since polynomials are differentiable functions,
 // this ensures that the true minimum is found.
-void MinimizePolynomial(const Vector& polynomial,
-                        double x_min,
-                        double x_max,
-                        double* optimal_x,
-                        double* optimal_value);
+CERES_EXPORT_INTERNAL void MinimizePolynomial(const Vector& polynomial,
+                                              double x_min,
+                                              double x_max,
+                                              double* optimal_x,
+                                              double* optimal_value);
 
 // Given a set of function value and/or gradient samples, find a
 // polynomial whose value and gradients are exactly equal to the ones
@@ -97,7 +97,8 @@
 // Of course its possible to sample a polynomial any number of times,
 // in which case, generally speaking the spurious higher order
 // coefficients will be zero.
-Vector FindInterpolatingPolynomial(const std::vector<FunctionSample>& samples);
+CERES_EXPORT_INTERNAL Vector
+FindInterpolatingPolynomial(const std::vector<FunctionSample>& samples);
 
 // Interpolate the function described by samples with a polynomial,
 // and minimize it on the interval [x_min, x_max]. Depending on the
@@ -105,11 +106,12 @@
 // finding algorithms may fail due to numerical difficulties. But the
 // function is guaranteed to return its best guess of an answer, by
 // considering the samples and the end points as possible solutions.
-void MinimizeInterpolatingPolynomial(const std::vector<FunctionSample>& samples,
-                                     double x_min,
-                                     double x_max,
-                                     double* optimal_x,
-                                     double* optimal_value);
+CERES_EXPORT_INTERNAL void MinimizeInterpolatingPolynomial(
+    const std::vector<FunctionSample>& samples,
+    double x_min,
+    double x_max,
+    double* optimal_x,
+    double* optimal_value);
 
 }  // namespace internal
 }  // namespace ceres
diff --git a/internal/ceres/preconditioner.h b/internal/ceres/preconditioner.h
index b10364b..dd843b0 100644
--- a/internal/ceres/preconditioner.h
+++ b/internal/ceres/preconditioner.h
@@ -36,6 +36,7 @@
 #include "ceres/casts.h"
 #include "ceres/compressed_row_sparse_matrix.h"
 #include "ceres/context_impl.h"
+#include "ceres/internal/port.h"
 #include "ceres/linear_operator.h"
 #include "ceres/sparse_matrix.h"
 #include "ceres/types.h"
@@ -46,7 +47,7 @@
 class BlockSparseMatrix;
 class SparseMatrix;
 
-class Preconditioner : public LinearOperator {
+class CERES_EXPORT_INTERNAL Preconditioner : public LinearOperator {
  public:
   struct Options {
     PreconditionerType type = JACOBI;
diff --git a/internal/ceres/preprocessor.h b/internal/ceres/preprocessor.h
index e69c790..ec56c6e 100644
--- a/internal/ceres/preprocessor.h
+++ b/internal/ceres/preprocessor.h
@@ -67,7 +67,7 @@
 //
 // The output of the Preprocessor is stored in a PreprocessedProblem
 // object.
-class Preprocessor {
+class CERES_EXPORT_INTERNAL Preprocessor {
  public:
   // Factory.
   static Preprocessor* Create(MinimizerType minimizer_type);
diff --git a/internal/ceres/problem_impl.h b/internal/ceres/problem_impl.h
index 004918a..9abff3f 100644
--- a/internal/ceres/problem_impl.h
+++ b/internal/ceres/problem_impl.h
@@ -63,7 +63,7 @@
 class Program;
 class ResidualBlock;
 
-class ProblemImpl {
+class CERES_EXPORT_INTERNAL ProblemImpl {
  public:
   typedef std::map<double*, ParameterBlock*> ParameterMap;
   typedef std::unordered_set<ResidualBlock*> ResidualBlockSet;
diff --git a/internal/ceres/program.h b/internal/ceres/program.h
index c4935e3..ca29d31 100644
--- a/internal/ceres/program.h
+++ b/internal/ceres/program.h
@@ -57,7 +57,7 @@
 // another; for example, the first stage of solving involves stripping all
 // constant parameters and residuals. This is in contrast with Problem, which is
 // not built for transformation.
-class Program {
+class CERES_EXPORT_INTERNAL Program {
  public:
   Program();
   explicit Program(const Program& program);
diff --git a/internal/ceres/reorder_program.h b/internal/ceres/reorder_program.h
index e32079c..2e0c326 100644
--- a/internal/ceres/reorder_program.h
+++ b/internal/ceres/reorder_program.h
@@ -44,17 +44,17 @@
 class Program;
 
 // Reorder the parameter blocks in program using the ordering
-bool ApplyOrdering(const ProblemImpl::ParameterMap& parameter_map,
-                   const ParameterBlockOrdering& ordering,
-                   Program* program,
-                   std::string* error);
+CERES_EXPORT_INTERNAL bool ApplyOrdering(
+    const ProblemImpl::ParameterMap& parameter_map,
+    const ParameterBlockOrdering& ordering,
+    Program* program,
+    std::string* error);
 
 // Reorder the residuals for program, if necessary, so that the residuals
 // involving each E block occur together. This is a necessary condition for the
 // Schur eliminator, which works on these "row blocks" in the jacobian.
-bool LexicographicallyOrderResidualBlocks(int size_of_first_elimination_group,
-                                          Program* program,
-                                          std::string* error);
+CERES_EXPORT_INTERNAL bool LexicographicallyOrderResidualBlocks(
+    int size_of_first_elimination_group, Program* program, std::string* error);
 
 // Schur type solvers require that all parameter blocks eliminated
 // by the Schur eliminator occur before others and the residuals be
@@ -72,7 +72,7 @@
 //
 // Upon return, ordering contains the parameter block ordering that
 // was used to order the program.
-bool ReorderProgramForSchurTypeLinearSolver(
+CERES_EXPORT_INTERNAL bool ReorderProgramForSchurTypeLinearSolver(
     LinearSolverType linear_solver_type,
     SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type,
     const ProblemImpl::ParameterMap& parameter_map,
@@ -90,7 +90,7 @@
 // fill-reducing ordering is available in the sparse linear algebra
 // library (SuiteSparse version >= 4.2.0) then the fill reducing
 // ordering will take it into account, otherwise it will be ignored.
-bool ReorderProgramForSparseCholesky(
+CERES_EXPORT_INTERNAL bool ReorderProgramForSparseCholesky(
     SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type,
     const ParameterBlockOrdering& parameter_block_ordering,
     int start_row_block,
@@ -107,7 +107,7 @@
 // bottom_residual_blocks.size() because we allow
 // bottom_residual_blocks to contain residual blocks not present in
 // the Program.
-int ReorderResidualBlocksByPartition(
+CERES_EXPORT_INTERNAL int ReorderResidualBlocksByPartition(
     const std::unordered_set<ResidualBlockId>& bottom_residual_blocks,
     Program* program);
 
diff --git a/internal/ceres/residual_block.h b/internal/ceres/residual_block.h
index 3d75339..f28fd42 100644
--- a/internal/ceres/residual_block.h
+++ b/internal/ceres/residual_block.h
@@ -65,7 +65,7 @@
 //
 // The residual block stores pointers to but does not own the cost functions,
 // loss functions, and parameter blocks.
-class ResidualBlock {
+class CERES_EXPORT_INTERNAL ResidualBlock {
  public:
   // Construct the residual block with the given cost/loss functions. Loss may
   // be null. The index is the index of the residual block in the Program's
diff --git a/internal/ceres/schur_complement_solver.h b/internal/ceres/schur_complement_solver.h
index 464af09..3bfa22f 100644
--- a/internal/ceres/schur_complement_solver.h
+++ b/internal/ceres/schur_complement_solver.h
@@ -107,7 +107,8 @@
 // set to DENSE_SCHUR and SPARSE_SCHUR
 // respectively. LinearSolver::Options::elimination_groups[0] should
 // be at least 1.
-class SchurComplementSolver : public BlockSparseMatrixSolver {
+class CERES_EXPORT_INTERNAL SchurComplementSolver
+    : public BlockSparseMatrixSolver {
  public:
   explicit SchurComplementSolver(const LinearSolver::Options& options)
       : options_(options) {
diff --git a/internal/ceres/schur_eliminator.h b/internal/ceres/schur_eliminator.h
index 66fcb4d..42c016e 100644
--- a/internal/ceres/schur_eliminator.h
+++ b/internal/ceres/schur_eliminator.h
@@ -164,7 +164,7 @@
 // 2008 for an example of such use].
 //
 // Example usage: Please see schur_complement_solver.cc
-class SchurEliminatorBase {
+class CERES_EXPORT_INTERNAL SchurEliminatorBase {
  public:
   virtual ~SchurEliminatorBase() {}
 
diff --git a/internal/ceres/single_linkage_clustering.h b/internal/ceres/single_linkage_clustering.h
index ef6bff4..e891a9e 100644
--- a/internal/ceres/single_linkage_clustering.h
+++ b/internal/ceres/single_linkage_clustering.h
@@ -34,6 +34,7 @@
 #include <unordered_map>
 
 #include "ceres/graph.h"
+#include "ceres/internal/port.h"
 
 namespace ceres {
 namespace internal {
@@ -54,10 +55,10 @@
 //
 // The return value of this function is the number of clusters
 // identified by the algorithm.
-int ComputeSingleLinkageClustering(
-    const SingleLinkageClusteringOptions& options,
-    const WeightedGraph<int>& graph,
-    std::unordered_map<int, int>* membership);
+int CERES_EXPORT_INTERNAL
+ComputeSingleLinkageClustering(const SingleLinkageClusteringOptions& options,
+                               const WeightedGraph<int>& graph,
+                               std::unordered_map<int, int>* membership);
 
 }  // namespace internal
 }  // namespace ceres
diff --git a/internal/ceres/sparse_cholesky.h b/internal/ceres/sparse_cholesky.h
index 9be98bd..a6af6b2 100644
--- a/internal/ceres/sparse_cholesky.h
+++ b/internal/ceres/sparse_cholesky.h
@@ -67,7 +67,7 @@
 //  CHECK_EQ(sparse_cholesky->Solve(rhs.data(), solution.data(), &message),
 //           LINEAR_SOLVER_SUCCESS);
 
-class SparseCholesky {
+class CERES_EXPORT_INTERNAL SparseCholesky {
  public:
   static std::unique_ptr<SparseCholesky> Create(
       const LinearSolver::Options& options);
@@ -115,7 +115,7 @@
 
 // Computes an initial solution using the given instance of
 // SparseCholesky, and then refines it using the IterativeRefiner.
-class RefinedSparseCholesky : public SparseCholesky {
+class CERES_EXPORT_INTERNAL RefinedSparseCholesky : public SparseCholesky {
  public:
   RefinedSparseCholesky(std::unique_ptr<SparseCholesky> sparse_cholesky,
                         std::unique_ptr<IterativeRefiner> iterative_refiner);
diff --git a/internal/ceres/sparse_matrix.h b/internal/ceres/sparse_matrix.h
index b8a3918..b57f108 100644
--- a/internal/ceres/sparse_matrix.h
+++ b/internal/ceres/sparse_matrix.h
@@ -36,6 +36,7 @@
 #include <cstdio>
 
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/linear_operator.h"
 #include "ceres/types.h"
 
@@ -63,7 +64,7 @@
 // matrix type dependent and we are at this stage unable to come up
 // with an efficient high level interface that spans multiple sparse
 // matrix types.
-class SparseMatrix : public LinearOperator {
+class CERES_EXPORT_INTERNAL SparseMatrix : public LinearOperator {
  public:
   virtual ~SparseMatrix();
 
diff --git a/internal/ceres/stringprintf.h b/internal/ceres/stringprintf.h
index 98e98cd..4d51278 100644
--- a/internal/ceres/stringprintf.h
+++ b/internal/ceres/stringprintf.h
@@ -63,25 +63,28 @@
 #endif
 
 // Return a C++ string.
-extern std::string StringPrintf(const char* format, ...)
+CERES_EXPORT_INTERNAL extern std::string StringPrintf(const char* format, ...)
     // Tell the compiler to do printf format string checking.
     CERES_PRINTF_ATTRIBUTE(1, 2);
 
 // Store result into a supplied string and return it.
-extern const std::string& SStringPrintf(std::string* dst,
-                                        const char* format,
-                                        ...)
+CERES_EXPORT_INTERNAL extern const std::string& SStringPrintf(
+    std::string* dst, const char* format, ...)
     // Tell the compiler to do printf format string checking.
     CERES_PRINTF_ATTRIBUTE(2, 3);
 
 // Append result to a supplied string.
-extern void StringAppendF(std::string* dst, const char* format, ...)
+CERES_EXPORT_INTERNAL extern void StringAppendF(std::string* dst,
+                                                const char* format,
+                                                ...)
     // Tell the compiler to do printf format string checking.
     CERES_PRINTF_ATTRIBUTE(2, 3);
 
 // Lower-level routine that takes a va_list and appends to a specified string.
 // All other routines are just convenience wrappers around it.
-extern void StringAppendV(std::string* dst, const char* format, va_list ap);
+CERES_EXPORT_INTERNAL extern void StringAppendV(std::string* dst,
+                                                const char* format,
+                                                va_list ap);
 
 #undef CERES_PRINTF_ATTRIBUTE
 
diff --git a/internal/ceres/subset_preconditioner.h b/internal/ceres/subset_preconditioner.h
index f83153c..9844a66 100644
--- a/internal/ceres/subset_preconditioner.h
+++ b/internal/ceres/subset_preconditioner.h
@@ -33,6 +33,7 @@
 
 #include <memory>
 
+#include "ceres/internal/port.h"
 #include "ceres/preconditioner.h"
 
 namespace ceres {
@@ -66,7 +67,8 @@
 // computationally expensive this preconditioner will be.
 //
 // See the tests for example usage.
-class SubsetPreconditioner : public BlockSparseMatrixPreconditioner {
+class CERES_EXPORT_INTERNAL SubsetPreconditioner
+    : public BlockSparseMatrixPreconditioner {
  public:
   SubsetPreconditioner(const Preconditioner::Options& options,
                        const BlockSparseMatrix& A);
diff --git a/internal/ceres/test_util.h b/internal/ceres/test_util.h
index ad98228..c33c69c 100644
--- a/internal/ceres/test_util.h
+++ b/internal/ceres/test_util.h
@@ -48,15 +48,17 @@
 //
 // If x and y have the same non-finite value (inf or nan) we treat them as being
 // close. In such a case no error is thrown and true is returned.
-bool ExpectClose(double x, double y, double max_abs_relative_difference);
+CERES_EXPORT_INTERNAL bool ExpectClose(double x,
+                                       double y,
+                                       double max_abs_relative_difference);
 
 // Expects that for all i = 1,.., n - 1
 //
 //   |p[i] - q[i]| / max(|p[i]|, |q[i]|) < tolerance
-void ExpectArraysClose(int n,
-                       const double* p,
-                       const double* q,
-                       double tolerance);
+CERES_EXPORT_INTERNAL void ExpectArraysClose(int n,
+                                             const double* p,
+                                             const double* q,
+                                             double tolerance);
 
 // Expects that for all i = 1,.., n - 1
 //
@@ -64,16 +66,17 @@
 //
 // where max_norm_p and max_norm_q are the max norms of the arrays p
 // and q respectively.
-void ExpectArraysCloseUptoScale(int n,
-                                const double* p,
-                                const double* q,
-                                double tolerance);
+CERES_EXPORT_INTERNAL void ExpectArraysCloseUptoScale(int n,
+                                                      const double* p,
+                                                      const double* q,
+                                                      double tolerance);
 
 // Construct a fully qualified path for the test file depending on the
 // local build/testing environment.
-std::string TestFileAbsolutePath(const std::string& filename);
+CERES_EXPORT_INTERNAL std::string TestFileAbsolutePath(
+    const std::string& filename);
 
-std::string ToString(const Solver::Options& options);
+CERES_EXPORT_INTERNAL std::string ToString(const Solver::Options& options);
 
 // A templated test fixture, that is used for testing Ceres end to end
 // by computing a solution to the problem for a given solver
diff --git a/internal/ceres/thread_pool.h b/internal/ceres/thread_pool.h
index 1ebb52e..cdf6625 100644
--- a/internal/ceres/thread_pool.h
+++ b/internal/ceres/thread_pool.h
@@ -37,6 +37,7 @@
 #include <vector>
 
 #include "ceres/concurrent_queue.h"
+#include "ceres/internal/port.h"
 
 namespace ceres {
 namespace internal {
@@ -57,7 +58,7 @@
 //  workers to stop.  The workers will finish all of the tasks that have already
 //  been added to the thread pool.
 //
-class ThreadPool {
+class CERES_EXPORT_INTERNAL ThreadPool {
  public:
   // Returns the maximum number of hardware threads.
   static int MaxNumThreadsAvailable();
diff --git a/internal/ceres/triplet_sparse_matrix.h b/internal/ceres/triplet_sparse_matrix.h
index cbda253..cc9fee5 100644
--- a/internal/ceres/triplet_sparse_matrix.h
+++ b/internal/ceres/triplet_sparse_matrix.h
@@ -35,6 +35,7 @@
 #include <vector>
 
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/sparse_matrix.h"
 #include "ceres/types.h"
 
@@ -45,7 +46,7 @@
 // manipulate sparse matrices in triplet (i,j,s) form.  This object is
 // inspired by the design of the cholmod_triplet struct used in the
 // SuiteSparse package and is memory layout compatible with it.
-class TripletSparseMatrix : public SparseMatrix {
+class CERES_EXPORT_INTERNAL TripletSparseMatrix : public SparseMatrix {
  public:
   TripletSparseMatrix();
   TripletSparseMatrix(int num_rows, int num_cols, int max_num_nonzeros);
diff --git a/internal/ceres/trust_region_minimizer.h b/internal/ceres/trust_region_minimizer.h
index 27a1b78..be4d406 100644
--- a/internal/ceres/trust_region_minimizer.h
+++ b/internal/ceres/trust_region_minimizer.h
@@ -34,6 +34,7 @@
 #include <memory>
 
 #include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
 #include "ceres/minimizer.h"
 #include "ceres/solver.h"
 #include "ceres/sparse_matrix.h"
@@ -47,7 +48,7 @@
 // Generic trust region minimization algorithm.
 //
 // For example usage, see SolverImpl::Minimize.
-class TrustRegionMinimizer : public Minimizer {
+class CERES_EXPORT_INTERNAL TrustRegionMinimizer : public Minimizer {
  public:
   ~TrustRegionMinimizer();
 
diff --git a/internal/ceres/trust_region_preprocessor.h b/internal/ceres/trust_region_preprocessor.h
index 9597905..2655abe 100644
--- a/internal/ceres/trust_region_preprocessor.h
+++ b/internal/ceres/trust_region_preprocessor.h
@@ -31,12 +31,13 @@
 #ifndef CERES_INTERNAL_TRUST_REGION_PREPROCESSOR_H_
 #define CERES_INTERNAL_TRUST_REGION_PREPROCESSOR_H_
 
+#include "ceres/internal/port.h"
 #include "ceres/preprocessor.h"
 
 namespace ceres {
 namespace internal {
 
-class TrustRegionPreprocessor : public Preprocessor {
+class CERES_EXPORT_INTERNAL TrustRegionPreprocessor : public Preprocessor {
  public:
   virtual ~TrustRegionPreprocessor();
   bool Preprocess(const Solver::Options& options,
diff --git a/internal/ceres/trust_region_strategy.h b/internal/ceres/trust_region_strategy.h
index 48e7347..176f73a 100644
--- a/internal/ceres/trust_region_strategy.h
+++ b/internal/ceres/trust_region_strategy.h
@@ -54,7 +54,7 @@
 // the LevenbergMarquardtStrategy uses the inverse of the trust region
 // radius to scale the damping term, which controls the step size, but
 // does not set a hard limit on its size.
-class TrustRegionStrategy {
+class CERES_EXPORT_INTERNAL TrustRegionStrategy {
  public:
   struct Options {
     TrustRegionStrategyType trust_region_strategy_type = LEVENBERG_MARQUARDT;
diff --git a/internal/ceres/visibility.h b/internal/ceres/visibility.h
index ed25d53..68c6723 100644
--- a/internal/ceres/visibility.h
+++ b/internal/ceres/visibility.h
@@ -39,6 +39,7 @@
 #include <vector>
 
 #include "ceres/graph.h"
+#include "ceres/internal/port.h"
 
 namespace ceres {
 namespace internal {
@@ -53,9 +54,10 @@
 //
 // In a structure from motion problem, e_blocks correspond to 3D
 // points and f_blocks correspond to cameras.
-void ComputeVisibility(const CompressedRowBlockStructure& block_structure,
-                       int num_eliminate_blocks,
-                       std::vector<std::set<int>>* visibility);
+CERES_EXPORT_INTERNAL void ComputeVisibility(
+    const CompressedRowBlockStructure& block_structure,
+    int num_eliminate_blocks,
+    std::vector<std::set<int>>* visibility);
 
 // Given f_block visibility as computed by the ComputeVisibility
 // function above, construct and return a graph whose vertices are
@@ -70,7 +72,7 @@
 //
 // Caller acquires ownership of the returned WeightedGraph pointer
 // (heap-allocated).
-WeightedGraph<int>* CreateSchurComplementGraph(
+CERES_EXPORT_INTERNAL WeightedGraph<int>* CreateSchurComplementGraph(
     const std::vector<std::set<int>>& visibility);
 
 }  // namespace internal
diff --git a/internal/ceres/wall_time.h b/internal/ceres/wall_time.h
index 3f465e8..9c92e9e 100644
--- a/internal/ceres/wall_time.h
+++ b/internal/ceres/wall_time.h
@@ -45,7 +45,7 @@
 // OpenMP is available then the high precision openmp_get_wtime()
 // function is used. Otherwise on unixes, gettimeofday is used. The
 // granularity is in seconds on windows systems.
-double WallTimeInSeconds();
+CERES_EXPORT_INTERNAL double WallTimeInSeconds();
 
 // Log a series of events, recording for each event the time elapsed
 // since the last event and since the creation of the object.