ouster-lidar / ouster_example

Ouster, Inc. sample code
Other
448 stars 432 forks source link

Clang support and explicit template instantiations #580

Open vebjornjr opened 4 months ago

vebjornjr commented 4 months ago

Hello!

We have problems using your C++ Ouster SDK with Clang (clang-17 at the moment, but the same problem existed for earlier versions too).

The OusterSDK is compiled up with GCC 9.4.0 and linked to our application.

The problem is a linker error due to explicit template instantiations. GCC-13 doesn't have any linker error.

mold: error: undefined symbol: Eigen::Ref<Eigen::Array<unsigned short, -1, -1, 1, -1, -1>, 0, Eigen::internal::conditional<img_t<unsigned short>::IsVectorAtCompileTime, Eigen::InnerStride<1>, Eigen::OuterStride<-1> >::type> ouster::LidarScan::field<unsigned short, (unsigned short)0>(ouster::sensor::ChanField)
>>> referenced by LidarOuster.cpp LidarOuster.cpp
>>>               Common/CommonLib/CMakeFiles/SteerCommonLib.dir/steer/common/autopilot/perception/LidarOuster.cpp.o:(steer::LidarOuster::receiveLoopv)
mold: error: undefined symbol: Eigen::Ref<Eigen::Array<unsigned int, -1, -1, 1, -1, -1>, 0, Eigen::internal::conditional<img_t<unsigned int>::IsVectorAtCompileTime, Eigen::InnerStride<1>, Eigen::OuterStride<-1> >::type> ouster::LidarScan::field<unsigned int, 0u>(ouster::sensor::ChanField)
>>> referenced by LidarOuster.cpp LidarOuster.cpp
>>>               Common/CommonLib/CMakeFiles/SteerCommonLib.dir/steer/common/autopilot/perception/LidarOuster.cpp.o:(steer::LidarOuster::receiveLoopv)
clang++-17: error: linker command failed with exit code 1 (use -v to see invocation)

I think this issue is related https://github.com/llvm/llvm-project/issues/62134.

A hacky fix for us is to provide the full template function in our LidarOuster.cpp file:

#if defined(__clang__)
namespace ouster {

template<typename T, typename std::enable_if<std::is_unsigned<T>::value, T>::type>
Eigen::Ref<img_t<T>> LidarScan::field(sensor::ChanField f) {
    return fields_.at(f).get<T>();
}

template<typename T, typename std::enable_if<std::is_unsigned<T>::value, T>::type>
Eigen::Ref<const img_t<T>> LidarScan::field(sensor::ChanField f) const {
    return fields_.at(f).get<T>();
}

}  // namespace ouster
#endif

The problem happens with ld linker, lld linker and mold linker.

Will you take this into account in future releases? Perhaps by moving the template function LidarScan::field() to lidar_scan_impl.h (in the same way as destagger())?

Platform (please complete the following information):