Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find FLANN using both module- and config-based methods #3202

Merged
merged 2 commits into from
Jul 4, 2019

Conversation

taketwo
Copy link
Member

@taketwo taketwo commented Jul 1, 2019

Work-in-progress implementation of my proposal from #3194.

@taketwo
Copy link
Member Author

taketwo commented Jul 2, 2019

Seems to work. I cleaned up the finder script a bit to remove unnecessary variables.

Note that this PR makes a transition of back, requiring to link against ${FLANN_LIBRARIES} instead of directly FLANN::FLANN target. The reason is that we support FLANN_USE_STATIC configuration option to abstract away the static vs dynamic choice from the rest of the library. Ideally we'd make FLANN::FLANN an alias for the appropriate target, however CMake (at least 3.5) does not support aliasing imported targets. Thus we need to resort to using a variable to point to the correct imported target.

Ping @SunBlack in case you want to have a look.

@taketwo taketwo changed the title [WIP] Try to find FLANN using Config file Find FLANN using both module- and config-based methods Jul 2, 2019
@SunBlack
Copy link
Contributor

SunBlack commented Jul 2, 2019

Ping @SunBlack in case you want to have a look.

I will take a look at this later this day :)

PCLConfig.cmake.in Outdated Show resolved Hide resolved
@SunBlack
Copy link
Contributor

SunBlack commented Jul 2, 2019

Had until now not the time to check what the config script of FLANN is exporting, but:

Ideally we'd make FLANN::FLANN an alias for the appropriate target, however CMake (at least 3.5) does not support aliasing imported targets.

Workaround:

set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES FLANN::FLANN_CPP)

This adds FLANN::FLANN_CPP as dependency to FLANN::FLANN, so if you write:
target_link_library(... FLANN::FLANN), FLANN::FLANN will be added too. Maybe FLANN::FLANN has then to be a interface target.

@taketwo
Copy link
Member Author

taketwo commented Jul 3, 2019

Hm, this may work. @SergioRAgostinho should we go this way? One downside is that there will be multiple targets (flann::flann, flann::flann_cpp, flann::flann_s, flann::flann_cpp_s, FLANN::FLANN) and someone may confuse which one to use. On the other hand we are the only users, and we do know that FLANN::FLANN is the one to be used, so maybe not a problem.

@SergioRAgostinho
Copy link
Member

One downside is that there will be multiple targets (flann::flann, flann::flann_cpp, flann::flann_s, flann::flann_cpp_s, FLANN::FLANN) and someone may confuse which one to use. On the other hand we are the only users, and we do know that FLANN::FLANN is the one to be used, so maybe not a problem.

I agree that we are required to have a target to abstract which flann::* is called under the hood. I also prefer to see something like FLANN::FLANN, instead of ${FLANN_LIBRARIES}, although this is just looks.

  • When compiling PCL, there's no user involvement in this process. The use of FLANN::FLANN is already done in the first place.
  • When using PCL in a downstream project. From what I can tell, the appropriate targets flann::flann, flann::flann_cpp, flann::flann_s, flann::flann_cpp_s will be created whenever possible in both config and module routes. So all the same "official targets" will exist for the end user. We add a new one which does not clash with the official one.
  • In case a downstream user needs to explicitly link against flann and runs find_package( flann NO_MODULE ...) before us, cmake will find the same modules as pcl and the targets will be the same. Also no problem.
  • There's no official CMake shipped find_package(flann) (Module), so if such a thing exists, the user is in full control of what targets are created.

Everything seems functional to me.

@taketwo
Copy link
Member Author

taketwo commented Jul 3, 2019

OK, will update this PR. One correction though:

From what I can tell, the appropriate targets flann::flann, flann::flann_cpp, flann::flann_s, flann::flann_cpp_s will be created whenever possible in both config and module routes.

In the module route we are in charge of creating them. And since only a single one is needed, I would only create a single one. And also I will call it FLANN::FLANN right away. To summarize which targets are created when:

  • In config mode
    • flann::flann: imported
    • flann::flann_cpp: imported
    • flann::flann_s: imported
    • flann::flann_cpp_s: imported
    • FLANN::FLANN: interface, depends on the appropriate _cpp* target
  • In module mode
    • FLANN::FLANN: imported, static/dynamic as needed

@SergioRAgostinho SergioRAgostinho merged commit b6e1163 into PointCloudLibrary:master Jul 4, 2019
@taketwo taketwo deleted the flann-config branch July 4, 2019 08:21
@jasjuang
Copy link
Contributor

jasjuang commented Jul 6, 2019

Is the PR supposed to also solve vcpkg install pcl[*] --head? I am getting the errors below when I did so

CMake Error at C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake:198 (_add_library):
  Target "pcl_kdtree" links to target "FLANN::FLANN" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?
Call Stack (most recent call first):
  cmake/pcl_targets.cmake:222 (add_library)
  kdtree/CMakeLists.txt:33 (PCL_ADD_LIBRARY)


CMake Error at C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake:198 (_add_library):
  Target "pcl_search" links to target "FLANN::FLANN" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?
Call Stack (most recent call first):
  cmake/pcl_targets.cmake:222 (add_library)
  search/CMakeLists.txt:43 (PCL_ADD_LIBRARY)


CMake Error at C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake:198 (_add_library):
  Target "pcl_search" links to target "FLANN::FLANN" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?
Call Stack (most recent call first):
  cmake/pcl_targets.cmake:222 (add_library)
  search/CMakeLists.txt:43 (PCL_ADD_LIBRARY)


CMake Error at C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake:198 (_add_library):
  Target "pcl_filters" links to target "FLANN::FLANN" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?
Call Stack (most recent call first):
  cmake/pcl_targets.cmake:222 (add_library)
  filters/CMakeLists.txt:128 (PCL_ADD_LIBRARY)

@taketwo
Copy link
Member Author

taketwo commented Jul 6, 2019

We do support all versions of FLANN now. Whether this is sufficient to build --head PCL I can not comment as I am not a Windows/vcpkg user.

@SergioRAgostinho
Copy link
Member

Is the PR supposed to also solve vcpkg install pcl[*] --head?

It depends: there's a couple of patches vcpkg applies to PCL before building that might not be valid. It is likely that the port file needs to be updated for the --head version to work.

@jasjuang
Copy link
Contributor

jasjuang commented Jul 7, 2019

I figured out how to make vcpkg install pcl[*] --head work. For those who are interested, I had to take out all the flann patches, disable ninja, and adjust vcpkg_fixup_cmake_targets() to vcpkg_fixup_cmake_targets(CONFIG_PATH "cmake").

@jasjuang
Copy link
Contributor

jasjuang commented Jul 7, 2019

It installed but the config file needs to be patched somehow to in order for the downstream to use it. Still unclear on how to patch it at the moment...

@jasjuang
Copy link
Contributor

@taketwo After the merge of this PR, is pcl supposed to work with the latest master of FLANN? If that's the case, for some reason when I link to pcl in my downstream project, I got the below error during CMake configuration

CMake Error at /usr/share/pcl-1.9/Modules/FindFLANN.cmake:43 (add_library):
  add_library cannot create imported target "FLANN::FLANN" because another
  target with the same name already exists.
Call Stack (most recent call first):
  /usr/share/pcl-1.9/PCLConfig.cmake:259 (find_package)
  /usr/share/pcl-1.9/PCLConfig.cmake:314 (find_flann)
  /usr/share/pcl-1.9/PCLConfig.cmake:552 (find_external_library)

@taketwo
Copy link
Member Author

taketwo commented Aug 13, 2019

I think I tested this, but can not say with 100% certainty. I will try to reproduce tomorrow on Ubuntu 18.04 + PCL master + FLANN master.

@jasjuang
Copy link
Contributor

jasjuang commented Aug 13, 2019

@taketwo after some trial and error, I figured out what version of flann works with the current pcl master. Only the 1.9.1 release works. I tried with the latest flann master, the commit prior to @jspricke's commit that used to break pcl compilation as indicated in #3194 and neither of them works with the current pcl master now.

@taketwo
Copy link
Member Author

taketwo commented Aug 15, 2019

I can not reproduce this on my system (Ubuntu 18.04). What I did:

  • Build FLANN from current master and install to a certain directory.
  • Configure PCL from current master, pointing it to use FLANN from where it was installed in the previous step.
  • Build and install PCL.
  • Configure and build a downstream project (I used "pcd_read" tutorial) pointing it to use PCL from where it was installed in the previous step.

This sequence succeeds for me. Are your steps similar, do did I do something substantially different from your use-case? Also, please post the following files:

  • /usr/share/pcl-1.9/Modules/FindFLANN.cmake
  • /usr/share/pcl-1.9/PCLConfig.cmake

@jasjuang
Copy link
Contributor

The only additional step I took is applying the patch as indicated in flann-lib/flann#369 in order to get flann to compile, but I don't think that affects anything. As for the pcd_read tutorial, I believe

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

are redundant, so in my downstream CMakeLists I don't have them, but again I believe this shouldn't affect things. The rest of the steps looks like it is the same to me. I have the files with pcl compiled with FLANN 1.9.1 readily available now as below:

PCLConfig.cmake

# ------------------------------------------------------------------------------------
# Helper to use PCL from outside project
#
# target_link_libraries(my_fabulous_target PCL_XXX_LIBRARIES) where XXX is the
# upper cased xxx from :
# 
# - common
# - kdtree
# - octree
# - search
# - sample_consensus
# - filters
# - 2d
# - geometry
# - io
# - features
# - ml
# - segmentation
# - visualization
# - surface
# - registration
# - keypoints
# - tracking
# - recognition
# - stereo
# - cuda_common
# - cuda_features
# - cuda_segmentation
# - cuda_sample_consensus
# - outofcore
# - gpu_containers
# - gpu_utils
# - gpu_octree
# - gpu_features
# - gpu_segmentation
# - people
#
# PCL_INCLUDE_DIRS is filled with PCL and available 3rdparty headers
# PCL_LIBRARY_DIRS is filled with PCL components libraries install directory and
# 3rdparty libraries paths
#
#                                   www.pointclouds.org
#------------------------------------------------------------------------------------

if(POLICY CMP0074)
  # TODO: update *_ROOT variables to be PCL_*_ROOT or equivalent.
  # CMP0074 directly affects how Find* modules work and *_ROOT variables.  Since
  # this is a config file that will be consumed by parent projects with (likely)
  # NEW behavior, we need to push a policy stack.
  cmake_policy(PUSH)
  cmake_policy(SET CMP0074 NEW)
endif()

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/Modules")

### ---[ some useful macros
macro(pcl_report_not_found _reason)
  unset(PCL_FOUND)
  unset(PCL_LIBRARIES)
  unset(PCL_COMPONENTS)
  unset(PCL_INCLUDE_DIRS)
  unset(PCL_LIBRARY_DIRS)
  unset(PCL_DEFINITIONS)
  if(PCL_FIND_REQUIRED)
    message(FATAL_ERROR ${_reason})
  elseif(NOT PCL_FIND_QUIETLY)
    message(WARNING ${_reason})
  endif()
  if(POLICY CMP0074)
    cmake_policy(POP)
  endif()
  return()
endmacro()

macro(pcl_message)
  if(NOT PCL_FIND_QUIETLY)
    message(${ARGN})
  endif()
endmacro()

# Remove duplicate libraries
macro(pcl_remove_duplicate_libraries _unfiltered_libraries _filtered_libraries)
  set(${_filtered_libraries})
  set(_debug_libraries)
  set(_optimized_libraries)
  set(_other_libraries)
  set(_waiting_for_debug 0)
  set(_waiting_for_optimized 0)
  set(_library_position -1)
  foreach(library ${${_unfiltered_libraries}})
    if("${library}" STREQUAL "debug")
      set(_waiting_for_debug 1)
    elseif("${library}" STREQUAL "optimized")
      set(_waiting_for_optimized 1)
    elseif(_waiting_for_debug)
      list(FIND _debug_libraries "${library}" library_position)
      if(library_position EQUAL -1)
        list(APPEND ${_filtered_libraries} debug ${library})
        list(APPEND _debug_libraries ${library})
      endif()
      set(_waiting_for_debug 0)
    elseif(_waiting_for_optimized)
      list(FIND _optimized_libraries "${library}" library_position)
      if(library_position EQUAL -1)
        list(APPEND ${_filtered_libraries} optimized ${library})
        list(APPEND _optimized_libraries ${library})
      endif()
      set(_waiting_for_optimized 0)
    else()
      list(FIND _other_libraries "${library}" library_position)
      if(library_position EQUAL -1)
        list(APPEND ${_filtered_libraries} ${library})
        list(APPEND _other_libraries ${library})
      endif()
    endif()
  endforeach()
endmacro()

### ---[ 3rd party libraries
macro(find_boost)
  if(PCL_ALL_IN_ONE_INSTALLER)
    set(BOOST_ROOT "${PCL_ROOT}/3rdParty/Boost")
  elseif(NOT BOOST_INCLUDEDIR)
    set(BOOST_INCLUDEDIR "/usr/include")
  endif()
  # use static Boost in Windows
  if(WIN32)
    set(Boost_USE_STATIC_LIBS )
    set(Boost_USE_STATIC )
    set(Boost_USE_MULTITHREAD )
  endif()
  set(Boost_ADDITIONAL_VERSIONS
    "1.68.0" "1.68"
    "1.70.0" "1.70"
    "1.69.0" "1.69" "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65"
    "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60"
    "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55")
  # Disable the config mode of find_package(Boost)
  set(Boost_NO_BOOST_CMAKE ON)
  find_package(Boost 1.55.0 ${QUIET_} COMPONENTS system filesystem date_time iostreams serialization)

  set(BOOST_FOUND ${Boost_FOUND})
  set(BOOST_INCLUDE_DIRS "${Boost_INCLUDE_DIR}")
  set(BOOST_LIBRARY_DIRS "${Boost_LIBRARY_DIRS}")
  set(BOOST_LIBRARIES ${Boost_LIBRARIES})
  if(WIN32 AND NOT MINGW)
    set(BOOST_DEFINITIONS ${BOOST_DEFINITIONS} -DBOOST_ALL_NO_LIB)
  endif()
endmacro()

#remove this as soon as eigen is shipped with FindEigen.cmake
macro(find_eigen)
  if(PCL_ALL_IN_ONE_INSTALLER)
    set(EIGEN_ROOT "${PCL_ROOT}/3rdParty/Eigen")
  elseif(NOT EIGEN_ROOT)
    get_filename_component(EIGEN_ROOT "/usr/include/eigen3" ABSOLUTE)
  endif()
  find_package(Eigen 3.1)
  set(EIGEN_DEFINITIONS ${EIGEN_DEFINITIONS})
endmacro()

#remove this as soon as qhull is shipped with FindQhull.cmake
macro(find_qhull)
  if(PCL_ALL_IN_ONE_INSTALLER)
    set(QHULL_ROOT "${PCL_ROOT}/3rdParty/Qhull")
  elseif(NOT QHULL_ROOT)
    get_filename_component(QHULL_ROOT "/usr/include" PATH)
  endif()

  set(QHULL_USE_STATIC )
  find_package(Qhull)
endmacro()

#remove this as soon as libopenni is shipped with FindOpenni.cmake
macro(find_openni)
  if(PCL_FIND_QUIETLY)
    set(OpenNI_FIND_QUIETLY TRUE)
  endif()

  if(NOT OPENNI_ROOT AND ("" STREQUAL "TRUE"))
    set(OPENNI_INCLUDE_DIRS_HINT "")
    get_filename_component(OPENNI_LIBRARY_HINT "OPENNI_LIBRARY-NOTFOUND" PATH)
  endif()

  find_package(OpenNI)
endmacro()

#remove this as soon as libopenni2 is shipped with FindOpenni2.cmake
macro(find_openni2)
  if(PCL_FIND_QUIETLY)
    set(OpenNI2_FIND_QUIETLY TRUE)
  endif()

  if(NOT OPENNI2_ROOT AND ("" STREQUAL "TRUE"))
    set(OPENNI2_INCLUDE_DIRS_HINT "")
    get_filename_component(OPENNI2_LIBRARY_HINT "OPENNI2_LIBRARY-NOTFOUND" PATH)
  endif()

  find_package(OpenNI2)
endmacro()

#remove this as soon as the Ensenso SDK is shipped with FindEnsenso.cmake
macro(find_ensenso)
  if(PCL_FIND_QUIETLY)
    set(ensenso_FIND_QUIETLY TRUE)
  endif()

  if(NOT ENSENSO_ROOT AND ("" STREQUAL "TRUE"))
    get_filename_component(ENSENSO_ABI_HINT "ENSENSO_INCLUDE_DIR-NOTFOUND" PATH)
  endif()

  find_package(Ensenso)
endmacro()

#remove this as soon as the davidSDK is shipped with FinddavidSDK.cmake
macro(find_davidSDK)
  if(PCL_FIND_QUIETLY)
    set(DAVIDSDK_FIND_QUIETLY TRUE)
  endif()

  if(NOT davidSDK_ROOT AND ("" STREQUAL "TRUE"))
    get_filename_component(DAVIDSDK_ABI_HINT DAVIDSDK_INCLUDE_DIR-NOTFOUND PATH)
  endif()

  find_package(davidSDK)
endmacro()

macro(find_dssdk)
  if(PCL_FIND_QUIETLY)
    set(DSSDK_FIND_QUIETLY TRUE)
  endif()
  if(NOT DSSDK_DIR AND ("" STREQUAL "TRUE"))
    get_filename_component(DSSDK_DIR_HINT "" PATH)
  endif()

  find_package(DSSDK)
endmacro()

macro(find_rssdk)
  if(PCL_FIND_QUIETLY)
    set(RSSDK_FIND_QUIETLY TRUE)
  endif()
  if(NOT RSSDK_DIR AND ("" STREQUAL "TRUE"))
    get_filename_component(RSSDK_DIR_HINT "" PATH)
  endif()

  find_package(RSSDK)
endmacro()

#remove this as soon as flann is shipped with FindFlann.cmake
macro(find_flann)
  if(PCL_ALL_IN_ONE_INSTALLER)
    set(FLANN_ROOT "${PCL_ROOT}/3rdParty/Flann")
  elseif(NOT FLANN_ROOT)
    set(FLANN_ROOT "/usr")
  endif()

  set(FLANN_USE_STATIC )
  find_package(FLANN)
endmacro()

macro(find_VTK)
  if(PCL_ALL_IN_ONE_INSTALLER AND NOT ANDROID)
    if(EXISTS "${PCL_ROOT}/3rdParty/VTK/lib/cmake")
      set(VTK_DIR "${PCL_ROOT}/3rdParty/VTK/lib/cmake/vtk-8.2" CACHE PATH "The directory containing VTKConfig.cmake")
    else()
      set(VTK_DIR "${PCL_ROOT}/3rdParty/VTK/lib/vtk-8.2" CACHE PATH "The directory containing VTKConfig.cmake")
    endif()
  elseif(NOT VTK_DIR AND NOT ANDROID)
    set(VTK_DIR "/usr/lib/x86_64-linux-gnu/cmake/vtk-8.2" CACHE PATH "The directory containing VTKConfig.cmake")
  endif()
  if(NOT ANDROID)
    find_package(VTK ${QUIET_} COMPONENTS ${PCL_VTK_COMPONENTS})
  endif()
endmacro()

macro(find_libusb)
  if(NOT WIN32)
    find_path(LIBUSB_1_INCLUDE_DIR
      NAMES libusb-1.0/libusb.h
      PATHS /usr/include /usr/local/include /opt/local/include /sw/include
      PATH_SUFFIXES libusb-1.0)

    find_library(LIBUSB_1_LIBRARY
      NAMES usb-1.0
      PATHS /usr/lib /usr/local/lib /opt/local/lib /sw/lib)
    find_package_handle_standard_args(libusb-1.0 LIBUSB_1_LIBRARY LIBUSB_1_INCLUDE_DIR)
  endif()
endmacro()

macro(find_glew)
  find_package(GLEW)
endmacro()

# Finds each component external libraries if any
# The functioning is as following
# try to find _lib
# |--> _lib found ==> include the headers,
# |                   link to its library directories or include _lib_USE_FILE
# `--> _lib not found
#                   |--> _lib is optional ==> disable it (thanks to the guardians)
#                   |                         and warn
#                   `--> _lib is required
#                                       |--> component is required explicitly ==> error
#                                       `--> component is induced ==> warn and remove it
#                                                                     from the list

macro(find_external_library _component _lib _is_optional)
  if("${_lib}" STREQUAL "boost")
    find_boost()
  elseif("${_lib}" STREQUAL "eigen")
    find_eigen()
  elseif("${_lib}" STREQUAL "flann")
    find_flann()
  elseif("${_lib}" STREQUAL "qhull")
    find_qhull()
  elseif("${_lib}" STREQUAL "openni")
    find_openni()
  elseif("${_lib}" STREQUAL "openni2")
    find_openni2()
  elseif("${_lib}" STREQUAL "ensenso")
    find_ensenso()
  elseif("${_lib}" STREQUAL "davidSDK")
    find_davidSDK()
  elseif("${_lib}" STREQUAL "dssdk")
    find_dssdk()
  elseif("${_lib}" STREQUAL "rssdk")
    find_rssdk()
  elseif("${_lib}" STREQUAL "vtk")
    find_VTK()
  elseif("${_lib}" STREQUAL "libusb-1.0")
    find_libusb()
  elseif("${_lib}" STREQUAL "glew")
    find_glew()
  elseif("${_lib}" STREQUAL "opengl")
    find_package(OpenGL)
  endif()

  string(TOUPPER "${_component}" COMPONENT)
  string(TOUPPER "${_lib}" LIB)
  string(REGEX REPLACE "[.-]" "_" LIB ${LIB})
  if(${LIB}_FOUND)
    list(APPEND PCL_${COMPONENT}_INCLUDE_DIRS ${${LIB}_INCLUDE_DIRS})
    if(${LIB}_USE_FILE)
      include(${${LIB}_USE_FILE})
    else()
      list(APPEND PCL_${COMPONENT}_LIBRARY_DIRS "${${LIB}_LIBRARY_DIRS}")
    endif()
    if(${LIB}_LIBRARIES)
      list(APPEND PCL_${COMPONENT}_LIBRARIES "${${LIB}_LIBRARIES}")
    endif()
    if(${LIB}_DEFINITIONS AND NOT ${LIB} STREQUAL "VTK")
      list(APPEND PCL_${COMPONENT}_DEFINITIONS ${${LIB}_DEFINITIONS})
    endif()
  else()
    if("${_is_optional}" STREQUAL "OPTIONAL")
      list(APPEND PCL_${COMPONENT}_DEFINITIONS "-DDISABLE_${LIB}")
      pcl_message("** WARNING ** ${_component} features related to ${_lib} will be disabled")
    elseif("${_is_optional}" STREQUAL "REQUIRED")
      if((NOT PCL_FIND_ALL) OR (PCL_FIND_ALL EQUAL 1))
        pcl_report_not_found("${_component} is required but ${_lib} was not found")
      elseif(PCL_FIND_ALL EQUAL 0)
        # raise error and remove _component from PCL_TO_FIND_COMPONENTS
        string(TOUPPER "${_component}" COMPONENT)
        pcl_message("** WARNING ** ${_component} will be disabled cause ${_lib} was not found")
        list(REMOVE_ITEM PCL_TO_FIND_COMPONENTS ${_component})
      endif()
    endif()
  endif()
endmacro()

macro(pcl_check_external_dependency _component)
endmacro()

#flatten dependencies recursivity is great \o/
macro(compute_dependencies TO_FIND_COMPONENTS)
  foreach(component ${${TO_FIND_COMPONENTS}})
    set(pcl_component pcl_${component})
    if(${pcl_component}_int_dep AND (NOT PCL_FIND_ALL))
      foreach(dependency ${${pcl_component}_int_dep})
        list(FIND ${TO_FIND_COMPONENTS} ${component} pos)
        list(FIND ${TO_FIND_COMPONENTS} ${dependency} found)
        if(found EQUAL -1)
          set(pcl_dependency pcl_${dependency})
          if(${pcl_dependency}_int_dep)
            list(INSERT ${TO_FIND_COMPONENTS} ${pos} ${dependency})
            if(pcl_${dependency}_ext_dep)
              list(APPEND pcl_${component}_ext_dep ${pcl_${dependency}_ext_dep})
            endif()
            if(pcl_${dependency}_opt_dep)
              list(APPEND pcl_${component}_opt_dep ${pcl_${dependency}_opt_dep})
            endif()
            compute_dependencies(${TO_FIND_COMPONENTS})
          else()
            list(INSERT ${TO_FIND_COMPONENTS} 0 ${dependency})
          endif()
        endif()
      endforeach()
    endif()
  endforeach()
endmacro()

### ---[ Find PCL

if(PCL_FIND_QUIETLY)
  set(QUIET_ QUIET)
else()
  set(QUIET_)
endif()

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_INCLUDE_DIRS "${PCL_ROOT}/include/pcl-${PCL_VERSION_MAJOR}.${PCL_VERSION_MINOR}")
  set(PCL_LIBRARY_DIRS "${PCL_ROOT}/lib")
  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_INCLUDE_DIRS "${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_INCLUDE_DIRS "${PCL_DIR}/include") # for pcl_config.h
  set(PCL_LIBRARY_DIRS "${PCL_DIR}/lib")
  set(PCL_SOURCES_TREE "/home/ubuntu/ppa/pcl")
else()
  pcl_report_not_found("PCL can not be found on this machine")
endif()

#set a suffix for debug libraries
set(PCL_DEBUG_SUFFIX "")
set(PCL_RELEASE_SUFFIX "")

#set SSE flags used compiling PCL
list(APPEND PCL_DEFINITIONS )
list(APPEND PCL_COMPILE_OPTIONS )

set(pcl_all_components  common kdtree octree search sample_consensus filters 2d geometry io features ml segmentation visualization surface registration keypoints tracking recognition stereo cuda_common cuda_features cuda_segmentation cuda_sample_consensus outofcore gpu_containers gpu_utils gpu_octree gpu_features gpu_segmentation people)
list(LENGTH pcl_all_components PCL_NB_COMPONENTS)

#list each component dependencies IN PCL
set(pcl_kdtree_int_dep common )
set(pcl_octree_int_dep common )
set(pcl_search_int_dep common kdtree octree )
set(pcl_sample_consensus_int_dep common search )
set(pcl_filters_int_dep common sample_consensus search kdtree octree )
set(pcl_2d_int_dep common filters )
set(pcl_geometry_int_dep common )
set(pcl_io_int_dep common octree )
set(pcl_features_int_dep common search kdtree octree filters 2d )
set(pcl_ml_int_dep common )
set(pcl_segmentation_int_dep common geometry search sample_consensus kdtree octree features filters ml )
set(pcl_visualization_int_dep common io kdtree geometry search octree )
set(pcl_surface_int_dep common search kdtree octree )
set(pcl_registration_int_dep common octree kdtree search sample_consensus features filters )
set(pcl_keypoints_int_dep common search kdtree octree features filters )
set(pcl_tracking_int_dep common search kdtree filters octree )
set(pcl_recognition_int_dep common io search kdtree octree features filters registration sample_consensus ml )
set(pcl_stereo_int_dep common io )
set(pcl_cuda_features_int_dep cuda_common io common )
set(pcl_cuda_segmentation_int_dep cuda_common io common )
set(pcl_cuda_sample_consensus_int_dep cuda_common io common )
set(pcl_outofcore_int_dep common io filters octree visualization )
set(pcl_gpu_containers_int_dep common )
set(pcl_gpu_utils_int_dep common gpu_containers )
set(pcl_gpu_octree_int_dep common gpu_containers gpu_utils )
set(pcl_gpu_features_int_dep common gpu_containers gpu_utils gpu_octree geometry )
set(pcl_gpu_segmentation_int_dep common gpu_containers gpu_utils gpu_octree )
set(pcl_people_int_dep common kdtree search features sample_consensus filters io visualization geometry segmentation octree )


#list each component external dependencies (ext means mandatory and opt means optional)
set(pcl_common_ext_dep eigen boost )
set(pcl_kdtree_ext_dep flann )
set(pcl_search_ext_dep flann )
set(pcl_visualization_ext_dep vtk )


set(pcl_2d_opt_dep vtk )
set(pcl_io_opt_dep pcap png vtk libusb-1.0 )
set(pcl_visualization_opt_dep )
set(pcl_surface_opt_dep qhull )


# VTK components required by PCL
set(PCL_VTK_COMPONENTS "vtkChartsCore;vtkCommonCore;vtkCommonDataModel;vtkCommonExecutionModel;vtkFiltersCore;vtkFiltersExtraction;vtkFiltersModeling;vtkImagingCore;vtkImagingSources;vtkInteractionStyle;vtkInteractionWidgets;vtkIOCore;vtkIOGeometry;vtkIOImage;vtkIOLegacy;vtkIOPLY;vtkRenderingAnnotation;vtkRenderingLOD;vtkViewsContext2D;vtkRenderingContextOpenGL2")

set(pcl_header_only_components 2d cuda_common geometry gpu_tracking modeler in_hand_scanner point_cloud_editor cloud_composer)

include(FindPackageHandleStandardArgs)

#check if user provided a list of components
#if no components at all or full list is given set PCL_FIND_ALL
if(PCL_FIND_COMPONENTS)
  list(LENGTH PCL_FIND_COMPONENTS PCL_FIND_COMPONENTS_LENGTH)
  if(PCL_FIND_COMPONENTS_LENGTH EQUAL PCL_NB_COMPONENTS)
    set(PCL_TO_FIND_COMPONENTS ${pcl_all_components})
    set(PCL_FIND_ALL 1)
  else()
    set(PCL_TO_FIND_COMPONENTS ${PCL_FIND_COMPONENTS})
  endif()
else()
  set(PCL_TO_FIND_COMPONENTS ${pcl_all_components})
  set(PCL_FIND_ALL 1)
endif()

compute_dependencies(PCL_TO_FIND_COMPONENTS)

# We do not need to find components that have been found already, e.g. during previous invocation
# of find_package(PCL). Filter them out.
foreach(component ${PCL_TO_FIND_COMPONENTS})
  string(TOUPPER "${component}" COMPONENT)
  if(NOT PCL_${COMPONENT}_FOUND)
    list(APPEND _PCL_TO_FIND_COMPONENTS ${component})
  endif()
endforeach()
set(PCL_TO_FIND_COMPONENTS ${_PCL_TO_FIND_COMPONENTS})
unset(_PCL_TO_FIND_COMPONENTS)

if(NOT PCL_TO_FIND_COMPONENTS)
  if(POLICY CMP0074)
    cmake_policy(POP)
  endif()
  return()
endif()

# compute external dependencies per component
foreach(component ${PCL_TO_FIND_COMPONENTS})
    foreach(opt ${pcl_${component}_opt_dep})
      find_external_library(${component} ${opt} OPTIONAL)
    endforeach()
    foreach(ext ${pcl_${component}_ext_dep})
      find_external_library(${component} ${ext} REQUIRED)
    endforeach()
endforeach()

foreach(component ${PCL_TO_FIND_COMPONENTS})
  set(pcl_component pcl_${component})
  string(TOUPPER "${component}" COMPONENT)

  pcl_message(STATUS "looking for PCL_${COMPONENT}")

  string(REGEX REPLACE "^cuda_(.*)$" "\\1" cuda_component "${component}")
  string(REGEX REPLACE "^gpu_(.*)$" "\\1" gpu_component "${component}")

  find_path(PCL_${COMPONENT}_INCLUDE_DIR
    NAMES pcl/${component}
          pcl/apps/${component}
          pcl/cuda/${cuda_component} pcl/cuda/${component}
          pcl/gpu/${gpu_component} pcl/gpu/${component}
    HINTS ${PCL_INCLUDE_DIRS}
          "${PCL_SOURCES_TREE}"
    PATH_SUFFIXES
          ${component}/include
          apps/${component}/include
          cuda/${cuda_component}/include
          gpu/${gpu_component}/include
    DOC "path to ${component} headers"
    NO_DEFAULT_PATH)
  mark_as_advanced(PCL_${COMPONENT}_INCLUDE_DIR)

  if(PCL_${COMPONENT}_INCLUDE_DIR)
    list(APPEND PCL_${COMPONENT}_INCLUDE_DIRS "${PCL_${COMPONENT}_INCLUDE_DIR}")
  else()
    #pcl_message("No include directory found for pcl_${component}.")
  endif()

  # Skip find_library for header only modules
  list(FIND pcl_header_only_components ${component} _is_header_only)
  if(_is_header_only EQUAL -1)
    find_library(PCL_${COMPONENT}_LIBRARY ${pcl_component}${PCL_RELEASE_SUFFIX}
      HINTS ${PCL_LIBRARY_DIRS}
      DOC "path to ${pcl_component} library"
      NO_DEFAULT_PATH)
    get_filename_component(${component}_library_path
      ${PCL_${COMPONENT}_LIBRARY}
      PATH)
    mark_as_advanced(PCL_${COMPONENT}_LIBRARY)

    find_library(PCL_${COMPONENT}_LIBRARY_DEBUG ${pcl_component}${PCL_DEBUG_SUFFIX}
      HINTS ${PCL_LIBRARY_DIRS}
      DOC "path to ${pcl_component} library debug"
      NO_DEFAULT_PATH)
    mark_as_advanced(PCL_${COMPONENT}_LIBRARY_DEBUG)

    if(PCL_${COMPONENT}_LIBRARY_DEBUG)
      get_filename_component(${component}_library_path_debug
        ${PCL_${COMPONENT}_LIBRARY_DEBUG}
        PATH)
    endif()

    # Restrict this to Windows users
    if(NOT PCL_${COMPONENT}_LIBRARY AND WIN32)
      # might be debug only
      set(PCL_${COMPONENT}_LIBRARY ${PCL_${COMPONENT}_LIBRARY_DEBUG})
    endif()

    find_package_handle_standard_args(PCL_${COMPONENT} DEFAULT_MSG
      PCL_${COMPONENT}_LIBRARY PCL_${COMPONENT}_INCLUDE_DIR)
  else()
    find_package_handle_standard_args(PCL_${COMPONENT} DEFAULT_MSG
      PCL_${COMPONENT}_INCLUDE_DIR)
  endif()

  if(PCL_${COMPONENT}_FOUND)
    if(NOT "${PCL_${COMPONENT}_INCLUDE_DIRS}" STREQUAL "")
      set(_filtered "")
      foreach(_inc ${PCL_${COMPONENT}_INCLUDE_DIRS})
        if(EXISTS ${_inc})
          list(APPEND _filtered "${_inc}")
        endif()
      endforeach()
      list(REMOVE_DUPLICATES _filtered)
      set(PCL_${COMPONENT}_INCLUDE_DIRS ${_filtered})
      list(APPEND PCL_INCLUDE_DIRS ${_filtered})
    endif()
    mark_as_advanced(PCL_${COMPONENT}_INCLUDE_DIRS)
    if(_is_header_only EQUAL -1)
      list(APPEND PCL_DEFINITIONS ${PCL_${COMPONENT}_DEFINITIONS})
      list(APPEND PCL_LIBRARY_DIRS ${component_library_path})
      if(PCL_${COMPONENT}_LIBRARY_DEBUG)
        list(APPEND PCL_LIBRARY_DIRS ${component_library_path_debug})
      endif()
      list(APPEND PCL_COMPONENTS ${pcl_component})
      mark_as_advanced(PCL_${COMPONENT}_LIBRARY PCL_${COMPONENT}_LIBRARY_DEBUG)
    endif()
    # Append internal dependencies
    foreach(int_dep ${pcl_${component}_int_dep})
      string(TOUPPER "${int_dep}" INT_DEP)
      if(PCL_${INT_DEP}_FOUND)
        list(APPEND PCL_${COMPONENT}_INCLUDE_DIRS ${PCL_${INT_DEP}_INCLUDE_DIRS})
        if(PCL_${INT_DEP}_LIBRARIES)
          list(APPEND PCL_${COMPONENT}_LINK_LIBRARIES "${PCL_${INT_DEP}_LIBRARIES}")
        endif()
      endif()
    endforeach()
    if(_is_header_only EQUAL -1)
      add_library(${pcl_component} SHARED IMPORTED)
      if(PCL_${COMPONENT}_LIBRARY_DEBUG)
        set_target_properties(${pcl_component}
          PROPERTIES
            IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
            IMPORTED_LOCATION_RELEASE "${PCL_${COMPONENT}_LIBRARY}"
            IMPORTED_LOCATION_DEBUG "${PCL_${COMPONENT}_LIBRARY_DEBUG}"
            IMPORTED_IMPLIB_RELEASE "${PCL_${COMPONENT}_LIBRARY}"
            IMPORTED_IMPLIB_DEBUG "${PCL_${COMPONENT}_LIBRARY_DEBUG}"
        )
      else()
        set_target_properties(${pcl_component}
          PROPERTIES
            IMPORTED_LOCATION "${PCL_${COMPONENT}_LIBRARY}"
            IMPORTED_IMPLIB "${PCL_${COMPONENT}_LIBRARY}"
        )
      endif()
      foreach(def ${PCL_DEFINITIONS})
        string(REPLACE " " ";" def2 ${def})
        string(REGEX REPLACE "^-D" "" def3 "${def2}")
        list(APPEND definitions ${def3})
      endforeach()
      if(CMAKE_VERSION VERSION_LESS 3.3)
        set_target_properties(${pcl_component}
          PROPERTIES
            INTERFACE_COMPILE_DEFINITIONS "${definitions}"
            INTERFACE_COMPILE_OPTIONS "${PCL_COMPILE_OPTIONS}"
            INTERFACE_COMPILE_FEATURES "cxx_std_14"
            INTERFACE_INCLUDE_DIRECTORIES "${PCL_${COMPONENT}_INCLUDE_DIRS}"
            INTERFACE_LINK_LIBRARIES "${PCL_${COMPONENT}_LINK_LIBRARIES}"
        )
      else()
        set_target_properties(${pcl_component}
          PROPERTIES
            INTERFACE_COMPILE_DEFINITIONS "${definitions}"
            INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:CXX>:${PCL_COMPILE_OPTIONS}>"
            INTERFACE_COMPILE_FEATURES "cxx_std_14"
            INTERFACE_INCLUDE_DIRECTORIES "${PCL_${COMPONENT}_INCLUDE_DIRS}"
            INTERFACE_LINK_LIBRARIES "${PCL_${COMPONENT}_LINK_LIBRARIES}"
        )
      endif()
      set(PCL_${COMPONENT}_LIBRARIES ${pcl_component})
    endif()
  endif()
endforeach()

if(NOT "${PCL_INCLUDE_DIRS}" STREQUAL "")
  list(REMOVE_DUPLICATES PCL_INCLUDE_DIRS)
endif()

if(NOT "${PCL_LIBRARY_DIRS}" STREQUAL "")
  list(REMOVE_DUPLICATES PCL_LIBRARY_DIRS)
endif()

if(NOT "${PCL_DEFINITIONS}" STREQUAL "")
  list(REMOVE_DUPLICATES PCL_DEFINITIONS)
endif()

pcl_remove_duplicate_libraries(PCL_COMPONENTS PCL_LIBRARIES)

# Add 3rd party libraries, as user code might include our .HPP implementations
list(APPEND PCL_LIBRARIES ${BOOST_LIBRARIES} ${QHULL_LIBRARIES} ${OPENNI_LIBRARIES} ${OPENNI2_LIBRARIES} ${ENSENSO_LIBRARIES} ${davidSDK_LIBRARIES} ${DSSDK_LIBRARIES} ${RSSDK_LIBRARIES} ${VTK_LIBRARIES})
if (TARGET FLANN::FLANN)
  list(APPEND PCL_LIBRARIES FLANN::FLANN)
endif()

find_package_handle_standard_args(PCL DEFAULT_MSG PCL_LIBRARIES PCL_INCLUDE_DIRS)
mark_as_advanced(PCL_LIBRARIES PCL_INCLUDE_DIRS PCL_LIBRARY_DIRS)

if(POLICY CMP0074)
  cmake_policy(POP)
endif()

FindFLANN.cmake

#.rst:
# FindFLANN
# --------
#
# Try to find FLANN library and headers. This module supports both old released versions
# of FLANN ≤ 1.9.1 and newer development versions that ship with a modern config file.
#
# IMPORTED Targets
# ^^^^^^^^^^^^^^^^
#
# This module defines the :prop_tgt:`IMPORTED` targets:
#
# ``FLANN::FLANN``
#  Defined if the system has FLANN.
#
# Result Variables
# ^^^^^^^^^^^^^^^^
#
# This module sets the following variables:
#
# ::
#
#   FLANN_FOUND               True in case FLANN is found, otherwise false
#   FLANN_ROOT                Path to the root of found FLANN installation
#
# Example usage
# ^^^^^^^^^^^^^
#
# ::
#
#     find_package(FLANN REQUIRED)
#
#     add_executable(foo foo.cc)
#     target_link_libraries(foo FLANN::FLANN)
#

# First try to locate FLANN using modern config
find_package(flann NO_MODULE ${FLANN_FIND_VERSION} QUIET)
if(flann_FOUND)
  unset(flann_FOUND)
  set(FLANN_FOUND ON)
  # Create interface library that effectively becomes an alias for the appropriate (static/dynamic) imported FLANN target
  add_library(FLANN::FLANN INTERFACE IMPORTED)
  if(FLANN_USE_STATIC)
    set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp_s)
  else()
    set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp)
  endif()
  # Determine FLANN installation root based on the path to the processed Config file
  get_filename_component(_config_dir "${flann_CONFIG}" DIRECTORY)
  get_filename_component(FLANN_ROOT "${_config_dir}/../../.." ABSOLUTE)
  unset(_config_dir)
  return()
endif()

# Second try to locate FLANN using pkgconfig
find_package(PkgConfig QUIET)
if(FLANN_FIND_VERSION)
  pkg_check_modules(PC_FLANN flann>=${FLANN_FIND_VERSION})
else()
  pkg_check_modules(PC_FLANN flann)
endif()

find_path(FLANN_INCLUDE_DIR
  NAMES
    flann/flann.hpp
  HINTS
    ${PC_FLANN_INCLUDE_DIRS}
    ${FLANN_ROOT}
    $ENV{FLANN_ROOT}
  PATHS
    $ENV{PROGRAMFILES}/Flann
    $ENV{PROGRAMW6432}/Flann
  PATH_SUFFIXES
    include
)

if(FLANN_USE_STATIC)
  set(FLANN_RELEASE_NAME flann_cpp_s)
  set(FLANN_DEBUG_NAME flann_cpp_s-gd)
  set(FLANN_LIBRARY_TYPE STATIC)
else()
  set(FLANN_RELEASE_NAME flann_cpp)
  set(FLANN_DEBUG_NAME flann_cpp-gd)
  set(FLANN_LIBRARY_TYPE SHARED)
endif()

find_library(FLANN_LIBRARY
  NAMES
    ${FLANN_RELEASE_NAME}
  HINTS
    ${PC_FLANN_LIBRARY_DIRS}
    ${FLANN_ROOT}
    $ENV{FLANN_ROOT}
  PATHS
    $ENV{PROGRAMFILES}/Flann
    $ENV{PROGRAMW6432}/Flann
  PATH_SUFFIXES
    lib
)

find_library(FLANN_LIBRARY_DEBUG
  NAMES
    ${FLANN_DEBUG_NAME}
  HINTS
    ${PC_FLANN_LIBRARY_DIRS}
    ${FLANN_ROOT}
    $ENV{FLANN_ROOT}
  PATHS
    $ENV{PROGRAMFILES}/Flann
    $ENV{PROGRAMW6432}/Flann
  PATH_SUFFIXES
    lib
)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
  FLANN DEFAULT_MSG
  FLANN_LIBRARY FLANN_INCLUDE_DIR
)

if(FLANN_FOUND)
  if(NOT TARGET FLANN::FLANN)
    add_library(FLANN::FLANN ${FLANN_LIBRARY_TYPE} IMPORTED)
    set_target_properties(FLANN::FLANN PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FLANN_INCLUDE_DIR}")
    set_target_properties(FLANN::FLANN PROPERTIES INTERFACE_COMPILE_DEFINITIONS "${PC_FLANN_CFLAGS_OTHER}")
    set_property(TARGET FLANN::FLANN APPEND PROPERTY IMPORTED_CONFIGURATIONS "RELEASE")
    set_target_properties(FLANN::FLANN PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX")
    if(WIN32 AND NOT FLANN_USE_STATIC)
      set_target_properties(FLANN::FLANN PROPERTIES IMPORTED_IMPLIB_RELEASE "${FLANN_LIBRARY}")
    else()
      set_target_properties(FLANN::FLANN PROPERTIES IMPORTED_LOCATION_RELEASE "${FLANN_LIBRARY}")
    endif()
    if(FLANN_LIBRARY_DEBUG)
      set_property(TARGET FLANN::FLANN APPEND PROPERTY IMPORTED_CONFIGURATIONS "DEBUG")
      set_target_properties(FLANN::FLANN PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX")
      if(WIN32 AND NOT FLANN_USE_STATIC)
        set_target_properties(FLANN::FLANN PROPERTIES IMPORTED_IMPLIB_DEBUG "${FLANN_LIBRARY_DEBUG}")
      else()
        set_target_properties(FLANN::FLANN PROPERTIES IMPORTED_LOCATION_DEBUG "${FLANN_LIBRARY_DEBUG}")
      endif()
    endif()
  endif()
  get_filename_component(FLANN_ROOT "${FLANN_INCLUDE_DIR}" PATH)
endif()

If you need me to show you the files with pcl compiled with FLANN master let me know.

@taketwo
Copy link
Member Author

taketwo commented Aug 27, 2019

It's been a while, but I finally had time today to investigate and found the problem.

Our new FindFLANN.cmake is not fully "reentrant"; calling find_package(FLANN) multiple times leads to redefinition of FLANN::FLANN target, which is not allowed by CMake. In fact, the "pkgconfig" branch is fine, because it checks if the target already exists. A similar check is lacking in the "modern config" branch.

As a quick fix, just add these lines to the top of FindFLANN.cmake:

if(TARGET FLANN::FLANN)
  return()
endif()

I'll send a PR later.

@jasjuang
Copy link
Contributor

jasjuang commented Aug 27, 2019

@taketwo amazing find, you are right that I was testing with my full-on downstream project and there are multiple find_package(PCL) calls. If I create a minimal example to test it out I might've discovered it earlier. I can confirm that this solves the problem. Looking forward to the PR and the merge!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants