PointCloudLibrary / pcl

Point Cloud Library (PCL)
https://pointclouds.org/
Other
9.88k stars 4.61k forks source link

[compile error] "can't found PCL because of wrong PCL_ROOT" #4661

Open perisage opened 3 years ago

perisage commented 3 years ago

I installed PCL by sudo apt install libpcl-dev. and used it like this:

cmake_minimum_required(VERSION 3.5)
project(test)

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic -Wno-unused-parameter)
endif()

# find dependencies
find_package(PCL REQUIRED)

some errors occurred when I built the project:

CMake Error at /lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake:62 (message):
  PCL can not be found on this machine
Call Stack (most recent call first):
  /lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake:452 (pcl_report_not_found)
  CMakeLists.txt:37 (find_package)

-- Configuring incomplete, errors occurred!

I'm trying to debug the cmake source code in /lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake:418-454, The cmake source is shown below:

find_package(PkgConfig QUIET)

file(TO_CMAKE_PATH "${PCL_DIR}" PCL_DIR)
if(WIN32 AND NOT MINGW)
# PCLConfig.cmake is installed to PCL_ROOT/cmake
  get_filename_component(PCL_ROOT "${PCL_DIR}" PATH)
else()
# PCLConfig.cmake is installed to PCL_ROOT/share/pcl-x.y
  get_filename_component(PCL_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../../.." ABSOLUTE)
endif()

# check whether PCLConfig.cmake is found into a PCL installation or in a build tree
if(EXISTS "${PCL_ROOT}/include/pcl-${PCL_VERSION_MAJOR}.${PCL_VERSION_MINOR}/pcl/pcl_config.h")
  # Found a PCL installation
  # pcl_message("Found a PCL installation")
  set(PCL_CONF_INCLUDE_DIR "${PCL_ROOT}/include/pcl-${PCL_VERSION_MAJOR}.${PCL_VERSION_MINOR}")
  set(PCL_LIBRARY_DIRS "${PCL_ROOT}/lib/x86_64-linux-gnu")
  if(EXISTS "${PCL_ROOT}/3rdParty")
    set(PCL_ALL_IN_ONE_INSTALLER ON)
  endif()
elseif(EXISTS "${PCL_ROOT}/include/pcl/pcl_config.h")
  # Found a non-standard (likely ANDROID) PCL installation
  # pcl_message("Found a PCL installation")
  set(PCL_CONF_INCLUDE_DIR "${PCL_ROOT}/include")
  set(PCL_LIBRARY_DIRS "${PCL_ROOT}/lib")
  if(EXISTS "${PCL_ROOT}/3rdParty")
    set(PCL_ALL_IN_ONE_INSTALLER ON)
  endif()
elseif(EXISTS "${PCL_DIR}/include/pcl/pcl_config.h")
  # Found PCLConfig.cmake in a build tree of PCL
  # pcl_message("PCL found into a build tree.")
  set(PCL_CONF_INCLUDE_DIR "${PCL_DIR}/include") # for pcl_config.h
  set(PCL_LIBRARY_DIRS "${PCL_DIR}/lib/x86_64-linux-gnu")
  set(PCL_SOURCES_TREE "/build/pcl-gWGA5r/pcl-1.10.0+dfsg")
else()
  pcl_report_not_found("PCL can not be found on this machine")
endif()

Through debugging, I found that the environment variable PCL_ROOT is set to / and PCL_DIR is set to /lib/x86_64-linux-gnu/cmake/pcl. So, It can't find correct PCL include directory(the correct PCL include dir is /usr/include/pcl-1.10) and lead to cmake error.

My Environment :

mvieth commented 3 years ago

Hm, yes, I think PCL_ROOT should be /usr. Not sure why cmake uses the wrong path there. You could try to set PCL_DIR manually as described in this tutorial

perisage commented 3 years ago

Well, Things are more complicated than imagined.

1. First Try

I set PCL_DIR to /usr/lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake as is shown below:

set(PCL_DIR "/usr/lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake")
find_package(PCL  REQUIRED)

But the value of PCL_DIR came back to /lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake when find_package(PCL REQUIRED) is invoked. Therefore, this method is not feasible. Obviously, the value of PCL_DIR will be reset somewhere in PCLConfig.cmake. So Where is the value of PCL_DIR reset?

2. Second Try

I noticed that the PCL_ROOT is decided by CMAKE_CURRENT_LIST_DIR on Linux in PCLConfig.cmake:386-392. The source code about this conclusion is shown below: https://github.com/PointCloudLibrary/pcl/blob/ea4d0b62d184349dbf4c245d9e79c71d070ff9fe/PCLConfig.cmake.in#L386-L392

I found the CMAKE_CURRENT_LIST_DIR 's value is /lib/x86_64-linux-gnu/cmake/pcl on my platform. so after get_filename_component(PCL_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../../.." ABSOLUTE), PCL_ROOT became /. The problem is that the value of CMAKE_CURRENT_LIST_DIR is /usr/lib/x86_64-linux-gnu/cmake/pcl on most platform. Under this condition, PCL_ROOTwill become the correct value /usr. As we know that /lib is a symbol link of /usr/lib. Based on this, I referenced OpenCVConfig.cmake in the OpenCV and modified the source code of PCLConfig.cmake. The code are as follows:

file(TO_CMAKE_PATH "${PCL_DIR}" PCL_DIR)
get_filename_component(PCL_DIR "${PCL_DIR}" REALPATH)

if(WIN32 AND NOT MINGW)
# PCLConfig.cmake is installed to PCL_ROOT/cmake
  get_filename_component(PCL_ROOT "${PCL_DIR}" PATH)
else()
# PCLConfig.cmake is installed to PCL_ROOT/share/pcl-x.y
#  get_filename_component(PCL_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../../.." ABSOLUTE)
  get_filename_component(PCL_CONFIG_PATH "${CMAKE_CURRENT_LIST_DIR}" REALPATH)
  get_filename_component(PCL_ROOT "${PCL_CONFIG_PATH}/../../../../" ABSOLUTE)
endif()

Then, I can find PCL by find_package(PCL REQUIRED) correctly and everything goes well. So Is this special situation(CMAKE_CURRENT_LIST_DIR was set as /lib/..., not /usr/lib/...) beyond PCLConfig.cmake's consideration.

Hm, yes, I think PCL_ROOT should be /usr. Not sure why cmake uses the wrong path there. You could try to set PCL_DIR manually as described in this tutorial

kunaltyagi commented 3 years ago

I think this approach will also work on non-special systems. A PR would be appretiated @perisage

Thanks for debugging it and the nice postmortem

mvieth commented 3 years ago

BTW I found this bug report: https://bugs.launchpad.net/ubuntu/+source/pcl/+bug/1896118 @perisage Out of interest, do you also use a Singularity container? Or is there anything special/uncommon about your operating system that may cause this? I am asking because Ubuntu is probably the most popular OS among PCL users, and I can't image that nobody would have noticed such a bug on a "common" Ubuntu installation.

perisage commented 3 years ago

BTW I found this bug report: https://bugs.launchpad.net/ubuntu/+source/pcl/+bug/1896118 @perisage Out of interest, do you also use a Singularity container? Or is there anything special/uncommon about your operating system that may cause this? I am asking because Ubuntu is probably the most popular OS among PCL users, and I can't image that nobody would have noticed such a bug on a "common" Ubuntu installation.

My OS is Ubuntu20.04.2 LTS which is downloaded and installed from the Ubuntu official website and there is nothing special/uncommon about it. I have tested PCL on two desktop computers with Ubuntu20.04.2 LTS and reproduced this issue on both of them.

MichealRW commented 1 year ago

you can use this commed to find where the real path of the PCLConfig.cmake: sudo find / -iname "*PCLConfig*" and then set the PCL_DIR in the CMakeLists.txt

stepeos commented 1 year ago
  get_filename_component(PCL_CONFIG_PATH "${CMAKE_CURRENT_LIST_DIR}" REALPATH)
  get_filename_component(PCL_ROOT "${PCL_CONFIG_PATH}/../../../../" ABSOLUTE)

Hi @perisage, I'm glad i found your comment as it fixed my issue!

I'm running on Ubuntu 20.04 and also came across the same issue. Here's what's weird.

When logging into ssh using VS Code remote, i was able to build the project just fine. However, when I logged into the machine via RDP and built the project using a snap installation of VS Code, cmake would fail with the same error message as described above. I just wanted to mention this, as it is apparently still an issue. I wonder, whether it is caused by different environment variables?

MichealRW commented 1 year ago
  get_filename_component(PCL_CONFIG_PATH "${CMAKE_CURRENT_LIST_DIR}" REALPATH)
  get_filename_component(PCL_ROOT "${PCL_CONFIG_PATH}/../../../../" ABSOLUTE)

Hi @perisage, I'm glad i found your comment as it fixed my issue!↳

I'm running on Ubuntu 20.04 and also came across the same issue. Here's what's weird.↳

When logging into ssh using VS Code remote, i was able to build the project just fine. However, when I logged into the machine via RDP and built the project using a snap installation of VS Code, cmake would fail with the same error message as described above. I just wanted to mention this, as it is apparently still an issue. I wonder, whether it is caused by different environment variables?↳

I think this is probably caused by Cmake's search mechanism ----"find_package" It will search for specific lib locations first, but where might there be no exact path. I have this problem mostly probably because I use the Cmake priority lookup path in the ROS library, but where is there only a fake address and my real pcl installation path under a characteristic folder.

hope this helps.

syo093c commented 11 months ago

I have the same problem when ROS environment is activated.

syo093c commented 11 months ago

Finally I found the problem, I have /bin before /usr/bin is my PATH. This cause problem! Please check it!