Repository: conan-io/conan-center-index

Issue:
[request] libigl/2.4.0
### Package Details
  * Package Name/Version: **libigl/2.4.0**
  * Website: **https://libigl.github.io/**
  * Source code: **https://github.com/libigl/libigl**


### Description Of The Library / Tool

From their website:

> libigl is a simple C++ geometry processing library. We have a wide functionality including construction of sparse discrete differential geometry operators and finite-elements matrices such as the cotangent Laplacian and diagonalized mass matrix, simple facet and edge-based topology data structures, mesh-viewing utilities for OpenGL and GLSL, and many core functions for matrix manipulation which make [Eigen](http://eigen.tuxfamily.org/) feel a lot more like MATLAB.



Discussion:
relates to https://github.com/conan-io/conan-center-index/pull/9469
@svenpilz, the recipe works fine locally, but not in the CI
> relates to #9469

Thanks @AndreyMlashkin, did not saw your pull-request.

Resolving patch:
diff --git a/recipes/libigl/2.x.x/conanfile.py b/recipes/libigl/2.x.x/conanfile.py
deleted file mode 100644
--- a/recipes/libigl/2.x.x/conanfile.py
+++ /dev/null
@@ -1,140 +0,0 @@
-import os
-from conans import ConanFile, tools, CMake
-from conans.errors import ConanInvalidConfiguration
-
-
-class LibiglConan(ConanFile):
-    name = "libigl"
-    description = ("Simple C++ geometry processing library")
-    topics = ("conan", "libigl", "geometry", "matrices", "algorithms")
-    url = "https://github.com/conan-io/conan-center-index"
-    exports_sources = ["CMakeLists.txt", "patches/**"]
-    homepage = "https://libigl.github.io/"
-    license = "MPL-2.0"
-    settings = "os", "arch", "compiler", "build_type"
-    options = {"header_only": [True, False], "fPIC": [True, False]}
-    default_options = {"header_only": True, "fPIC": True}
-    generators = "cmake", "cmake_find_package"
-    requires = ("eigen/3.3.9")
-    _cmake = None
-
-    @property
-    def _source_subfolder(self):
-        return "source_subfolder"
-
-    @property
-    def _build_subfolder(self):
-        return "build_subfolder"
-
-    @property
-    def _minimum_cpp_standard(self):
-        return 14
-
-    @property
-    def _minimum_compilers_version(self):
-        return {
-            "Visual Studio": "16",
-            "gcc": "6",
-            "clang": "3.4",
-            "apple-clang": "5.1",
-        }
-
-    def validate(self):
-        if self.settings.compiler.get_safe("cppstd"):
-            tools.check_min_cppstd(self, self._minimum_cpp_standard)
-        min_version = self._minimum_compilers_version.get(str(self.settings.compiler))
-        if not min_version:
-            self.output.warn("{} recipe lacks information about the {} compiler support.".format(
-                self.name, self.settings.compiler))
-        else:
-            if tools.Version(self.settings.compiler.version) < min_version:
-                raise ConanInvalidConfiguration("{} requires C++{} support. The current compiler {} {} does not support it.".format(
-                    self.name, self._minimum_cpp_standard, self.settings.compiler, self.settings.compiler.version))
-        if self.settings.compiler == "Visual Studio" and "MT" in self.settings.compiler.runtime and not self.options.header_only:
-            raise ConanInvalidConfiguration("Visual Studio build with MT runtime is not supported")
-        if "arm" in self.settings.arch or "x86" is self.settings.arch:
-            raise ConanInvalidConfiguration("Not available for arm. Requested arch: {}".format(self.settings.arch))
-
-    def config_options(self):
-        if self.settings.os == "Windows":
-            del self.options.fPIC
-
-    def configure(self):
-        if self.options.header_only:
-            del self.options.fPIC
-
-    def _patch_sources(self):
-        for patch in self.conan_data.get("patches", {}).get(self.version, []):
-            tools.patch(**patch)
-
-    def source(self):
-        tools.get(**self.conan_data["sources"][self.version], strip_root=True, destination=self._source_subfolder)
-
-    def _configure_cmake(self):
-        if not self._cmake:
-            self._cmake = CMake(self, parallel=False)
-            self._cmake.definitions["LIBIGL_EXPORT_TARGETS"] = True
-            self._cmake.definitions["LIBIGL_USE_STATIC_LIBRARY"] = not self.options.header_only
-
-            # All these dependencies are needed to build the examples or the tests
-            self._cmake.definitions["LIBIGL_BUILD_TUTORIALS"] = "OFF"
-            self._cmake.definitions["LIBIGL_BUILD_TESTS"] = "OFF"
-            self._cmake.definitions["LIBIGL_BUILD_PYTHON"] = "OFF"
-
-            self._cmake.definitions["LIBIGL_WITH_CGAL"] = False
-            self._cmake.definitions["LIBIGL_WITH_COMISO"] = False
-            self._cmake.definitions["LIBIGL_WITH_CORK"] = False
-            self._cmake.definitions["LIBIGL_WITH_EMBREE"] = False
-            self._cmake.definitions["LIBIGL_WITH_MATLAB"] = False
-            self._cmake.definitions["LIBIGL_WITH_MOSEK"] = False
-            self._cmake.definitions["LIBIGL_WITH_OPENGL"] = False
-            self._cmake.definitions["LIBIGL_WITH_OPENGL_GLFW"] = False
-            self._cmake.definitions["LIBIGL_WITH_OPENGL_GLFW_IMGUI"] = False
-            self._cmake.definitions["LIBIGL_WITH_PNG"] = False
-            self._cmake.definitions["LIBIGL_WITH_TETGEN"] = False
-            self._cmake.definitions["LIBIGL_WITH_TRIANGLE"] = False
-            self._cmake.definitions["LIBIGL_WITH_XML"] = False
-            self._cmake.definitions["LIBIGL_WITH_PYTHON"] = "OFF"
-            self._cmake.definitions["LIBIGL_WITH_PREDICATES"] = False
-        return self._cmake
-
-    def build(self):
-        self._patch_sources()
-        cmake = self._configure_cmake()
-        cmake.configure()
-        cmake.build()
-
-    def package(self):
-        cmake = self._configure_cmake()
-        cmake.install()
-        self.copy("LICENSE.GPL", dst="licenses", src=self._source_subfolder)
-        self.copy("LICENSE.MPL2", dst="licenses", src=self._source_subfolder)
-
-        tools.rmdir(os.path.join(self.package_folder, "share"))
-        if not self.options.header_only:
-            tools.remove_files_by_mask(self.package_folder, "*.c")
-            tools.remove_files_by_mask(self.package_folder, "*.cpp")
-
-    def package_id(self):
-        if self.options.header_only:
-            self.info.header_only()
-
-    def package_info(self):
-        self.cpp_info.filenames["cmake_find_package"] = "libigl"
-        self.cpp_info.filenames["cmake_find_package_multi"] = "libigl"
-        self.cpp_info.names["cmake_find_package"] = "igl"
-        self.cpp_info.names["cmake_find_package_multi"] = "igl"
-
-        self.cpp_info.components["igl_common"].names["cmake_find_package"] = "common"
-        self.cpp_info.components["igl_common"].names["cmake_find_package_multi"] = "common"
-        self.cpp_info.components["igl_common"].libs = []
-        self.cpp_info.components["igl_common"].requires = ["eigen::eigen"]
-        if self.settings.os == "Linux":
-            self.cpp_info.components["igl_common"].system_libs = ["pthread"]
-
-        self.cpp_info.components["igl_core"].names["cmake_find_package"] = "core"
-        self.cpp_info.components["igl_core"].names["cmake_find_package_multi"] = "core"
-        self.cpp_info.components["igl_core"].requires = ["igl_common"]
-        if not self.options.header_only:
-            self.cpp_info.components["igl_core"].libs = ["igl"]
-            self.cpp_info.components["igl_core"].defines.append("IGL_STATIC_LIBRARY")
diff --git a/recipes/libigl/all/conanfile.py b/recipes/libigl/all/conanfile.py
new file mode 100644
--- /dev/null
+++ b/recipes/libigl/all/conanfile.py
@@ -0,0 +1,210 @@
+import os
+
+from conan import ConanFile, conan_version
+from conan.errors import ConanInvalidConfiguration, ConanException
+from conan.tools.build import check_min_cppstd
+from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
+from conan.tools.env import VirtualBuildEnv
+from conan.tools.files import copy, get, rm, rmdir, replace_in_file, export_conandata_patches, apply_conandata_patches
+from conan.tools.microsoft import is_msvc_static_runtime
+from conan.tools.scm import Version
+
+required_conan_version = ">=1.52.0"
+
+
+class LibiglConan(ConanFile):
+    name = "libigl"
+    description = "Simple C++ geometry processing library"
+    # As per https://libigl.github.io/license/, the library itself is MPL-2, components are not
+    # No issue as we don't build them, but if done so in the future, please update this field!
+    license = "MPL-2.0"
+    url = "https://github.com/conan-io/conan-center-index"
+    homepage = "https://libigl.github.io/"
+    topics = ("geometry", "matrices", "algorithms", "header-only")
+
+    package_type = "static-library"
+    settings = "os", "arch", "compiler", "build_type"
+    options = {
+        "fPIC": [True, False],
+        "header_only": [True, False],
+    }
+    default_options = {
+        "fPIC": True,
+        "header_only": False,
+    }
+
+    @property
+    def _minimum_cpp_standard(self):
+        return 14
+
+    @property
+    def _minimum_compilers_version(self):
+        return {
+            "Visual Studio": "16",
+            "msvc": "192",
+            "gcc": "6",
+            "clang": "3.4",
+            "apple-clang": "5.1",
+        }
+
+    def export_sources(self):
+        export_conandata_patches(self)
+        copy(self, "conan_deps.cmake", self.recipe_folder, os.path.join(self.export_sources_folder, "src"))
+
+    def config_options(self):
+        if self.settings.os == "Windows":
+            del self.options.fPIC
+
+    def configure(self):
+        if self.options.header_only:
+            self.options.rm_safe("fPIC")
+            # No automatic detection for non "library" package-types, manually override
+            self.package_type = "header-library"
+
+    def layout(self):
+        cmake_layout(self, src_folder="src")
+
+    def requirements(self):
+        if Version(self.version) >= "2.5.0":
+            self.requires("eigen/3.4.0", transitive_headers=True)
+        else:
+            # 3.4.0 is not compatible with older versions
+            self.requires("eigen/3.3.9", transitive_headers=True)
+
+    def build_requirements(self):
+        self.tool_requires("cmake/[>=3.16 <4]")
+
+    def package_id(self):
+        if self.info.options.header_only:
+            self.info.clear()
+
+    def validate(self):
+        if "arm" in self.settings.arch or self.settings.arch == "x86":
+            raise ConanInvalidConfiguration(f"Not available for arm. Requested arch: {self.settings.arch}")
+        if is_msvc_static_runtime(self) and not self.options.header_only:
+            raise ConanInvalidConfiguration("Visual Studio build with MT runtime is not supported")
+
+        if self.version == "2.3.0" and conan_version.major == 1 and self.settings.build_type == "Debug":
+            raise ConanInvalidConfiguration("Debug build disabled for Conan 1.x due to excessive memory use in ConanCenter CI")
+
+        def loose_lt_semver(v1, v2):
+            return all(int(p1) < int(p2) for p1, p2 in zip(str(v1).split("."), str(v2).split(".")))
+
+        if self.settings.compiler.cppstd:
+            check_min_cppstd(self, self._minimum_cpp_standard)
+        min_version = self._minimum_compilers_version.get(str(self.settings.compiler))
+        if min_version and loose_lt_semver(self.settings.compiler.version, min_version):
+            raise ConanInvalidConfiguration(
+                f"{self.name} requires C++{self._minimum_cpp_standard} support. The current compiler"
+                f" {self.settings.compiler} {self.settings.compiler.version} does not support it."
+            )
+
+    def source(self):
+        get(self, **self.conan_data["sources"][self.version], strip_root=True)
+
+    def generate(self):
+        env = VirtualBuildEnv(self)
+        env.generate()
+
+        tc = CMakeToolchain(self)
+        tc.variables["CMAKE_PROJECT_libigl_INCLUDE"] = "conan_deps.cmake"
+        tc.variables["LIBIGL_USE_STATIC_LIBRARY"] = not self.options.header_only
+        tc.variables["LIBIGL_POSITION_INDEPENDENT_CODE"] = self.options.get_safe("fPIC", True)
+        tc.cache_variables["CMAKE_POLICY_DEFAULT_CMP0048"] = "NEW"
+        tc.cache_variables["CMAKE_POLICY_DEFAULT_CMP0077"] = "NEW"
+
+        # All these dependencies are needed to build the examples or the tests
+        tc.variables["LIBIGL_BUILD_TUTORIALS"] = False
+        tc.variables["LIBIGL_BUILD_TESTS"] = False
+        tc.variables["LIBIGL_BUILD_PYTHON"] = False
+
+        if Version(self.version) >= "2.4.0":
+            tc.variables["LIBIGL_EMBREE"] = False
+            tc.variables["LIBIGL_GLFW"] = False
+            tc.variables["LIBIGL_IMGUI"] = False
+            tc.variables["LIBIGL_OPENGL"] = False
+            tc.variables["LIBIGL_STB"] = False
+            tc.variables["LIBIGL_PREDICATES"] = False
+            tc.variables["LIBIGL_SPECTRA"] = False
+            tc.variables["LIBIGL_XML"] = False
+            tc.variables["LIBIGL_COPYLEFT_CORE"] = False
+            tc.variables["LIBIGL_COPYLEFT_CGAL"] = False
+            tc.variables["LIBIGL_COPYLEFT_COMISO"] = False
+            tc.variables["LIBIGL_COPYLEFT_TETGEN"] = False
+            tc.variables["LIBIGL_RESTRICTED_MATLAB"] = False
+            tc.variables["LIBIGL_RESTRICTED_MOSEK"] = False
+            tc.variables["LIBIGL_RESTRICTED_TRIANGLE"] = False
+            tc.variables["LIBIGL_GLFW_TESTS"] = False
+        else:
+            tc.variables["LIBIGL_EXPORT_TARGETS"] = True
+            tc.variables["LIBIGL_WITH_EMBREE"] = False
+            tc.variables["LIBIGL_WITH_OPENGL_GLFW"] = False
+            tc.variables["LIBIGL_WITH_OPENGL_GLFW_IMGUI"] = False
+            tc.variables["LIBIGL_WITH_OPENGL"] = False
+            tc.variables["LIBIGL_WITH_PNG"] = False
+            tc.variables["LIBIGL_WITH_PREDICATES"] = False
+            tc.variables["LIBIGL_WITH_XML"] = False
+            tc.variables["LIBIGL_WITH_CGAL"] = False
+            tc.variables["LIBIGL_WITH_COMISO"] = False
+            tc.variables["LIBIGL_WITH_CORK"] = False
+            tc.variables["LIBIGL_WITH_TETGEN"] = False
+            tc.variables["LIBIGL_WITH_MATLAB"] = False
+            tc.variables["LIBIGL_WITH_MOSEK"] = False
+            tc.variables["LIBIGL_WITH_TRIANGLE"] = False
+            tc.variables["LIBIGL_WITH_PYTHON"] = False
+        tc.generate()
+
+        deps = CMakeDeps(self)
+        deps.generate()
+
+    def _patch_sources(self):
+        apply_conandata_patches(self)
+        if Version(self.version) < "2.4.0":
+            libigl_cmake = os.path.join(self.source_folder, "cmake", "libigl.cmake")
+            replace_in_file(self, libigl_cmake, "-fPIC", "")
+            replace_in_file(self, libigl_cmake, "INTERFACE_POSITION_INDEPENDENT_CODE ON", "")
+
+    def build(self):
+        self._patch_sources()
+        cmake = CMake(self)
+        cmake.configure()
+        try:
+            cmake.build()
+        except ConanException:
+            # Workaround for C3I running out of memory during build
+            self.conf.define("tools.build:jobs", 1)
+            cmake.build()
+
+    def package(self):
+        cmake = CMake(self)
+        cmake.install()
+        # If components are built and packaged in the future, uncomment this line, their license is different
+        # copy(self, "LICENSE.GPL", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder)
+        copy(self, "LICENSE.MPL2", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder)
+
+        rmdir(self, os.path.join(self.package_folder, "share"))
+        rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
+        if not self.options.header_only:
+            rm(self, "*.c", self.package_folder, recursive=True)
+            rm(self, "*.cpp", self.package_folder, recursive=True)
+
+    def package_info(self):
+        self.cpp_info.set_property("cmake_file_name", "libigl")
+        self.cpp_info.set_property("cmake_target_name", "igl::igl")
+
+        self.cpp_info.components["common"].set_property("cmake_target_name", "igl::common")
+        self.cpp_info.components["common"].requires = ["eigen::eigen"]
+        if self.settings.os in ["Linux", "FreeBSD"]:
+            self.cpp_info.components["common"].system_libs = ["pthread"]
+
+        self.cpp_info.components["core"].set_property("cmake_target_name", "igl::core")
+        self.cpp_info.components["core"].requires = ["common"]
+        if not self.options.header_only:
+            self.cpp_info.components["core"].libs = ["igl"]
+            self.cpp_info.components["core"].defines.append("IGL_STATIC_LIBRARY")
+
+        # TODO: to remove in conan v2 once cmake_find_package_* generators removed
+        self.cpp_info.filenames["cmake_find_package"] = "libigl"
+        self.cpp_info.filenames["cmake_find_package_multi"] = "libigl"
+        self.cpp_info.names["cmake_find_package"] = "igl"
+        self.cpp_info.names["cmake_find_package_multi"] = "igl"


Test patch:
diff --git a/recipes/libigl/2.x.x/test_package/CMakeLists.txt b/recipes/libigl/all/test_package/CMakeLists.txt
similarity index 62%
rename from recipes/libigl/2.x.x/test_package/CMakeLists.txt
rename to recipes/libigl/all/test_package/CMakeLists.txt
--- a/recipes/libigl/2.x.x/test_package/CMakeLists.txt
+++ b/recipes/libigl/all/test_package/CMakeLists.txt
@@ -1,9 +1,6 @@
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.15)
 project(PackageTest CXX)
 
-include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
-conan_basic_setup(TARGETS)
-
 find_package(libigl REQUIRED CONFIG)
 
 add_executable(example example.cpp)
diff --git a/recipes/libigl/all/test_package/conanfile.py b/recipes/libigl/all/test_package/conanfile.py
new file mode 100644
--- /dev/null
+++ b/recipes/libigl/all/test_package/conanfile.py
@@ -0,0 +1,26 @@
+from conan import ConanFile
+from conan.tools.build import can_run
+from conan.tools.cmake import cmake_layout, CMake
+import os
+
+
+class TestPackageConan(ConanFile):
+    settings = "os", "arch", "compiler", "build_type"
+    generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
+    test_type = "explicit"
+
+    def requirements(self):
+        self.requires(self.tested_reference_str)
+
+    def layout(self):
+        cmake_layout(self)
+
+    def build(self):
+        cmake = CMake(self)
+        cmake.configure()
+        cmake.build()
+
+    def test(self):
+        if can_run(self):
+            bin_path = os.path.join(self.cpp.build.bindir, "example")
+            self.run(bin_path, env="conanrun")
diff --git a/recipes/libigl/2.x.x/test_package/example.cpp b/recipes/libigl/all/test_package/example.cpp
similarity index 100%
rename from recipes/libigl/2.x.x/test_package/example.cpp
rename to recipes/libigl/all/test_package/example.cpp
diff --git a/recipes/libigl/all/test_v1_package/CMakeLists.txt b/recipes/libigl/all/test_v1_package/CMakeLists.txt
new file mode 100644
--- /dev/null
+++ b/recipes/libigl/all/test_v1_package/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.15)
+project(test_package)
+
+include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
+conan_basic_setup(TARGETS)
+
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/
+                 ${CMAKE_CURRENT_BINARY_DIR}/test_package/)
diff --git a/recipes/libigl/2.x.x/test_package/conanfile.py b/recipes/libigl/all/test_v1_package/conanfile.py
similarity index 100%
rename from recipes/libigl/2.x.x/test_package/conanfile.py
rename to recipes/libigl/all/test_v1_package/conanfile.py