pcl icon indicating copy to clipboard operation
pcl copied to clipboard

[cmake] Is it possible to use FetchContent to bring in PCL?

Open xkaraman opened this issue 3 years ago • 10 comments

Describe the bug

I am trying to bring PCL dependency with CMakes FetchContent Functionality.

Context

FetchContent will download PCL repo at config time and MakeAvailable populates the source folder of pcl. Then PCL will be built along the original project.

--- CMakeLists.txt ---
cmake_minimum_required(VERSION 3.0.2)
project(fetch_content_example)

include(FetchContent)

FetchContent_Declare(
  PCL
  GIT_REPOSITORY https://github.com/PointCloudLibrary/pcl.git
  GIT_TAG        pcl-1.12.0# release-1.12.0
)
FetchContent_MakeAvailable(PCL)

add_library(${PROJECT_NAME}_parser
  src/parser.cpp
)
target_link_libraries(${PROJECT_NAME}_parser pcl_common)
--- src/parser.hpp ---
#ifndef PARSER_H
#define PARSER_H
# pragma once
 
#include <pcl/point_types.h>
  # code
  
--- src/parser.cpp ---
   # Implementation

After invoking cmake and then start to build the project, PCL builds succesfully but when building src/parser.cpp an error occurs of fatal error: pcl/point_types.h: No such file or directory #include <pcl/point_types.h> .

I tried multiple include structures such as #include <pcl/pcl/point_types.h> #include <pcl-1.12.0/pcl/point_types.h>

with the same error.

Expected behavior I don't know if it should be supported (other than building from source and installing it) but I would expect to be able to find the header files.

Current Behavior

No build produced To Reproduce Files containing the code above. mkdir && cd build cmake .. make -j8

Your Environment (please complete the following information):

  • OS: [e.g. Ubuntu 18.04]
  • Compiler: [:eg GCC 7.5]
  • PCL Version [e.g. tag pcl-1.12.0]

xkaraman avatar Dec 14 '21 16:12 xkaraman

I have never used FetchContent before, so the problem might only occur if that is used, but you could check out this tutorial on how to use PCL via CMake. Especially the command include_directories(${PCL_INCLUDE_DIRS}) might be missing. I know in modern CMake it is possible to simply specify a target as a dependency via target_link_libraries and also automatically be aware of all header directories, but I can't guarantee that PCL supports that already.

mvieth avatar Dec 16 '21 09:12 mvieth

Yes i am aware of that possibility to use PCL with CMAKE. I just wanted to try it and since FetchContent is a 'fairly' new feature of CMake, report it. According to docs of FetchContent_Declare() and FetchContent_MakeAvailable() there is no need for include_directories (if not mistaken), as it automagically calls add_subdirectory() under the hood.

I don't know though if that' something you would want to look at, but i guess it can be a good source to bring PCL from in projects when there is no PCL library available.

xkaraman avatar Dec 16 '21 10:12 xkaraman

Is there a guide on how to make a CMake project work with FetchContent?

@SunBlack As my goto expert of CMake, perhaps you can shine a light on OP's issues

kunaltyagi avatar Dec 16 '21 11:12 kunaltyagi

Have to try it myself. Maybe I have next time week for this experiment (the next two working days looks bad).

SunBlack avatar Dec 16 '21 11:12 SunBlack

Another error, i have encountered, is that if i bring multiple projects with FetchContent that define the same target like uninstall or docs, CMake will fail with

CMake Error at /home/***/ros_ws/git_ws/build/fetch_content_example/_deps/kindr-src/CMakeLists.txt:138 (add_custom_target):
  add_custom_target cannot create target "uninstall" because another target
  with the same name already exists.  The existing target is a custom target
  created in source directory
  "/home/***/ros_ws/git_ws/build/fetch_content_example/_deps/pcl-src".
  See documentation for policy CMP0002 for more details.

Example CMakeLists.txt (rest same with original on 1st comment) with FetchContent of PCL and kindr library

FetchContent_Declare(
  PCL
  GIT_REPOSITORY https://github.com/PointCloudLibrary/pcl.git
  GIT_TAG        pcl-1.12.0# release-1.12.0
)

FetchContent_Declare(
  kindr
  GIT_REPOSITORY https://github.com/ANYbotics/kindr
  GIT_TAG 1.2.0
)

FetchContent_MakeAvailable(PCL kindr)

xkaraman avatar Dec 17 '21 12:12 xkaraman

Checked it now.

I printed the content of pcl_common just before your call to target_link_libraries via this script. There INCLUDE_DIRECTORIES contains the correct include directory (<buildDir>/_deps/pcl-src/common/include) (and as IMPORTED is false INCLUDE_DIRECTORIES should be imho correct). Nevertheless MSVC doesn't show any any include directories. I debugged it a little bit within CMake now, but it seems this is resolved just in the generation step. But as the PCL is even within resolved within this steps, it doesn't make fun to debug it. So I suggest to ask for help within the CMake issue tracker.

In general I wouldn't recommend to use FetchContent im combination with the PCL. As you can see, you pollute your workspace with targets like the INSTALL target, which may conflict with other projects.

If you want to simplify the setup of your project, use vcpkg (Windows) or pkg (Unix).

SunBlack avatar Dec 20 '21 14:12 SunBlack

Thanks for checking it out.

I figured it would be pain to debug this out, and probably there is no need to support this feature of CMake.

Yeah the best course of action i guess it is vckpg or others, but that's just that. You must require the users to have it to ease the process, where CMake is your config/build tool anyways.

xkaraman avatar Dec 20 '21 15:12 xkaraman

In general find_package(PCL REQUIRED) should be enough as it automatically find the PCL components in case they are installed via libpcl-dev (Unix). On Windows just pass the directory to the PCL install dir and everything is fine (or use vcpkg). On this way the other devs doesn't have to compile PCL multiple times in case they have multiple copies on your project on the disk.

Even there are a few projects which doesn't recommend this way (e.g. GoogleTest), I prefer this way as I mostly have multiple copies of a single project on the disc.

SunBlack avatar Dec 20 '21 15:12 SunBlack

Yes i completely understand the problems involved ( i think). I was just curious and if it can be an option to fetch pcl like this why not offer it.

I get what your saying about multiple copies ( i guess diff versions) but fetchcontent can be used if find_package() fails meaning PCL is not already installed. Moreover libpcl-dev is mostly outdated on older OS Linux machines so FetchContent can bring any version you want by specifying the commit hash or tag.

GoogleTest cmake quickstart uses FetchContent unless i read an outdated one.

xkaraman avatar Dec 20 '21 15:12 xkaraman

@xkaraman I have used Fetch Content and I think you should link the Fetch content "target" into your main project

--- CMakeLists.txt ---

cmake_minimum_required(VERSION 3.0.2)
project(fetch_content_example)

include(FetchContent)
.
.
.

target_link_libraries(${PROJECT_NAME}_parser PCL)

This will enable all include/library content

td43 avatar Sep 12 '22 11:09 td43