Repository: conan-io/conan-center-index

Issue:
(#13422) bump proj 9.1.0
Specify library name and version:  **lib/1.0**

This is also a good place to share with all of us **why you are submitting this PR** (specially if it is a new addition to ConanCenter): is it a dependency of other libraries you want to package? Are you the author of the library? Thanks!

---

- [x] I've read the [guidelines](https://github.com/conan-io/conan-center-index/blob/master/docs/how_to_add_packages.md) for contributing.
- [x] I've followed the [PEP8](https://www.python.org/dev/peps/pep-0008/) style guides for Python code in the recipes.
- [x] I've used the [latest](https://github.com/conan-io/conan/releases/latest) Conan client version.
- [ ] I've tried at least one configuration locally with the [conan-center hook](https://github.com/conan-io/hooks.git) activated.



Discussion:

Resolving patch:
diff --git a/recipes/proj/all/conanfile.py b/recipes/proj/all/conanfile.py
--- a/recipes/proj/all/conanfile.py
+++ b/recipes/proj/all/conanfile.py
@@ -1,14 +1,23 @@
-from conans import ConanFile, CMake, tools
+from conan import ConanFile
+from conan.tools.apple import is_apple_os
+from conans.tools import stdcpp_library
+from conan.tools.build import cross_building
+from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
+from conan.tools.env import VirtualBuildEnv, VirtualRunEnv
+from conan.tools.files import apply_conandata_patches, export_conandata_patches, get, copy, rmdir, replace_in_file, collect_libs, rm, rename
+from conan.tools.microsoft import is_msvc
+from conan.tools.scm import Version
 import os
 
-required_conan_version = ">=1.43.0"
+
+required_conan_version = ">=1.53.0"
 
 
 class ProjConan(ConanFile):
     name = "proj"
     description = "Cartographic Projections and Coordinate Transformations Library."
     license = "MIT"
-    topics = ("dsp", "proj", "proj4", "projections", "gis", "geospatial")
+    topics = "dsp", "proj", "proj4", "projections", "gis", "geospatial"
     homepage = "https://proj.org"
     url = "https://github.com/conan-io/conan-center-index"
 
@@ -30,162 +39,152 @@ class ProjConan(ConanFile):
         "build_executables": True,
     }
 
-    generators = "cmake", "cmake_find_package"
-    _cmake = None
-
-    @property
-    def _source_subfolder(self):
-        return "source_subfolder"
-
-    @property
-    def _is_msvc(self):
-        return str(self.settings.compiler) in ["Visual Studio", "msvc"]
-
-    @property
-    def _settings_build(self):
-        return getattr(self, "settings_build", self.settings)
-
     def export_sources(self):
-        self.copy("CMakeLists.txt")
-        for patch in self.conan_data.get("patches", {}).get(self.version, []):
-            self.copy(patch["patch_file"])
+        export_conandata_patches(self)
 
     def config_options(self):
         if self.settings.os == "Windows":
             del self.options.fPIC
-        if tools.Version(self.version) < "7.0.0":
+        if Version(self.version) < "7.0.0":
             del self.options.with_tiff
             del self.options.with_curl
 
     def configure(self):
         if self.options.shared:
-            del self.options.fPIC
+            self.options.rm_safe("fPIC")
+
+    def layout(self):
+        cmake_layout(self, src_folder="src")
 
     def requirements(self):
-        self.requires("nlohmann_json/3.10.5")
-        self.requires("sqlite3/3.38.5")
+        self.requires("nlohmann_json/3.11.2")
+        self.requires("sqlite3/3.40.0")
         if self.options.get_safe("with_tiff"):
-            self.requires("libtiff/4.3.0")
+            self.requires("libtiff/4.4.0")
         if self.options.get_safe("with_curl"):
-            self.requires("libcurl/7.83.1")
+            self.requires("libcurl/7.86.0")
 
     def build_requirements(self):
-        if hasattr(self, "settings_build"):
-            self.build_requires("sqlite3/3.38.5")
+        if hasattr(self, "settings_build") and cross_building(self):
+            self.tool_requires("sqlite3/3.40.0")
 
     def source(self):
-        tools.get(**self.conan_data["sources"][self.version],
-                  destination=self._source_subfolder, strip_root=True)
+        get(self, **self.conan_data["sources"][self.version], destination=self.source_folder, strip_root=True)
 
-    def build(self):
-        self._patch_sources()
-        # we should inject build env vars if 2 profile, here it's host env vars !
-        with tools.run_environment(self):
-            cmake = self._configure_cmake()
-            cmake.build()
+    def generate(self):
+        if hasattr(self, "settings_build") and cross_building(self):
+            env = VirtualBuildEnv(self)
+            env.generate()
+        else:
+            env = VirtualRunEnv(self)
+            env.generate(scope="build")
+
+        tc = CMakeToolchain(self)
+        tc.variables["USE_THREAD"] = self.options.threadsafe
+        tc.variables["BUILD_CCT"] = self.options.build_executables
+        tc.variables["BUILD_CS2CS"] = self.options.build_executables
+        tc.variables["BUILD_GEOD"] = self.options.build_executables
+        tc.variables["BUILD_GIE"] = self.options.build_executables
+        tc.variables["BUILD_PROJ"] = self.options.build_executables
+        tc.variables["BUILD_PROJINFO"] = self.options.build_executables
+        if Version(self.version) < "9.1.0":
+            tc.variables["PROJ_DATA_SUBDIR"] = "res"
+        if Version(self.version) < "7.0.0":
+            tc.variables["PROJ_TESTS"] = False
+            tc.variables["BUILD_LIBPROJ_SHARED"] = self.options.shared
+            tc.variables["ENABLE_LTO"] = False
+            tc.variables["JNI_SUPPORT"] = False
+        else:
+            tc.variables["ENABLE_TIFF"] = self.options.with_tiff
+            tc.variables["ENABLE_CURL"] = self.options.with_curl
+            tc.variables["BUILD_TESTING"] = False
+            tc.variables["ENABLE_IPO"] = False
+            tc.variables["BUILD_PROJSYNC"] = self.options.build_executables and self.options.with_curl
+        if Version(self.version) >= "8.1.0":
+            tc.variables["NLOHMANN_JSON_ORIGIN"] = "external"
+        tc.variables["CMAKE_MACOSX_BUNDLE"] = False
+        # Honor BUILD_SHARED_LIBS from conan_toolchain (see https://github.com/conan-io/conan/issues/11840)
+        tc.cache_variables["CMAKE_POLICY_DEFAULT_CMP0077"] = "NEW"
+        tc.generate()
+
+        deps = CMakeDeps(self)
+        deps.generate()
 
     def _patch_sources(self):
-        for patch in self.conan_data.get("patches", {}).get(self.version, []):
-            tools.patch(**patch)
+        apply_conandata_patches(self)
 
-        cmakelists = os.path.join(self._source_subfolder, "CMakeLists.txt")
-        tools.replace_in_file(cmakelists, "/W4", "")
+        cmakelists = os.path.join(self.source_folder, "CMakeLists.txt")
+        replace_in_file(self, cmakelists, "/W4", "")
+
+        # Fix up usage of SQLite3 finder outputs
+        rm(self, "FindSqlite3.cmake", os.path.join(self.source_folder, "cmake"))
+        replace_in_file(self, cmakelists, "SQLITE3_FOUND", "SQLite3_FOUND")
+        replace_in_file(self, cmakelists, "SQLITE3_VERSION", "SQLite3_VERSION")
+        replace_in_file(self, cmakelists, "find_package(Sqlite3 REQUIRED)", "find_package(SQLite3 REQUIRED)")
 
         # Let CMake install shared lib with a clean rpath !
-        if tools.Version(self.version) >= "7.1.0" and tools.Version(self.version) < "9.0.0":
-            tools.replace_in_file(cmakelists,
+        if Version(self.version) >= "7.1.0" and Version(self.version) < "9.0.0":
+            replace_in_file(self, cmakelists,
                                   "set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)",
                                   "")
 
-        # Trick to find sqlite3 executable for build machine
-        # TODO: shouldn't be necessary in conan v2 with VirtualBuildEnv?
-        sqlite3_exe = " ".join("\"{}\"".format(path.replace("\\", "/")) for path in self.deps_env_info["sqlite3"].PATH)
-        tools.replace_in_file(
-            cmakelists,
-            "find_program(EXE_SQLITE3 sqlite3)",
-            "find_program(EXE_SQLITE3 sqlite3 PATHS {} NO_DEFAULT_PATH)".format(sqlite3_exe),
-        )
-
-        # Agressive workaround against SIP on macOS, to handle sqlite3 executable
+        # Aggressive workaround against SIP on macOS, to handle sqlite3 executable
         # linked to shared sqlite3 lib
-        if tools.is_apple_os(self._settings_build.os):
-            # TODO: no hope for 2 profiles, wait for stable self.dependencies
-            #       because we want absolute lib paths of build profile actually
-            if not hasattr(self, "settings_build"):
-                if tools.Version(self.version) < "8.1.0":
-                    cmake_sqlite_call = "CMakeLists.txt"
-                    pattern = "${EXE_SQLITE3}"
-                else:
-                    cmake_sqlite_call = "generate_proj_db.cmake"
-                    pattern = "\"${EXE_SQLITE3}\""
-                lib_paths = self.deps_cpp_info["sqlite3"].lib_paths
-                tools.replace_in_file(
-                    os.path.join(self._source_subfolder, "data", cmake_sqlite_call),
-                    "COMMAND {}".format(pattern),
-                    "COMMAND ${{CMAKE_COMMAND}} -E env \"DYLD_LIBRARY_PATH={}\" {}".format(
-                        ":".join(lib_paths), pattern
-                    ),
-                )
+        if is_apple_os(self):
+            if Version(self.version) < "8.1.0":
+                cmake_sqlite_call = "CMakeLists.txt"
+                pattern = "${EXE_SQLITE3}"
+            else:
+                cmake_sqlite_call = "generate_proj_db.cmake"
+                pattern = "\"${EXE_SQLITE3}\""
+            if hasattr(self, "settings_build") and cross_building(self):
+                lib_paths = self.dependencies.build["sqlite3"].cpp_info.libdirs
+            else:
+                lib_paths = self.dependencies["sqlite3"].cpp_info.libdirs
+            replace_in_file(self,
+                os.path.join(self.source_folder, "data", cmake_sqlite_call),
+                f"COMMAND {pattern}",
+                f"COMMAND ${{CMAKE_COMMAND}} -E env \"DYLD_LIBRARY_PATH={':'.join(lib_paths)}\" {pattern}"
+            )
 
         # unvendor nlohmann_json
-        if tools.Version(self.version) < "8.1.0":
-            tools.rmdir(os.path.join(self._source_subfolder, "include", "proj", "internal", "nlohmann"))
-
-    def _configure_cmake(self):
-        if self._cmake:
-            return self._cmake
-        self._cmake = CMake(self)
-        self._cmake.definitions["USE_THREAD"] = self.options.threadsafe
-        self._cmake.definitions["BUILD_CCT"] = self.options.build_executables
-        self._cmake.definitions["BUILD_CS2CS"] = self.options.build_executables
-        self._cmake.definitions["BUILD_GEOD"] = self.options.build_executables
-        self._cmake.definitions["BUILD_GIE"] = self.options.build_executables
-        self._cmake.definitions["BUILD_PROJ"] = self.options.build_executables
-        self._cmake.definitions["BUILD_PROJINFO"] = self.options.build_executables
-        self._cmake.definitions["PROJ_DATA_SUBDIR"] = "res"
-        if tools.Version(self.version) < "7.0.0":
-            self._cmake.definitions["PROJ_TESTS"] = False
-            self._cmake.definitions["BUILD_LIBPROJ_SHARED"] = self.options.shared
-            self._cmake.definitions["ENABLE_LTO"] = False
-            self._cmake.definitions["JNI_SUPPORT"] = False
-        else:
-            self._cmake.definitions["ENABLE_TIFF"] = self.options.with_tiff
-            self._cmake.definitions["ENABLE_CURL"] = self.options.with_curl
-            self._cmake.definitions["BUILD_TESTING"] = False
-            self._cmake.definitions["ENABLE_IPO"] = False
-            self._cmake.definitions["BUILD_PROJSYNC"] = self.options.build_executables and self.options.with_curl
-        if tools.Version(self.version) >= "8.1.0":
-            self._cmake.definitions["NLOHMANN_JSON_ORIGIN"] = "external"
-        self._cmake.definitions["CMAKE_MACOSX_BUNDLE"] = False
-        self._cmake.configure()
-        return self._cmake
+        if Version(self.version) < "8.1.0":
+            rmdir(self, os.path.join(self.source_folder, "include", "proj", "internal", "nlohmann"))
+
+    def build(self):
+        self._patch_sources()
+        cmake = CMake(self)
+        cmake.configure()
+        cmake.build()
 
     def package(self):
-        self.copy("COPYING", dst="licenses", src=self._source_subfolder)
-        cmake = self._configure_cmake()
+        copy(self, "COPYING", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder)
+        cmake = CMake(self)
         cmake.install()
-        tools.rmdir(os.path.join(self.package_folder, "share"))
-        tools.rmdir(os.path.join(self.package_folder, "lib", "cmake"))
-        tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig"))
+        # recover the data ... 9.1.0 saves into share/proj rather than res directly
+        # the new PROJ_DATA_PATH can't seem to be controlled from conan.
+        if Version(self.version) >= "9.1.0":
+            rename(self, src=os.path.join(self.package_folder, "share", "proj"), dst=os.path.join(self.package_folder, "res"))
+        # delete the rest of the deployed data
+        rmdir(self, os.path.join(self.package_folder, "share"))
+        rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
+        rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
+
 
     def package_info(self):
-        proj_version = tools.Version(self.version)
+        proj_version = Version(self.version)
         cmake_config_filename = "proj" if proj_version >= "7.0.0" else "proj4"
         cmake_namespace = "PROJ" if proj_version >= "7.0.0" else "PROJ4"
         self.cpp_info.set_property("cmake_file_name", cmake_config_filename)
-        self.cpp_info.set_property("cmake_target_name", "{}::proj".format(cmake_namespace))
+        self.cpp_info.set_property("cmake_target_name", f"{cmake_namespace}::proj")
         self.cpp_info.set_property("pkg_config_name", "proj")
-        self.cpp_info.components["projlib"].set_property("cmake_target_name", "{}::proj".format(cmake_namespace))
+        self.cpp_info.components["projlib"].set_property("cmake_target_name", f"{cmake_namespace}::proj")
         self.cpp_info.components["projlib"].set_property("pkg_config_name", "proj")
 
         self.cpp_info.filenames["cmake_find_package"] = cmake_config_filename
         self.cpp_info.filenames["cmake_find_package_multi"] = cmake_config_filename
-        self.cpp_info.names["cmake_find_package"] = cmake_namespace
-        self.cpp_info.names["cmake_find_package_multi"] = cmake_namespace
-        self.cpp_info.components["projlib"].names["cmake_find_package"] = "proj"
-        self.cpp_info.components["projlib"].names["cmake_find_package_multi"] = "proj"
 
-        self.cpp_info.components["projlib"].libs = tools.collect_libs(self)
+        self.cpp_info.components["projlib"].libs = collect_libs(self)
         if self.settings.os in ["Linux", "FreeBSD"]:
             self.cpp_info.components["projlib"].system_libs.append("m")
             if self.options.threadsafe:
@@ -195,28 +194,35 @@ def package_info(self):
                 self.cpp_info.components["projlib"].system_libs.append("shell32")
             if proj_version >= "7.1.0":
                 self.cpp_info.components["projlib"].system_libs.append("Ole32")
-        if not self.options.shared and tools.stdcpp_library(self):
-            self.cpp_info.components["projlib"].system_libs.append(tools.stdcpp_library(self))
+        if not self.options.shared and stdcpp_library(self):
+            self.cpp_info.components["projlib"].system_libs.append(stdcpp_library(self))
         self.cpp_info.components["projlib"].requires.extend(["nlohmann_json::nlohmann_json", "sqlite3::sqlite3"])
         if self.options.get_safe("with_tiff"):
             self.cpp_info.components["projlib"].requires.append("libtiff::libtiff")
         if self.options.get_safe("with_curl"):
             self.cpp_info.components["projlib"].requires.append("libcurl::libcurl")
-        if tools.Version(self.version) < "8.2.0":
-            if self.options.shared and self._is_msvc:
+        if Version(self.version) < "8.2.0":
+            if self.options.shared and is_msvc(self):
                 self.cpp_info.components["projlib"].defines.append("PROJ_MSVC_DLL_IMPORT")
         else:
             if not self.options.shared:
                 self.cpp_info.components["projlib"].defines.append("PROJ_DLL=")
 
         res_path = os.path.join(self.package_folder, "res")
-        self.output.info("Prepending to PROJ_LIB environment variable: {}".format(res_path))
+        self.output.info(f"Prepending to PROJ_LIB environment variable: {res_path}")
         self.runenv_info.prepend_path("PROJ_LIB", res_path)
+
         # TODO: to remove after conan v2, it allows to not break consumers still relying on virtualenv generator
         self.env_info.PROJ_LIB = res_path
 
         if self.options.build_executables:
             self.buildenv_info.prepend_path("PROJ_LIB", res_path)
             bin_path = os.path.join(self.package_folder, "bin")
-            self.output.info("Appending PATH environment variable: {}".format(bin_path))
+            self.output.info(f"Appending PATH environment variable: {bin_path}")
             self.env_info.PATH.append(bin_path)
+
+        # TODO: to remove in conan v2 once cmake_find_package_* generators removed
+        self.cpp_info.names["cmake_find_package"] = cmake_namespace
+        self.cpp_info.names["cmake_find_package_multi"] = cmake_namespace
+        self.cpp_info.components["projlib"].names["cmake_find_package"] = "proj"
+        self.cpp_info.components["projlib"].names["cmake_find_package_multi"] = "proj"


Test patch:
diff --git a/recipes/proj/all/test_package/CMakeLists.txt b/recipes/proj/all/test_package/CMakeLists.txt
--- a/recipes/proj/all/test_package/CMakeLists.txt
+++ b/recipes/proj/all/test_package/CMakeLists.txt
@@ -1,14 +1,11 @@
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.8)
 project(test_package C)
 
-include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
-conan_basic_setup(TARGETS)
-
 add_executable(test_package test_package.c)
 if(PROJ_VERSION_GE_7)
   find_package(proj REQUIRED CONFIG)
-  target_link_libraries(test_package PROJ::proj)
+  target_link_libraries(test_package PRIVATE PROJ::proj)
 else()
   find_package(proj4 REQUIRED CONFIG)
-  target_link_libraries(test_package PROJ4::proj)
+  target_link_libraries(test_package PRIVATE PROJ4::proj)
 endif()
diff --git a/recipes/proj/all/test_package/conanfile.py b/recipes/proj/all/test_package/conanfile.py
--- a/recipes/proj/all/test_package/conanfile.py
+++ b/recipes/proj/all/test_package/conanfile.py
@@ -1,27 +1,32 @@
-from conans import ConanFile, CMake, tools
+from conan import ConanFile
+from conan.tools.build import can_run
+from conan.tools.cmake import cmake_layout, CMake, CMakeToolchain
+from conan.tools.scm import Version
 import os
 
 
 class TestPackageConan(ConanFile):
     settings = "os", "arch", "compiler", "build_type"
-    generators = "cmake", "cmake_find_package_multi"
+    generators = "CMakeDeps", "VirtualRunEnv"
+    test_type = "explicit"
 
-    def build_requirements(self):
-        if self.settings.os == "Macos" and self.settings.arch == "armv8":
-            # Workaround for CMake bug with error message:
-            # Attempting to use @rpath without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being
-            # set. This could be because you are using a Mac OS X version less than 10.5
-            # or because CMake's platform configuration is corrupt.
-            # FIXME: Remove once CMake on macOS/M1 CI runners is upgraded.
-            self.build_requires("cmake/3.22.0")
+    def requirements(self):
+        self.requires(self.tested_reference_str)
+
+    def layout(self):
+        cmake_layout(self)
+
+    def generate(self):
+        tc = CMakeToolchain(self)
+        tc.variables["PROJ_VERSION_GE_7"] = Version(self.dependencies["proj"].ref.version) >= "7.0.0"
+        tc.generate()
 
     def build(self):
         cmake = CMake(self)
-        cmake.definitions["PROJ_VERSION_GE_7"] = tools.Version(self.deps_cpp_info["proj"].version) >= "7.0.0"
         cmake.configure()
         cmake.build()
 
     def test(self):
-        if not tools.cross_building(self):
-            bin_path = os.path.join("bin", "test_package")
-            self.run(bin_path, run_environment=True)
+        if can_run(self):
+            bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
+            self.run(bin_path, env="conanrun")
diff --git a/recipes/proj/all/test_v1_package/CMakeLists.txt b/recipes/proj/all/test_v1_package/CMakeLists.txt
new file mode 100644
--- /dev/null
+++ b/recipes/proj/all/test_v1_package/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.1)
+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/proj/all/test_v1_package/conanfile.py b/recipes/proj/all/test_v1_package/conanfile.py
new file mode 100644
--- /dev/null
+++ b/recipes/proj/all/test_v1_package/conanfile.py
@@ -0,0 +1,18 @@
+from conans import ConanFile, CMake, tools
+import os
+
+
+class TestPackageConan(ConanFile):
+    settings = "os", "arch", "compiler", "build_type"
+    generators = "cmake", "cmake_find_package_multi"
+
+    def build(self):
+        cmake = CMake(self)
+        cmake.definitions["PROJ_VERSION_GE_7"] = tools.Version(self.deps_cpp_info["proj"].version) >= "7.0.0"
+        cmake.configure()
+        cmake.build()
+
+    def test(self):
+        if not tools.cross_building(self):
+            bin_path = os.path.join("bin", "test_package")
+            self.run(bin_path, run_environment=True)