1

I've been trying to build Pymesh on MacOS 10.15 with GCC 9.3.0 and I get the following error in the make step

Scanning dependencies of target lib_IGL
[ 48%] Building CXX object tools/IGL/CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
[ 48%] Building CXX object tools/IGL/CMakeFiles/lib_IGL.dir/DiskCutter.cpp.o
[ 48%] Building CXX object tools/IGL/CMakeFiles/lib_IGL.dir/HarmonicSolver.cpp.o
[ 49%] Building CXX object tools/IGL/CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
[ 49%] Linking CXX shared library ../../../python/pymesh/lib/libPyMesh-IGL.dylib
duplicate symbol 'typeinfo name for CORE::Realbase_for' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::Realbase_for' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::Realbase_for' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::Realbase_for' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::Realbase_forCORE::BigInt' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::Realbase_forCORE::BigInt' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::ConstPolyRepCORE::BigInt' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::ConstPolyRepCORE::BigInt' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::Realbase_forCORE::BigFloat' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::Realbase_forCORE::BigFloat' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::ConstPolyRepCORE::BigFloat' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::ConstPolyRepCORE::BigFloat' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::Realbase_forCORE::BigRat' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::Realbase_forCORE::BigRat' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::ConstPolyRepCORE::BigRat' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::ConstPolyRepCORE::BigRat' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::ConstPolyRepCORE::Expr' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::ConstPolyRepCORE::Expr' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::AddSubRepCORE::Add' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::AddSubRepCORE::Add' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo name for CORE::AddSubRepCORE::Sub' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
duplicate symbol 'typeinfo for CORE::AddSubRepCORE::Sub' in:
CMakeFiles/lib_IGL.dir/CellPartition.cpp.o
CMakeFiles/lib_IGL.dir/MinkowskiSum.cpp.o
ld: 22 duplicate symbols for architecture x86_64
collect2: error: ld returned 1 exit status
make[2]: *** [../python/pymesh/lib/libPyMesh-IGL.dylib] Error 1
make[1]: *** [tools/IGL/CMakeFiles/lib_IGL.dir/all] Error 2
make: *** [all] Error 2

So I went over to the files to see what was wrong

MinkowskiSum.cpp

#ifdef WITH_IGL_AND_CGAL
#include "MinkowskiSum.h"
#include <Math/MatrixUtils.h>
#include <igl/copyleft/cgal/minkowski_sum.h>
#include <igl/copyleft/cgal/mesh_boolean.h>
#include <igl/MeshBooleanType.h>

#include <vector>

using namespace PyMesh;

MinkowskiSum::Ptr MinkowskiSum::create(const Mesh::Ptr& mesh) {
    const MatrixFr vertices = MatrixUtils::reshape<MatrixFr>(
            mesh->get_vertices(), mesh->get_num_vertices(), mesh->get_dim());
    const MatrixIr faces = MatrixUtils::reshape<MatrixIr>(
            mesh->get_faces(), mesh->get_num_faces(),
            mesh->get_vertex_per_face());
    return MinkowskiSum::Ptr(new MinkowskiSum(vertices, faces));
}

MinkowskiSum::Ptr MinkowskiSum::create_raw(
        const MatrixFr& vertices, const MatrixIr& faces) {
    return MinkowskiSum::Ptr(new MinkowskiSum(vertices, faces));
}

void MinkowskiSum::run(const MatrixFr& path) {
    const size_t num_pts = path.rows();
    if (num_pts <= 1) {
        m_out_vertices = m_vertices;
        m_out_faces = m_faces;
        return;
    }

    std::vector<MatrixFr> vertices;
    std::vector<MatrixIr> faces;

    for (size_t i=1; i<num_pts; i++) {
        const Eigen::Matrix<Float, 1, 3> s = path.row(i-1);
        const Eigen::Matrix<Float, 1, 3> d = path.row(i);
        MatrixFr V;
        MatrixIr F;
        VectorI J;

        igl::copyleft::cgal::minkowski_sum<
            MatrixFr, MatrixIr,
            Float, 3, 1,
            Float, 3, 1,
            MatrixFr, MatrixIr, VectorI>(m_vertices, m_faces, s, d, V, F, J);
        vertices.emplace_back(V);
        faces.emplace_back(F);
    }

    size_t v_count = 0;
    for (size_t i=0; i<num_pts-1; i++) {
        faces[i].array() += v_count;
        v_count += vertices[i].rows();
    }

    MatrixFr combined_vertices = MatrixUtils::vstack(vertices);
    MatrixIr combined_faces = MatrixUtils::vstack(faces);

    // Self union to remove self-intersections.
    MatrixFr empty_vertices;
    MatrixIr empty_faces;
    VectorI J;

    igl::copyleft::cgal::mesh_boolean(
            combined_vertices, combined_faces,
            empty_vertices, empty_faces,
            igl::MESH_BOOLEAN_TYPE_UNION,
            m_out_vertices, m_out_faces, J);
}

#endif

Minkowski_Sum.h

#pragma once
#ifdef WITH_IGL_AND_CGAL
#include <memory>

#include <Core/EigenTypedef.h>
#include <Mesh.h>

namespace PyMesh {

class MinkowskiSum {
    public:
        typedef std::shared_ptr<MinkowskiSum> Ptr;
        static Ptr create(const Mesh::Ptr& mesh);
        static Ptr create_raw(const MatrixFr& vertices, const MatrixIr& faces);

    public:
        MinkowskiSum(const MatrixFr& vertices, const MatrixIr& faces):
            m_vertices(vertices), m_faces(faces) { }

        void run(const MatrixFr& path);

        MatrixFr get_vertices() const { return m_out_vertices; }
        MatrixIr get_faces() const { return m_out_faces; }

    private:
        MatrixFr m_vertices;
        MatrixIr m_faces;
        MatrixFr m_out_vertices;
        MatrixIr m_out_faces;
};

}

#endif

minkowski_sum.h

#ifndef IGL_COPYLEFT_CGAL_MINKOWSKI_SUM_H
#define IGL_COPYLEFT_CGAL_MINKOWSKI_SUM_H

#include "../../igl_inline.h"
#include <Eigen/Core>

namespace igl
{
  namespace copyleft
  {
    namespace cgal
    {
      // Compute the Minkowski sum of a closed triangle mesh (V,F) and a
      // set of simplices in 3D.
      //
      // Inputs:
      //   VA  #VA by 3 list of mesh vertices in 3D
      //   FA  #FA by 3 list of triangle indices into VA
      //   VB  #VB by 3 list of mesh vertices in 3D
      //   FB  #FB by ss list of simplex indices into VB, ss<=3
      //   resolve_overlaps  whether or not to resolve self-union. If false
      //     then result may contain self-intersections if input mesh is
      //     non-convex.
      // Outputs:
      //   W  #W by 3 list of mesh vertices in 3D
      //   G  #G by 3 list of triangle indices into W
      //   J  #G by 2 list of indices into 
      //   
      template <
        typename DerivedVA,
        typename DerivedFA,
        typename DerivedVB,
        typename DerivedFB,
        typename DerivedW,
        typename DerivedG,
        typename DerivedJ>
      IGL_INLINE void minkowski_sum(
        const Eigen::MatrixBase<DerivedVA> & VA,
        const Eigen::MatrixBase<DerivedFA> & FA,
        const Eigen::MatrixBase<DerivedVB> & VB,
        const Eigen::MatrixBase<DerivedFB> & FB,
        const bool resolve_overlaps,
        Eigen::PlainObjectBase<DerivedW> & W,
        Eigen::PlainObjectBase<DerivedG> & G,
        Eigen::PlainObjectBase<DerivedJ> & J);
      // Compute the Minkowski sum of a closed triangle mesh (V,F) and a
      // segment [s,d] in 3D.
      //
      // Inputs:
      //   VA  #VA by 3 list of mesh vertices in 3D
      //   FA  #FA by 3 list of triangle indices into VA
      //   s  segment source endpoint in 3D
      //   d  segment source endpoint in 3D
      //   resolve_overlaps  whether or not to resolve self-union. If false
      //     then result may contain self-intersections if input mesh is
      //     non-convex.
      // Outputs:
      //   W  #W by 3 list of mesh vertices in 3D
      //   G  #G by 3 list of triangle indices into W
      //   J  #G list of indices into [F;#V+F;[s d]] of birth parents
      //
      template <
        typename DerivedVA,
        typename DerivedFA,
        typename sType, int sCols, int sOptions,
        typename dType, int dCols, int dOptions,
        typename DerivedW,
        typename DerivedG,
        typename DerivedJ>
      IGL_INLINE void minkowski_sum(
        const Eigen::MatrixBase<DerivedVA> & VA,
        const Eigen::MatrixBase<DerivedFA> & FA,
        const Eigen::Matrix<sType,1,sCols,sOptions> & s,
        const Eigen::Matrix<dType,1,dCols,dOptions> & d,
        const bool resolve_overlaps,
        Eigen::PlainObjectBase<DerivedW> & W,
        Eigen::PlainObjectBase<DerivedG> & G,
        Eigen::PlainObjectBase<DerivedJ> & J);
      template <
        typename DerivedVA,
        typename DerivedFA,
        typename sType, int sCols, int sOptions,
        typename dType, int dCols, int dOptions,
        typename DerivedW,
        typename DerivedG,
        typename DerivedJ>
      IGL_INLINE void minkowski_sum(
        const Eigen::MatrixBase<DerivedVA> & VA,
        const Eigen::MatrixBase<DerivedFA> & FA,
        const Eigen::Matrix<sType,1,sCols,sOptions> & s,
        const Eigen::Matrix<dType,1,dCols,dOptions> & d,
        Eigen::PlainObjectBase<DerivedW> & W,
        Eigen::PlainObjectBase<DerivedG> & G,
        Eigen::PlainObjectBase<DerivedJ> & J);
    }
  }
}

#ifndef IGL_STATIC_LIBRARY
#  include "minkowski_sum.cpp"
#endif

#endif

mesh_boolean.h

#ifndef IGL_COPYLEFT_CGAL_MESH_BOOLEAN_H
#define IGL_COPYLEFT_CGAL_MESH_BOOLEAN_H

#include "../../igl_inline.h"
#include "../../MeshBooleanType.h"
#include <Eigen/Core>
#include <functional>
#include <vector>

namespace igl
{
  namespace copyleft
  {
    namespace cgal
    {
      //  MESH_BOOLEAN Compute boolean csg operations on "solid", consistently
      //  oriented meshes.
      //
      //  Inputs:
      //    VA  #VA by 3 list of vertex positions of first mesh
      //    FA  #FA by 3 list of triangle indices into VA
      //    VB  #VB by 3 list of vertex positions of second mesh
      //    FB  #FB by 3 list of triangle indices into VB
      //    type  type of boolean operation
      //  Outputs:
      //    VC  #VC by 3 list of vertex positions of boolean result mesh
      //    FC  #FC by 3 list of triangle indices into VC
      //    J  #FC list of indices into [FA;FA.rows()+FB] revealing "birth" facet
      //  Returns true if inputs induce a piecewise constant winding number
      //  field and type is valid
      //
      //  See also: mesh_boolean_cork, intersect_other,
      //  remesh_self_intersections
      template <
        typename DerivedVA,
        typename DerivedFA,
        typename DerivedVB,
        typename DerivedFB,
        typename DerivedVC,
        typename DerivedFC,
        typename DerivedJ>
      IGL_INLINE bool mesh_boolean(
        const Eigen::MatrixBase<DerivedVA > & VA,
        const Eigen::MatrixBase<DerivedFA > & FA,
        const Eigen::MatrixBase<DerivedVB > & VB,
        const Eigen::MatrixBase<DerivedFB > & FB,
        const MeshBooleanType & type,
        Eigen::PlainObjectBase<DerivedVC > & VC,
        Eigen::PlainObjectBase<DerivedFC > & FC,
        Eigen::PlainObjectBase<DerivedJ > & J);
      template <
        typename DerivedVA,
        typename DerivedFA,
        typename DerivedVB,
        typename DerivedFB,
        typename DerivedVC,
        typename DerivedFC,
        typename DerivedJ>
      IGL_INLINE bool mesh_boolean(
        const Eigen::MatrixBase<DerivedVA > & VA,
        const Eigen::MatrixBase<DerivedFA > & FA,
        const Eigen::MatrixBase<DerivedVB > & VB,
        const Eigen::MatrixBase<DerivedFB > & FB,
        const std::string & type_str,
        Eigen::PlainObjectBase<DerivedVC > & VC,
        Eigen::PlainObjectBase<DerivedFC > & FC,
        Eigen::PlainObjectBase<DerivedJ > & J);
      //
      //  Inputs:
      //    VA  #VA by 3 list of vertex positions of first mesh
      //    FA  #FA by 3 list of triangle indices into VA
      //    VB  #VB by 3 list of vertex positions of second mesh
      //    FB  #FB by 3 list of triangle indices into VB
      //    wind_num_op  function handle for filtering winding numbers from
      //      tuples of integer values to [0,1] outside/inside values
      //    keep  function handle for determining if a patch should be "kept"
      //      in the output based on the winding number on either side
      //  Outputs:
      //    VC  #VC by 3 list of vertex positions of boolean result mesh
      //    FC  #FC by 3 list of triangle indices into VC
      //    J  #FC list of indices into [FA;FB] revealing "birth" facet
      //  Returns true iff inputs induce a piecewise constant winding number
      //    field
      //
      //  See also: mesh_boolean_cork, intersect_other,
      //  remesh_self_intersections
      template <
        typename DerivedVA,
        typename DerivedFA,
        typename DerivedVB,
        typename DerivedFB,
        typename DerivedVC,
        typename DerivedFC,
        typename DerivedJ>
      IGL_INLINE bool mesh_boolean(
          const Eigen::MatrixBase<DerivedVA> & VA,
          const Eigen::MatrixBase<DerivedFA> & FA,
          const Eigen::MatrixBase<DerivedVB> & VB,
          const Eigen::MatrixBase<DerivedFB> & FB,
          const std::function<int(const Eigen::Matrix<int,1,Eigen::Dynamic>) >& wind_num_op,
          const std::function<int(const int, const int)> & keep,
          Eigen::PlainObjectBase<DerivedVC > & VC,
          Eigen::PlainObjectBase<DerivedFC > & FC,
          Eigen::PlainObjectBase<DerivedJ > & J);
      //  MESH_BOOLEAN Variadic boolean operations
      //
      //  Inputs:
      //    Vlist  k-long list of lists of mesh vertex positions
      //    Flist  k-long list of lists of mesh face indices, so that Flist[i] indexes
      //      vertices in Vlist[i]
      //    wind_num_op  function handle for filtering winding numbers from
      //      n-tuples of integer values to [0,1] outside/inside values
      //    keep  function handle for determining if a patch should be "kept"
      //      in the output based on the winding number on either side
      //  Outputs:
      //    VC  #VC by 3 list of vertex positions of boolean result mesh
      //    FC  #FC by 3 list of triangle indices into VC
      //    J  #FC list of indices into [Flist[0];Flist[1];...;Flist[k]]
      //      revealing "birth" facet
      //  Returns true iff inputs induce a piecewise constant winding number
      //    field
      //
      //  See also: mesh_boolean_cork, intersect_other,
      //  remesh_self_intersections
      template <
        typename DerivedV,
        typename DerivedF,
        typename DerivedVC,
        typename DerivedFC,
        typename DerivedJ>
      IGL_INLINE bool mesh_boolean(
          const std::vector<DerivedV > & Vlist,
          const std::vector<DerivedF > & Flist,
          const std::function<int(const Eigen::Matrix<int,1,Eigen::Dynamic>) >& wind_num_op,
          const std::function<int(const int, const int)> & keep,
          Eigen::PlainObjectBase<DerivedVC > & VC,
          Eigen::PlainObjectBase<DerivedFC > & FC,
          Eigen::PlainObjectBase<DerivedJ > & J);
      template <
        typename DerivedV,
        typename DerivedF,
        typename DerivedVC,
        typename DerivedFC,
        typename DerivedJ>
      IGL_INLINE bool mesh_boolean(
          const std::vector<DerivedV > & Vlist,
          const std::vector<DerivedF > & Flist,
          const MeshBooleanType & type,
          Eigen::PlainObjectBase<DerivedVC > & VC,
          Eigen::PlainObjectBase<DerivedFC > & FC,
          Eigen::PlainObjectBase<DerivedJ > & J);
      // Given a merged mesh (V,F) and list of sizes of inputs
      //
      // Inputs:
      //   V  #V by 3 list of merged mesh vertex positions
      //   F  #F by 3 list of merged mesh face indices so that first sizes(0)
      //     faces come from the first input, and the next sizes(1) faces come
      //     from the second input, and so on.
      //   sizes  #inputs list of sizes so that sizes(i) is the #faces in the
      //     ith input
      //    wind_num_op  function handle for filtering winding numbers from
      //      tuples of integer values to [0,1] outside/inside values
      //    keep  function handle for determining if a patch should be "kept"
      //      in the output based on the winding number on either side
      //  Outputs:
      //    VC  #VC by 3 list of vertex positions of boolean result mesh
      //    FC  #FC by 3 list of triangle indices into VC
      //    J  #FC list of birth parent indices
      // 
      template <
        typename DerivedVV,
        typename DerivedFF,
        typename Derivedsizes,
        typename DerivedVC,
        typename DerivedFC,
        typename DerivedJ>
      IGL_INLINE bool mesh_boolean(
          const Eigen::MatrixBase<DerivedVV > & VV,
          const Eigen::MatrixBase<DerivedFF > & FF,
          const Eigen::MatrixBase<Derivedsizes> & sizes,
          const std::function<int(const Eigen::Matrix<int,1,Eigen::Dynamic>) >& wind_num_op,
          const std::function<int(const int, const int)> & keep,
          Eigen::PlainObjectBase<DerivedVC > & VC,
          Eigen::PlainObjectBase<DerivedFC > & FC,
          Eigen::PlainObjectBase<DerivedJ > & J);
      //  Inputs:
      //    VA  #VA by 3 list of vertex positions of first mesh
      //    FA  #FA by 3 list of triangle indices into VA
      //    VB  #VB by 3 list of vertex positions of second mesh
      //    FB  #FB by 3 list of triangle indices into VB
      //    type  type of boolean operation
      //  Outputs:
      //    VC  #VC by 3 list of vertex positions of boolean result mesh
      //    FC  #FC by 3 list of triangle indices into VC
      //  Returns true ff inputs induce a piecewise constant winding number
      //    field and type is valid
      template <
        typename DerivedVA,
        typename DerivedFA,
        typename DerivedVB,
        typename DerivedFB,
        typename DerivedVC,
        typename DerivedFC>
      IGL_INLINE bool mesh_boolean(
          const Eigen::MatrixBase<DerivedVA > & VA,
          const Eigen::MatrixBase<DerivedFA > & FA,
          const Eigen::MatrixBase<DerivedVB > & VB,
          const Eigen::MatrixBase<DerivedFB > & FB,
          const MeshBooleanType & type,
          Eigen::PlainObjectBase<DerivedVC > & VC,
          Eigen::PlainObjectBase<DerivedFC > & FC);
    }
  }
}

#ifndef IGL_STATIC_LIBRARY
#  include "mesh_boolean.cpp"
#endif

#endif

minkowski_sum.cpp

#include "minkowski_sum.h"
#include "mesh_boolean.h"

#include "../../slice.h"
#include "../../slice_mask.h"
#include "../../LinSpaced.h"
#include "../../unique_rows.h"
#include "../../get_seconds.h"
#include "../../edges.h"
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <cassert>
#include <vector>
#include <iostream>


template <
  typename DerivedVA,
  typename DerivedFA,
  typename DerivedVB,
  typename DerivedFB,
  typename DerivedW,
  typename DerivedG,
  typename DerivedJ>
IGL_INLINE void igl::copyleft::cgal::minkowski_sum(
  const Eigen::MatrixBase<DerivedVA> & VA,
  const Eigen::MatrixBase<DerivedFA> & FA,
  const Eigen::MatrixBase<DerivedVB> & VB,
  const Eigen::MatrixBase<DerivedFB> & FB,
  const bool resolve_overlaps,
  Eigen::PlainObjectBase<DerivedW> & W,
  Eigen::PlainObjectBase<DerivedG> & G,
  Eigen::PlainObjectBase<DerivedJ> & J)
{
  using namespace std;
  using namespace Eigen;
  assert(FA.cols() == 3 && "FA must contain a closed triangle mesh");
  assert(FB.cols() <= FA.cols() && 
    "FB must contain lower diemnsional simplices than FA");
  const auto tictoc = []()->double
  {
    static double t_start;
    double now = igl::get_seconds();
    double interval = now-t_start;
    t_start = now;
    return interval;
  };
  tictoc();
  Matrix<typename DerivedFB::Scalar,Dynamic,2> EB;
  edges(FB,EB);
  Matrix<typename DerivedFA::Scalar,Dynamic,2> EA(0,2);
  if(FB.cols() == 3)
  {
    edges(FA,EA);
  }
  // number of copies of A along edges of B
  const int n_ab = EB.rows();
  // number of copies of B along edges of A
  const int n_ba = EA.rows();

  vector<DerivedW> vW(n_ab + n_ba);
  vector<DerivedG> vG(n_ab + n_ba);
  vector<DerivedJ> vJ(n_ab + n_ba);
  vector<int> offsets(n_ab + n_ba + 1);
  offsets[0] = 0;
  // sweep A along edges of B
  for(int e = 0;e<n_ab;e++)
  {
    Matrix<typename DerivedJ::Scalar,Dynamic,1> eJ;
    minkowski_sum(
      VA,
      FA,
      VB.row(EB(e,0)).eval(),
      VB.row(EB(e,1)).eval(),
      false,
      vW[e],
      vG[e],
      eJ);
    assert(vG[e].rows() == eJ.rows());
    assert(eJ.cols() == 1);
    vJ[e].resize(vG[e].rows(),2);
    vJ[e].col(0) = eJ;
    vJ[e].col(1).setConstant(e);
    offsets[e+1] = offsets[e] + vW[e].rows();
  }
  // sweep B along edges of A
  for(int e = 0;e<n_ba;e++)
  {
    Matrix<typename DerivedJ::Scalar,Dynamic,1> eJ;
    const int ee = n_ab+e;
    minkowski_sum(
      VB,
      FB,
      VA.row(EA(e,0)).eval(),
      VA.row(EA(e,1)).eval(),
      false,
      vW[ee],
      vG[ee],
      eJ);
    vJ[ee].resize(vG[ee].rows(),2);
    vJ[ee].col(0) = eJ.array() + (FA.rows()+1);
    vJ[ee].col(1).setConstant(ee);
    offsets[ee+1] = offsets[ee] + vW[ee].rows();
  }
  // Combine meshes
  int n=0,m=0;
  for_each(vW.begin(),vW.end(),[&n](const DerivedW & w){n+=w.rows();});
  for_each(vG.begin(),vG.end(),[&m](const DerivedG & g){m+=g.rows();});
  assert(n == offsets.back());

  W.resize(n,3);
  G.resize(m,3);
  J.resize(m,2);
  {
    int m_off = 0,n_off = 0;
    for(int i = 0;i<vG.size();i++)
    {
      W.block(n_off,0,vW[i].rows(),3) = vW[i];
      G.block(m_off,0,vG[i].rows(),3) = vG[i].array()+offsets[i];
      J.block(m_off,0,vJ[i].rows(),2) = vJ[i];
      n_off += vW[i].rows();
      m_off += vG[i].rows();
    }
    assert(n == n_off);
    assert(m == m_off);
  }
  if(resolve_overlaps)
  {
    Eigen::Matrix<typename DerivedJ::Scalar, Eigen::Dynamic,1> SJ;
    mesh_boolean(
      DerivedW(W),
      DerivedG(G),
      Matrix<typename DerivedW::Scalar,Dynamic,Dynamic>(),
      Matrix<typename DerivedG::Scalar,Dynamic,Dynamic>(),
      MESH_BOOLEAN_TYPE_UNION,
      W,
      G,
      SJ);
    slice(DerivedJ(J),SJ,1,J);
  }
}

#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
// generated by autoexplicit.sh
template void igl::copyleft::cgal::minkowski_sum<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, CGAL::Lazy_exact_nt<CGAL::Gmpq>, 3, 1, CGAL::Lazy_exact_nt<CGAL::Gmpq>, 3, 1, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 3, 1, 1, 3> const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 3, 1, 1, 3> const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
// generated by autoexplicit.sh
template void igl::copyleft::cgal::minkowski_sum<
  Eigen::Matrix<float, -1, 3, 1, -1, 3>, 
  Eigen::Matrix<int, -1, 3, 1, -1, 3>, 
  double, 3, 1, 
  float, 3, 1, 
  Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -1, -1>, 
  Eigen::Matrix<int, -1, -1, 0, -1, -1>, 
  Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, Eigen::Matrix<float, 1, 3, 1, 1, 3> const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
#endif

I read somewhere that the error can be caused because of directly using #include on .cpp files which is done in the last two header files so I tried copying the content of the .cpp files and placing it instead of the #include and I still get the same error.

Does anybody know what to do here?

Karan Rao
  • 33
  • 5
  • Including a cpp file and cutting and pasting it are exactly the same thing. But of course you should never include a cpp file. It seems that you have responsibility for yet more code which is trying to pretend that it's OK to put template code in cpp files and then to play tricks with includes to fix the problems that result. It really is very simple, put template code in header files only, and all your problems will disappear. See here for more details https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – john Apr 07 '20 at 12:13
  • So I have to take the templates from the cpp file and paste them into a header file? I'm really confused here – Karan Rao Apr 07 '20 at 12:18
  • Yes that's right. All template code should go in header files. The only exception is if you are using explicit template instantiation. But no-one uses that because it defeats the point of templates. – john Apr 07 '20 at 12:26
  • Why are you insisting on difficult solutions? What's wrong with putting template code in header files? – john Apr 07 '20 at 12:27
  • I have added minkowski_sum.cpp to the post. Can you tell me which part of the code goes where? Thank you so much for your help! – Karan Rao Apr 07 '20 at 12:38
  • Well I can see from the comments at the bottom that you are trying to use explicit template instantiation (that thing I said that no-one uses). That changes things. So are you trying to compile with `IGL_STATIC_LIBRARY` defined or not? Or are you trying to make it work both ways? – john Apr 07 '20 at 12:43
  • If you are not defining `IGL_STATIC_LIBRARY` then all this code should be put into a header file (as I've said many times already). – john Apr 07 '20 at 12:44
  • Sorry sir, I do not have much experience in C++. This is actually a Python module I'm trying to build from source so I can't really understand what's going on here. Where would I define the IGL_STATIC_LIBRARY? I tried copying the templates into another header file and including it but it throws a bunch of errors – Karan Rao Apr 07 '20 at 13:21
  • You would define it when you compile the code. Why you would want to do that I have no idea, but clearly the code has been written in such a way that it's an option. Presumably this is covered in the instructions you have for building this code. – john Apr 07 '20 at 14:10
  • Since this is third party code, I would not alter it. I'm not sure what problem made you feel that editing the code was a good idea, but I doubt that it was. So I would go back to the code as you downloaded it and try and build it using the official instructions. Any problems you have should be solvable without altering the code itself. – john Apr 07 '20 at 14:11
  • BTW you shouldn't copy the templates into another header file, you should copy them into the same header file. So the code in minkowski_sum.cpp should be copied to the bottom of minkowski_sum.h. If you want to go down that route. But as I said above I don't think it's a good idea to alter third party code, and to alter C++ code when you have little understanding of C++ is never going to work. – john Apr 07 '20 at 14:15
  • Yeah, that's the issue. I followed the exact instructions given here https://github.com/PyMesh/PyMesh but the linker always fails at this step so I'm not really sure what to do. That's why I asked if it was possible to ignore these symbols by using some ld flag – Karan Rao Apr 07 '20 at 14:18
  • Also, if I were to copy the code from the cpp file to the header, would I have to remove the ifndef part from the .h file? – Karan Rao Apr 07 '20 at 14:24
  • I'm not sure what the issue is. Having looked around it's clearly something more subtle than the usual template issues (which is what I assumed initially). I'm beginning to supect some kind of compiler version issue, but I could easily be wrong. Anyway you need specialist help, I would contact the owners of the code, or a forum dedicated to this particular library. Sorry I can't be of more help. – john Apr 07 '20 at 14:52
  • Yeah, I have a lurking suspicion it's because of the ld linker on macos. GNU ld has a way to ignore duplicate symbols but I can't find the same for this. And no problems at all! I appreciate the help – Karan Rao Apr 07 '20 at 14:56

0 Answers0