背景
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パッケージがコンパイルできなくなる問題を回避した
参考文献
- [Bug] ndt_gpu not built using catkin_make_release/colcon_release on ros kinetic gpu desktop
- compiler errors - friend function in CUDA C++
変更履歴
- 2019/08/24: 新規作成
0 件のコメント:
コメントを投稿