Skip to content

Commit

Permalink
(#5613) pdal: allow static builds + add several options + unvendor bo…
Browse files Browse the repository at this point in the history
…ost & eigen + fix direct dependencies

* no os.rename

* formatting

* fix pkg_config name

official pkgconfig file is lowercase

* add more topics

* remove pdal-config* from package

* reorder methods by order of execution

* bump dependencies

* add zlib option & fix direct dependencies

libcurl & zlib are direct dependencies (libcurl is a dependency of vendored arbiter).
It was working previously because these libraries were dragged indirectly by other dependencies, but it could have failed with other options values of these dependencies.

* avoid to enable libunwind if with_unwind option is False

* unvendor boost & eigen

pdal depends on boost filesystem

* allow to build static libs of PDAL

we also build pdal_util as a static lib

* do not hardcode rpath into shared libs

* add with_lzma option

* add with_lazperf option

this option is disabled for the moment since lazperf recipe is not available in CCI.

* fix typo

* bump libcurl version
  • Loading branch information
SpaceIm authored Jun 7, 2021
1 parent 38d85e3 commit 66e8222
Showing 1 changed file with 134 additions and 54 deletions.
188 changes: 134 additions & 54 deletions recipes/pdal/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,52 +1,49 @@
import os
from conans import ConanFile, tools, CMake
from conans.errors import ConanInvalidConfiguration
import os

required_conan_version = ">=1.33.0"


class PdalConan(ConanFile):
name = "pdal"
description = "PDAL is Point Data Abstraction Library. GDAL for point cloud data."
topics = ("conan", "pdal", "gdal", "point-cloud-data", "lidar")
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://pdal.io"
license = "BSD-3-Clause"
exports_sources = ["CMakeLists.txt", "patches/*"]
generators = "cmake", "cmake_find_package"

settings = "os", "arch", "compiler", "build_type"
options = {"shared": [True, False],
"fPIC": [True, False],
"with_unwind": [True, False],
"with_xml": [True, False],
"with_zstd": [True, False],
"with_laszip": [True, False],
}
default_options = {"shared": True,
"fPIC": True,
"with_unwind": False,
"with_xml": True,
"with_zstd": True,
"with_laszip": True}
topics = ("conan", "pdal", "gdal")

_source_subfolder = "source_subfolder"
options = {
"shared": [True, False],
"fPIC": [True, False],
"with_unwind": [True, False],
"with_xml": [True, False],
"with_lazperf": [True, False],
"with_laszip": [True, False],
"with_zlib": [True, False],
"with_lzma": [True, False],
"with_zstd": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
"with_unwind": False,
"with_xml": True,
"with_lazperf": False, # TODO: should be True
"with_laszip": True,
"with_zlib": True,
"with_lzma": False,
"with_zstd": True,
}

exports_sources = ["CMakeLists.txt", "patches/*"]
generators = "cmake", "cmake_find_package"
_cmake = None

def requirements(self):
# TODO package improvements:
# - switch from vendored arbiter (not in CCI). disabled openssl and curl are deps of arbiter
# - switch from vendor/nlohmann to nlohmann_json (in CCI)
# - evaluate dependency to boost instead of boost parts in vendor/pdalboost
self.requires("gdal/3.1.4")
self.requires("libgeotiff/1.6.0")
if self.options.with_xml:
self.requires("libxml2/2.9.10")
if self.options.with_zstd:
self.requires("zstd/1.4.5")
if self.options.with_laszip:
self.requires("laszip/3.4.3")
if self.options.get_safe("with_unwind"):
self.requires("libunwind/1.3.1")
# vendored nanoflann is 1.3.1 with minor code removal
self.requires("nanoflann/1.3.1")
@property
def _source_subfolder(self):
return "source_subfolder"

def config_options(self):
if self.settings.os == "Windows":
Expand All @@ -55,30 +52,63 @@ def config_options(self):
del self.options.with_unwind

def configure(self):
# upstream export/install targets do not work with static builds
if not self.options.shared:
raise ConanInvalidConfiguration("pdal does not support building as a static lib yet")
if self.options.shared:
del self.options.fPIC
if self.settings.compiler.cppstd:
tools.check_min_cppstd(self, 11)
if self.settings.compiler == "gcc" and tools.Version(self.settings.compiler.version) < 5:
raise ConanInvalidConfiguration ("This compiler version is unsupported")

def requirements(self):
# TODO package improvements:
# - switch from vendored arbiter (not in CCI). disabled openssl and curl are deps of arbiter
# - switch from vendor/nlohmann to nlohmann_json (in CCI)
self.requires("boost/1.76.0")
self.requires("eigen/3.3.9")
self.requires("gdal/3.2.1")
self.requires("libcurl/7.77.0") # mandatory dependency of arbiter (to remove if arbiter is unvendored)
self.requires("libgeotiff/1.6.0")
self.requires("nanoflann/1.3.2")
if self.options.with_xml:
self.requires("libxml2/2.9.10")
if self.options.with_zstd:
self.requires("zstd/1.5.0")
if self.options.with_lazperf:
raise ConanInvalidConfiguration("lazperf recipe not yet available in CCI")
if self.options.with_laszip:
self.requires("laszip/3.4.3")
if self.options.with_zlib:
self.requires("zlib/1.2.11")
if self.options.with_lzma:
self.requires("xz_utils/5.2.5")
if self.options.get_safe("with_unwind"):
self.requires("libunwind/1.5.0")

@property
def _required_boost_components(self):
return ["filesystem"]

def validate(self):
miss_boost_required_comp = any(getattr(self.options["boost"], "without_{}".format(boost_comp), True) for boost_comp in self._required_boost_components)
if self.options["boost"].header_only or miss_boost_required_comp:
raise ConanInvalidConfiguration("{0} requires non header-only boost with these components: {1}".format(self.name, ", ".join(self._required_boost_components)))

def source(self):
tools.get(**self.conan_data["sources"][self.version])
os.rename("PDAL-%s-src" % self.version, self._source_subfolder)
tools.get(**self.conan_data["sources"][self.version],
destination=self._source_subfolder, strip_root=True)

def _configure_cmake(self):
if self._cmake:
return self._cmake

self._cmake = CMake(self)
self._cmake.definitions["PDAL_BUILD_STATIC"] = not self.options.shared
self._cmake.definitions["WITH_TESTS"] = False
self._cmake.definitions["WITH_LAZPERF"] = False
self._cmake.definitions["WITH_LAZPERF"] = self.options.with_lazperf
self._cmake.definitions["WITH_LASZIP"] = self.options.with_laszip
self._cmake.definitions["WITH_STATIC_LASZIP"] = True # doesn't really matter but avoids to inject useless definition
self._cmake.definitions["WITH_ZSTD"] = self.options.with_zstd
self._cmake.definitions["WITH_ZLIB"] = True
self._cmake.definitions["WITH_ZLIB"] = self.options.with_zlib
self._cmake.definitions["WITH_LZMA"] = self.options.with_lzma
# disable plugin that requires postgresql
self._cmake.definitions["BUILD_PLUGIN_PGPOINTCLOUD"] = False
self._cmake.configure()
Expand All @@ -89,16 +119,46 @@ def _patch_sources(self):
tools.patch(**patch)
# drop conflicting CMake files
# LASzip works fine
for module in ('ZSTD', 'ICONV', 'GeoTIFF', 'Curl'):
for module in ("ZSTD", "ICONV", "GeoTIFF", "Curl"):
os.remove(os.path.join(self._source_subfolder, "cmake", "modules", "Find"+module+".cmake"))

top_cmakelists = os.path.join(self._source_subfolder, "CMakeLists.txt")
util_cmakelists = os.path.join(self._source_subfolder, "pdal", "util", "CMakeLists.txt")

# disabling libxml2 support is only done via patching
if not self.options.with_xml:
tools.replace_in_file(
os.path.join(self._source_subfolder, "CMakeLists.txt"),
"include(${PDAL_CMAKE_DIR}/libxml2.cmake)",
"#include(${PDAL_CMAKE_DIR}/libxml2.cmake)")
tools.replace_in_file(top_cmakelists, "include(${PDAL_CMAKE_DIR}/libxml2.cmake)", "")
# disabling libunwind support is only done via patching
if not self.options.get_safe("with_unwind", False):
tools.replace_in_file(util_cmakelists, "include(${PDAL_CMAKE_DIR}/unwind.cmake)", "")
# remove vendored eigen
tools.rmdir(os.path.join(self._source_subfolder, "vendor", "eigen"))
# remove vendored nanoflann. include path is patched
tools.rmdir(os.path.join(self._source_subfolder, 'vendor', 'nanoflann'))
tools.rmdir(os.path.join(self._source_subfolder, "vendor", "nanoflann"))
# remove vendored boost
tools.rmdir(os.path.join(self._source_subfolder, "vendor", "pdalboost"))
tools.replace_in_file(top_cmakelists, "add_subdirectory(vendor/pdalboost)", "")
tools.replace_in_file(util_cmakelists, "${PDAL_BOOST_LIB_NAME}", "${CONAN_LIBS}")
tools.replace_in_file(os.path.join(self._source_subfolder, "pdal", "util", "FileUtils.cpp"),
"pdalboost::", "boost::")
# No rpath manipulation
tools.replace_in_file(top_cmakelists, "include(${PDAL_CMAKE_DIR}/rpath.cmake)", "")
# No reexport
tools.replace_in_file(top_cmakelists,
"set(PDAL_REEXPORT \"-Wl,-reexport_library,$<TARGET_FILE:${PDAL_UTIL_LIB_NAME}>\")",
"")
# fix static build
if not self.options.shared:
tools.replace_in_file(top_cmakelists, "add_definitions(\"-DPDAL_DLL_EXPORT=1\")", "")
tools.replace_in_file(top_cmakelists,
"${PDAL_BASE_LIB_NAME} ${PDAL_UTIL_LIB_NAME}",
"${PDAL_BASE_LIB_NAME} ${PDAL_UTIL_LIB_NAME} ${PDAL_ARBITER_LIB_NAME} ${PDAL_KAZHDAN_LIB_NAME}")
tools.replace_in_file(os.path.join(self._source_subfolder, "cmake", "macros.cmake"),
" install(TARGETS ${_name}",
" endif()\n if (PDAL_LIB_TYPE STREQUAL \"STATIC\" OR NOT ${_library_type} STREQUAL \"STATIC\")\n install(TARGETS ${_name}")
tools.replace_in_file(util_cmakelists,
"PDAL_ADD_FREE_LIBRARY(${PDAL_UTIL_LIB_NAME} SHARED ${PDAL_UTIL_SOURCES})",
"PDAL_ADD_FREE_LIBRARY(${PDAL_UTIL_LIB_NAME} ${PDAL_LIB_TYPE} ${PDAL_UTIL_SOURCES})")

def build(self):
self._patch_sources()
Expand All @@ -109,13 +169,33 @@ def package(self):
self.copy("LICENSE.txt", src=self._source_subfolder, dst="licenses", ignore_case=True, keep_path=False)
cmake = self._configure_cmake()
cmake.install()
tools.rmdir(os.path.join(self.package_folder, 'lib', 'cmake'))
tools.rmdir(os.path.join(self.package_folder, 'lib', 'pkgconfig'))
tools.rmdir(os.path.join(self.package_folder, "lib", "cmake"))
tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig"))
tools.remove_files_by_mask(os.path.join(self.package_folder, "bin"), "pdal-config*")

def package_info(self):
self.cpp_info.names["cmake_find_package"] = "PDAL"
self.cpp_info.names["cmake_find_package_multi"] = "PDAL"
self.cpp_info.names["pkg_config"] = "PDAL"
self.cpp_info.libs = tools.collect_libs(self)
self.cpp_info.names["pkg_config"] = "pdal"
pdal_base_name = "pdalcpp" if self.settings.os == "Windows" or tools.is_apple_os(self.settings.os) else "pdal_base"
self.cpp_info.libs = [pdal_base_name, "pdal_util"]
if not self.options.shared:
self.cpp_info.libs.extend(["pdal_arbiter", "pdal_kazhdan"])
if self.settings.os == "Linux":
self.cpp_info.system_libs.extend(["dl", "m"])
self.cpp_info.requires = [
"boost::filesystem", "eigen::eigen", "gdal::gdal",
"libcurl::libcurl", "libgeotiff::libgeotiff", "nanoflann::nanoflann"
]
if self.options.with_xml:
self.cpp_info.requires.append("libxml2::libxml2")
if self.options.with_zstd:
self.cpp_info.requires.append("zstd::zstd")
if self.options.with_laszip:
self.cpp_info.requires.append("laszip::laszip")
if self.options.with_zlib:
self.cpp_info.requires.append("zlib::zlib")
if self.options.with_lzma:
self.cpp_info.requires.append("xz_utils::xz_utils")
if self.options.get_safe("with_unwind"):
self.cpp_info.requires.append("libunwind::libunwind")

0 comments on commit 66e8222

Please sign in to comment.