2019/08/24

CUDA10のコンパイラでrosのパッケージがコンパイルできない問題の対処法

背景


CUDA10のnvccを用いてrosのパッケージをコンパイルする際、エラーが発生してコンパイルできない問題が生じた。

記事の目的


CUDA10のnvccでrosパッケージをコンパイルできるようにする

nvccのバグ


ここでは、CUDA10のnvccでrosパッケージをコンパイルできない現象、原因及び対策について記載する。

現象

CUDA10のnvccでrosパッケージをコンパイルすると、下記のエラーが発生する場合がある。
$ catkin_make
...
/usr/include/pcl-1.7/pcl/point_cloud.h:586:100 error: template-id ‘getMapping’ used as a declarator
friend boost::shared_ptr& detail::getMapping(pcl::PointCloud &p);
^
/usr/include/pcl-1.7/pcl/point_cloud.h:586:100 error: ‘getMapping’ is neither function nor member function; cannot be declared friend
cc1plus: error: expected ‘;’ at end of member declaration
/usr/include/pcl-1.7/pcl/point_cloud.h:586:111: error: expected ‘)’ before ‘&’ token
...
make: *** [all] Error 2

原因

nvccが利用しているgnuコンパイラのバグが原因である。このバグは、「friend関数によりnamespace内で定義された関数を使用する」記述があるコードで発生する。ところで、rosは独自に手を加えたPointCloudLibrary(PCL)を使用しているが、PCLのコード内に上記の記述が存在する('/usr/include/pcl-1.7/pcl/point_cloud.h'内 l.586)。nvccのコンパイラは、上記箇所をコンパイルする際に、関数のnamespace部分を削除してしまう(detail::getMapping→getMapping)。そのため、コンパイラ自身が関数を見つけられなくなり、エラーとなる。
$less /usr/include/pcl-1.7/pcl/point_cloud.h 
'point_cloud.h'内の該当箇所
 
namespace detail
  {
    template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
    getMapping (pcl::PointCloud<PointT>& p);
  } // namespace detail
 
    protected:
      // This is motivated by ROS integration. Users should not need to access mapping_.
      boost::shared_ptr<MsgFieldMap> mapping_;

      friend boost::shared_ptr<MsgFieldMap>& detail::getMapping<PointT>(pcl::PointCloud<PointT> &p);

    public:
      EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  };

  namespace detail
  {
    template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
    getMapping (pcl::PointCloud<PointT>& p)
    {
      return (p.mapping_);
    }
  } // namespace detail

対策

'/usr/include/pcl-1.7/pcl/point_cloud.h'を下記のように書き換えることで回避できる。
// Add ---------------------------------------------------------------------- //
template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
    getMapping (pcl::PointCloud<PointT>& p);
// -------------------------------------------------------------------------- //
namespace detail
  {
    template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
    getMapping (pcl::PointCloud<PointT>& p);
  } // namespace detail
 
    protected:
      // This is motivated by ROS integration. Users should not need to access mapping_.
      boost::shared_ptr<MsgFieldMap> mapping_;
      // Change ------------------------------------------------------------------- //
      friend boost::shared_ptr<MsgFieldMap>& getMapping<PointT>(pcl::PointCloud<PointT> &p);
      // friend boost::shared_ptr<MsgFieldMap>& detail::getMapping<PointT>(pcl::PointCloud<PointT> &p);
      // -------------------------------------------------------------------------- //
    public:
      EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  };

// Add ---------------------------------------------------------------------- //
template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
    getMapping (pcl::PointCloud<PointT>& p)
{
    return (p.mapping_);
}
// -------------------------------------------------------------------------- //
namespace detail
  {
    template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
    getMapping (pcl::PointCloud<PointT>& p)
    {
      return (p.mapping_);
    }
  } // namespace detail

備考

  • ros-kinetic、cuda 10.1で検証した
  • コンパイルが通ることと、実行可能であることを確認した

まとめ


  • rosをapt install時にインストールされるpclのヘッダーファイルを変更することにより、CUDA10のnvccでrosパッケージがコンパイルできなくなる問題を回避した

参考文献



変更履歴


  1. 2019/08/24: 新規作成

0 件のコメント:

コメントを投稿

MQTTの導入

背景 IoTデバイスの接続環境構築のため、MQTT(mosquitto)の導入を行った。 記事の目的 MQTT(mosquitto)をUbuntuに導入する mosquitto ここではmosquittoについて記載する。 MQTT MQTT(Message Qu...