Repository: conan-io/conan-center-index

Issue:
[package] ncurses/6.4: Seems to not be conan2 compatible
### Description

Was told this package may not have been updated to conan/2 as i was updating my own project

### Package and Environment Details

* Package Name/Version: **ncurses/6.4**
* Operating System+version: **Linux Ubuntu 20.04 (win10 wsl2)**
* Compiler+version: **GCC 9.4**
* Conan version: **conan 2.0.10**
* Python version: **Python 3.8.10**


### Conan profile

Host profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=9
os=Linux

Build profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=9
os=Linux

### Steps to reproduce
git  clone https://github.com/benny-edlund/task-pool/
cd task-pool/examples
git checkout conan_examples_update
conan install . --output-folder=build --build=missing --settings=build_type=Release

### Logs

<details><summary>Click to expand log</summary>

```
*********************************************************
Recipe 'ncurses/6.3' seems broken.
It is possible that this recipe is not Conan 2.0 ready
If the recipe comes from ConanCenter, report it at https://github.com/conan-io/conan-center-index/issues
If it is your recipe, check if it is updated to 2.0
*********************************************************

ERROR: Package 'ncurses/6.3' not resolved: ncurses/6.3: Cannot load recipe.
Error loading conanfile at '/home/benny/.conan2/p/ncurse90fb70e239f8/e/conanfile.py': Unable to load conanfile in /home/benny/.conan2/p/ncurse90fb70e239f8/e/conanfile.py
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/benny/.conan2/p/ncurse90fb70e239f8/e/conanfile.py", line 1, in <module>
    from conans import AutoToolsBuildEnvironment, ConanFile, tools
ImportError: cannot import name 'AutoToolsBuildEnvironment' from 'conans' (/home/benny/.local/lib/python3.8/site-packages/conans/__init__.py)```

</details>



Discussion:
There are 2 PRs: https://github.com/conan-io/conan-center-index/pull/17805 & https://github.com/conan-io/conan-center-index/pull/18568

Resolving patch:
diff --git a/recipes/ncurses/all/conanfile.py b/recipes/ncurses/all/conanfile.py
--- a/recipes/ncurses/all/conanfile.py
+++ b/recipes/ncurses/all/conanfile.py
@@ -1,21 +1,29 @@
-from conans import AutoToolsBuildEnvironment, ConanFile, tools
-from conans.errors import ConanInvalidConfiguration
-import contextlib
-import functools
 import os
-import textwrap
 
-required_conan_version = ">=1.33.0"
+from conan import ConanFile
+from conan.errors import ConanInvalidConfiguration
+from conan.tools.apple import fix_apple_shared_install_name
+from conan.tools.build import cross_building, stdcpp_library
+from conan.tools.env import Environment
+from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get
+from conan.tools.gnu import Autotools, AutotoolsToolchain, PkgConfigDeps
+from conan.tools.layout import basic_layout
+from conan.tools.microsoft import is_msvc, is_msvc_static_runtime, unix_path
+from conan.tools.scm import Version
+
+required_conan_version = ">=1.53.0"
 
 
 class NCursesConan(ConanFile):
     name = "ncurses"
     description = "The ncurses (new curses) library is a free software emulation of curses in System V Release 4.0 (SVr4), and more"
-    topics = ("ncurses", "terminal", "screen", "tui")
+    license = "X11"
     url = "https://github.com/conan-io/conan-center-index"
     homepage = "https://www.gnu.org/software/ncurses"
-    license = "X11"
-    settings = "os", "compiler", "build_type", "arch"
+    topics = ("terminal", "screen", "tui")
+
+    package_type = "library"
+    settings = "os", "arch", "compiler", "build_type"
     options = {
         "shared": [True, False],
         "fPIC": [True, False],
@@ -41,90 +49,85 @@ class NCursesConan(ConanFile):
         "with_pcre2": False,
     }
 
-    generators = "pkg_config"
-    exports_sources = "patches/*"
-
-    @property
-    def _source_subfolder(self):
-        return "source_subfolder"
-
     @property
     def _settings_build(self):
         return getattr(self, "settings_build", self.settings)
 
     @property
-    def _with_ticlib(self):
-        if self.options.with_ticlib == "auto":
-            return self.settings.os != "Windows"
-        else:
-            return self.options.with_ticlib
+    def _is_mingw(self):
+        return self.settings.os == "Windows" and self.settings.compiler == "gcc"
 
-    @property
-    def _with_tinfo(self):
-        if self.options.with_tinfo == "auto":
-            return self.settings.os != "Windows"
-        else:
-            return self.options.with_tinfo
+    def export_sources(self):
+        export_conandata_patches(self)
+        copy(self, "*.cmake", src=self.recipe_folder, dst=self.export_sources_folder)
 
     def config_options(self):
         if self.settings.os == "Windows":
             del self.options.fPIC
+        # Set the default value based on OS
+        self.options.with_ticlib = self.settings.os != "Windows"
+        self.options.with_tinfo = self.settings.os != "Windows"
 
     def configure(self):
         if self.options.shared:
-            del self.options.fPIC
+            self.options.rm_safe("fPIC")
         if not self.options.with_cxx:
-            del self.settings.compiler.libcxx
-            del self.settings.compiler.cppstd
+            self.settings.rm_safe("compiler.libcxx")
+            self.settings.rm_safe("compiler.cppstd")
         if not self.options.with_widec:
-            del self.options.with_extended_colors
+            self.options.rm_safe("with_extended_colors")
+
+    def layout(self):
+        basic_layout(self, src_folder="src")
 
     def requirements(self):
         if self.options.with_pcre2:
-            self.requires("pcre2/10.37")
-        if self.settings.compiler == "Visual Studio":
+            self.requires("pcre2/10.42")
+        if is_msvc(self):
             self.requires("getopt-for-visual-studio/20200201")
-            self.requires("dirent/1.23.2")
-            if self.options.get_safe("with_extended_colors", False):
+            self.requires("dirent/1.24")
+            if self.options.get_safe("with_extended_colors"):
                 self.requires("naive-tsearch/0.1.1")
 
-    def build_requirements(self):
-        if self._settings_build.os == "Windows" and not tools.get_env("CONAN_BASH_PATH"):
-            self.build_requires("msys2/cci.latest")
-
     def validate(self):
-        if any("arm" in arch for arch in (self.settings.arch, self._settings_build.arch)) and tools.cross_building(self):
+        if cross_building(self) and ("arm" in str(self.settings.arch) or "arm" in str(self._settings_build.arch)):
             # FIXME: Cannot build ncurses from x86_64 to armv8 (Apple M1).  Cross building from Linux/x86_64 to Mingw/x86_64 works flawless.
             # FIXME: Need access to environment of build profile to set build compiler (BUILD_CC/CC_FOR_BUILD)
             raise ConanInvalidConfiguration("Cross building to/from arm is (currently) not supported")
-        if self.options.shared and self.settings.compiler == "Visual Studio" and "MT" in self.settings.compiler.runtime:
+        if self.options.shared and is_msvc_static_runtime(self):
             raise ConanInvalidConfiguration("Cannot build shared libraries with static (MT) runtime")
         if self.settings.os == "Windows":
-            if self._with_tinfo:
+            if self.options.with_tinfo:
                 raise ConanInvalidConfiguration("terminfo cannot be built on Windows because it requires a term driver")
-            if self.options.shared and self._with_ticlib:
+            if self.options.shared and self.options.with_ticlib:
                 raise ConanInvalidConfiguration("ticlib cannot be built separately as a shared library on Windows")
 
+    def build_requirements(self):
+        if self._settings_build.os == "Windows":
+            self.win_bash = True
+            if not self.conf.get("tools.microsoft.bash:path", check_type=str):
+                self.tool_requires("msys2/cci.latest")
+        if not self.conf.get("tools.gnu:pkg_config", default=False, check_type=str):
+            self.tool_requires("pkgconf/2.0.3")
+
     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], strip_root=True)
 
-    @functools.lru_cache(1)
-    def _configure_autotools(self):
-        autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows)
+    def generate(self):
+        tc = AutotoolsToolchain(self)
         yes_no = lambda v: "yes" if v else "no"
-        conf_args = [
+        tc.configure_args += [
             "--with-shared={}".format(yes_no(self.options.shared)),
             "--with-cxx-shared={}".format(yes_no(self.options.shared)),
             "--with-normal={}".format(yes_no(not self.options.shared)),
             "--enable-widec={}".format(yes_no(self.options.with_widec)),
-            "--enable-ext-colors={}".format(yes_no(self.options.get_safe("with_extended_colors", False))),
+            "--enable-ext-colors={}".format(yes_no(self.options.get_safe("with_extended_colors"))),
             "--enable-reentrant={}".format(yes_no(self.options.with_reentrant)),
             "--with-pcre2={}".format(yes_no(self.options.with_pcre2)),
             "--with-cxx-binding={}".format(yes_no(self.options.with_cxx)),
             "--with-progs={}".format(yes_no(self.options.with_progs)),
-            "--with-termlib={}".format(yes_no(self._with_tinfo)),
-            "--with-ticlib={}".format(yes_no(self._with_ticlib)),
+            "--with-termlib={}".format(yes_no(self.options.with_tinfo)),
+            "--with-ticlib={}".format(yes_no(self.options.with_ticlib)),
             "--without-libtool",
             "--without-ada",
             "--without-manpages",
@@ -134,108 +137,118 @@ def _configure_autotools(self):
             "--without-profile",
             "--with-sp-funcs",
             "--disable-rpath",
-            "--datarootdir={}".format(tools.unix_path(os.path.join(self.package_folder, "res"))),
             "--disable-pc-files",
+            "--datarootdir=${prefix}/res",
         ]
         build = None
         host = None
         if self.settings.os == "Windows":
-            conf_args.extend([
+            tc.configure_args += [
                 "--disable-macros",
                 "--disable-termcap",
                 "--enable-database",
                 "--enable-sp-funcs",
                 "--enable-term-driver",
                 "--enable-interop",
-            ])
-        if self.settings.compiler == "Visual Studio":
-            build = host = "{}-w64-mingw32-msvc".format(self.settings.arch)
-            conf_args.extend([
+            ]
+        if is_msvc(self):
+            build = host = f"{self.settings.arch}-w64-mingw32-msvc"
+            tc.configure_args += [
                 "ac_cv_func_getopt=yes",
                 "ac_cv_func_setvbuf_reversed=no",
-            ])
-            autotools.cxx_flags.append("-EHsc")
-            if tools.Version(self.settings.compiler.version) >= 12:
-                autotools.flags.append("-FS")
-        if (self.settings.os, self.settings.compiler) == ("Windows", "gcc"):
+            ]
+            # The env vars below are used by ./configure, but not during make
+            tc.make_args += [
+                "CC=cl -nologo",
+                "CPP=cl -nologo -E",
+            ]
+            tc.extra_cflags.append("-FS")
+            tc.extra_cxxflags.append("-FS")
+            tc.extra_cxxflags.append("-EHsc")
+            if self.options.get_safe("with_extended_colors"):
+                tc.extra_cflags.append(" ".join(f"-I{dir}" for dir in self.dependencies["naive-tsearch"].cpp_info.includedirs))
+                tc.extra_ldflags.append(" ".join(f"-l{lib}" for lib in self.dependencies["naive-tsearch"].cpp_info.libs))
+        if self._is_mingw:
             # add libssp (gcc support library) for some missing symbols (e.g. __strcpy_chk)
-            autotools.libs.extend(["mingwex", "ssp"])
+            tc.extra_ldflags.extend(["-lmingwex", "-lssp"])
         if build:
-            conf_args.append(f"ac_cv_build={build}")
+            tc.configure_args.append(f"ac_cv_build={build}")
         if host:
-            conf_args.append(f"ac_cv_host={host}")
-            conf_args.append(f"ac_cv_target={host}")
-        autotools.configure(args=conf_args, configure_dir=self._source_subfolder, host=host, build=build)
-        return autotools
-
-    def _patch_sources(self):
-        for patch in self.conan_data.get("patches", {}).get(self.version, []):
-            tools.patch(**patch)
-
-    @contextlib.contextmanager
-    def _build_context(self):
-        if self.settings.compiler == "Visual Studio":
-            with tools.vcvars(self):
-                env = {
-                    "CC": "cl -nologo",
-                    "CXX": "cl -nologo",
-                    "LD": "link -nologo",
-                    "LDFLAGS": "",
-                    "NM": "dumpbin -symbols",
-                    "STRIP": ":",
-                    "AR": "lib -nologo",
-                    "RANLIB": ":",
-                }
-                with tools.environment_append(env):
-                    yield
-        else:
-            yield
+            tc.configure_args.append(f"ac_cv_host={host}")
+            tc.configure_args.append(f"ac_cv_target={host}")
+        # Allow ncurses to set the include dir with an appropriate subdir
+        tc.configure_args.remove("--includedir=${prefix}/include")
+        tc.generate()
+
+        if is_msvc(self):
+            env = Environment()
+            env.define("CC", "cl -nologo -FS")
+            env.define("CXX", "cl -nologo -FS")
+            env.define("LD", "link")
+            env.define("AR", "lib")
+            env.define("NM", "dumpbin -symbols")
+            env.define("OBJDUMP", ":")
+            env.define("RANLIB", ":")
+            env.define("STRIP", ":")
+            env.vars(self).save_script("conanbuild_msvc")
+
+        if is_msvc(self):
+            # Custom AutotoolsDeps for cl like compilers
+            # workaround for https://github.com/conan-io/conan/issues/12784
+            includedirs = []
+            defines = []
+            libs = []
+            libdirs = []
+            linkflags = []
+            cxxflags = []
+            cflags = []
+            for dependency in self.dependencies.values():
+                deps_cpp_info = dependency.cpp_info.aggregated_components()
+                includedirs.extend(deps_cpp_info.includedirs)
+                defines.extend(deps_cpp_info.defines)
+                libs.extend(deps_cpp_info.libs + deps_cpp_info.system_libs)
+                libdirs.extend(deps_cpp_info.libdirs)
+                linkflags.extend(deps_cpp_info.sharedlinkflags + deps_cpp_info.exelinkflags)
+                cxxflags.extend(deps_cpp_info.cxxflags)
+                cflags.extend(deps_cpp_info.cflags)
+            env = Environment()
+            env.append("CPPFLAGS", [f"-I{unix_path(self, p)}" for p in includedirs] + [f"-D{d}" for d in defines])
+            env.append("_LINK_", [lib if lib.endswith(".lib") else f"{lib}.lib" for lib in libs])
+            env.append("LDFLAGS", [f"-L{unix_path(self, p)}" for p in libdirs] + linkflags)
+            env.append("CXXFLAGS", cxxflags)
+            env.append("CFLAGS", cflags)
+            env.vars(self).save_script("conanautotoolsdeps_cl_workaround")
+
+        deps = PkgConfigDeps(self)
+        deps.generate()
 
     def build(self):
-        self._patch_sources()
-        with self._build_context():
-            autotools = self._configure_autotools()
-            autotools.make()
+        apply_conandata_patches(self)
+        autotools = Autotools(self)
+        autotools.configure()
+        autotools.make()
 
     @property
     def _major_version(self):
-        return tools.Version(self.version).major
-
-    @staticmethod
-    def _create_cmake_module_alias_targets(module_file):
-        tools.save(module_file, textwrap.dedent("""\
-            set(CURSES_FOUND ON)
-            set(CURSES_INCLUDE_DIRS ${ncurses_libcurses_INCLUDE_DIRS})
-            set(CURSES_LIBRARIES ${ncurses_libcurses_LINK_LIBS})
-            set(CURSES_CFLAGS ${ncurses_DEFINITIONS} ${ncurses_COMPILE_OPTIONS_C})
-            set(CURSES_HAVE_CURSES_H OFF)
-            set(CURSES_HAVE_NCURSES_H OFF)
-            if(CURSES_NEED_NCURSES)
-                set(CURSES_HAVE_NCURSES_CURSES_H ON)
-                set(CURSES_HAVE_NCURSES_NCURSES_H ON)
-            endif()
-
-            # Backward Compatibility
-            set(CURSES_INCLUDE_DIR ${CURSES_INCLUDE_DIRS})
-            set(CURSES_LIBRARY ${CURSES_LIBRARIES})
-        """))
+        return Version(self.version).major
 
     def package(self):
-        # return
-        self.copy("COPYING", src=self._source_subfolder, dst="licenses")
-        with self._build_context():
-            autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows)
-            autotools.install()
-
-            os.unlink(os.path.join(self.package_folder, "bin", "ncurses{}{}-config".format(self._suffix, self._major_version)))
-
-        self._create_cmake_module_alias_targets(os.path.join(self.package_folder, self._module_subfolder, self._module_file))
+        copy(self, "COPYING", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
+        autotools = Autotools(self)
+        autotools.install()
+        os.unlink(os.path.join(self.package_folder, "bin", f"ncurses{self._suffix}{self._major_version}-config"))
+        copy(self, "*.cmake",
+             src=os.path.join(self.export_sources_folder, "cmake"),
+             dst=os.path.join(self.package_folder, self._module_subfolder))
+        fix_apple_shared_install_name(self)
 
     @property
     def _suffix(self):
         res = ""
+        # https://github.com/mirror/ncurses/blob/v6.4/configure.in#L1393
         if self.options.with_reentrant:
             res += "t"
+        # https://github.com/mirror/ncurses/blob/v6.4/configure.in#L959
         if self.options.with_widec:
             res += "w"
         return res
@@ -248,80 +261,80 @@ def _lib_suffix(self):
                 res += ".dll"
         return res
 
-    def package_id(self):
-        self.info.options.with_ticlib = self._with_ticlib
-        self.info.options.with_tinfo = self._with_tinfo
-
     @property
     def _module_subfolder(self):
         return os.path.join("lib", "cmake")
 
     @property
     def _module_file(self):
-        return "conan-official-{}-targets.cmake".format(self.name)
+        return f"conan-official-{self.name}-targets.cmake"
 
     def package_info(self):
-        self.cpp_info.filenames["cmake_find_package"] = "Curses"
-        self.cpp_info.filenames["cmake_find_package_multi"] = "Curses"
-        if self._with_tinfo:
-            self.cpp_info.components["tinfo"].libs = ["tinfo" + self._lib_suffix]
-            self.cpp_info.components["tinfo"].names["pkg_config"] = "tinfo" + self._lib_suffix
-            self.cpp_info.components["tinfo"].includedirs.append(os.path.join("include", "ncurses" + self._suffix))
-
-        self.cpp_info.components["libcurses"].libs = ["ncurses" + self._lib_suffix]
-        self.cpp_info.components["libcurses"].names["pkg_config"] = "ncurses" + self._lib_suffix
-        self.cpp_info.components["libcurses"].includedirs.append(os.path.join("include", "ncurses" + self._suffix))
-        if not self.options.shared:
-            self.cpp_info.components["libcurses"].defines = ["NCURSES_STATIC"]
-            if self.settings.os == "Linux":
-                self.cpp_info.components["libcurses"].system_libs = ["dl", "m"]
-        if self._with_tinfo:
-            self.cpp_info.components["libcurses"].requires.append("tinfo")
+        self.cpp_info.set_property("cmake_find_mode", "both")
+        self.cpp_info.set_property("cmake_file_name", "Curses")
 
-        if self.settings.compiler == "Visual Studio":
-            self.cpp_info.components["libcurses"].requires.extend([
-                "getopt-for-visual-studio::getopt-for-visual-studio",
-                "dirent::dirent",
-            ])
-            if self.options.get_safe("with_extended_colors", False):
-                self.cpp_info.components["libcurses"].requires.append("naive-tsearch::naive-tsearch")
+        # CMake's standard FindCurses module does not define a target.
+        # Adding one nevertheless for consistency with other packages.
+        # https://gitlab.kitware.com/cmake/cmake/-/issues/23051
+        self.cpp_info.set_property("cmake_target_name", "Curses::Curses")
 
-        module_rel_path = os.path.join(self._module_subfolder, self._module_file)
-        self.cpp_info.components["libcurses"].builddirs.append(self._module_subfolder)
-        self.cpp_info.components["libcurses"].build_modules["cmake_find_package"] = [module_rel_path]
-        self.cpp_info.components["libcurses"].build_modules["cmake_find_package_multi"] = [module_rel_path]
+        def _add_component(name, lib_name=None, requires=None):
+            lib_name = lib_name or name
+            self.cpp_info.components[name].libs = [lib_name + self._lib_suffix]
+            self.cpp_info.components[name].set_property("pkg_config_name", lib_name + self._lib_suffix)
+            self.cpp_info.components[name].includedirs.append(os.path.join("include", "ncurses" + self._suffix))
+            self.cpp_info.components[name].requires = requires if requires else []
 
-        self.cpp_info.components["panel"].libs = ["panel" + self._lib_suffix]
-        self.cpp_info.components["panel"].names["pkg_config"] = "panel" + self._lib_suffix
-        self.cpp_info.components["panel"].requires = ["libcurses"]
+        _add_component("libcurses", lib_name="ncurses")
+        _add_component("panel", requires=["libcurses"])
+        _add_component("menu", requires=["libcurses"])
+        _add_component("form", requires=["libcurses"])
 
-        self.cpp_info.components["menu"].libs = ["menu" + self._lib_suffix]
-        self.cpp_info.components["menu"].names["pkg_config"] = "menu" + self._lib_suffix
-        self.cpp_info.components["menu"].requires = ["libcurses"]
+        if self.options.with_tinfo:
+            _add_component("tinfo")
+            self.cpp_info.components["libcurses"].requires += ["tinfo"]
 
-        self.cpp_info.components["form"].libs = ["form" + self._lib_suffix]
-        self.cpp_info.components["form"].names["pkg_config"] = "form" + self._lib_suffix
-        self.cpp_info.components["form"].requires = ["libcurses"]
-        if self.options.with_pcre2:
-            self.cpp_info.components["form"].requires.append("pcre2::pcre2")
+        if self.options.with_ticlib:
+            _add_component("ticlib", lib_name="tic", requires=["libcurses"])
 
         if self.options.with_cxx:
-            self.cpp_info.components["curses++"].libs = ["ncurses++" + self._lib_suffix]
-            self.cpp_info.components["curses++"].names["pkg_config"] = "ncurses++" + self._lib_suffix
-            self.cpp_info.components["curses++"].requires = ["libcurses"]
+            _add_component("curses++", lib_name="ncurses++", requires=["libcurses"])
+            if self.settings.os in ["Linux", "FreeBSD"]:
+                self.cpp_info.components["libcurses++"].system_libs.append("util")
+            libcxx = stdcpp_library(self)
+            if libcxx:
+                self.cpp_info.components["libcurses++"].system_libs.append(libcxx)
+
+        if is_msvc(self):
+            self.cpp_info.components["libcurses"].requires += [
+                "getopt-for-visual-studio::getopt-for-visual-studio",
+                "dirent::dirent",
+            ]
+            if self.options.get_safe("with_extended_colors"):
+                self.cpp_info.components["libcurses"].requires += [
+                    "naive-tsearch::naive-tsearch"
+                ]
+        if self.options.with_pcre2:
+            self.cpp_info.components["form"].requires.append("pcre2::pcre2")
 
-        if self._with_ticlib:
-            self.cpp_info.components["ticlib"].libs = ["tic" + self._lib_suffix]
-            self.cpp_info.components["ticlib"].names["pkg_config"] = "tic" + self._lib_suffix
-            self.cpp_info.components["ticlib"].requires = ["libcurses"]
+        if not self.options.shared:
+            self.cpp_info.components["libcurses"].defines = ["NCURSES_STATIC"]
+            if self.settings.os in ["Linux", "FreeBSD"]:
+                self.cpp_info.components["libcurses"].system_libs = ["dl", "m"]
 
-        if self.options.with_progs:
-            bin_path = os.path.join(self.package_folder, "bin")
-            self.output.info("Appending PATH environment variable: {}".format(bin_path))
-            self.env_info.PATH.append(bin_path)
+        module_rel_path = os.path.join(self._module_subfolder, self._module_file)
+        self.cpp_info.components["libcurses"].builddirs.append(self._module_subfolder)
+        self.cpp_info.set_property("cmake_build_modules", [module_rel_path])
 
         terminfo = os.path.join(self.package_folder, "res", "terminfo")
-        self.output.info("Setting TERMINFO environment variable: {}".format(terminfo))
-        self.env_info.TERMINFO = terminfo
+        self.buildenv_info.define_path("TERMINFO", terminfo)
+        self.runenv_info.define_path("TERMINFO", terminfo)
+        self.conf_info.define("user.ncurses:lib_suffix", self._lib_suffix)
 
+        # TODO: Legacy, to be removed on Conan 2.0
+        self.cpp_info.names["cmake_find_package"] = "Curses"
+        self.cpp_info.names["cmake_find_package_multi"] = "Curses"
+        self.cpp_info.components["libcurses"].build_modules["cmake_find_package"] = [module_rel_path]
+        self.cpp_info.components["libcurses"].build_modules["cmake_find_package_multi"] = [module_rel_path]
+        self.env_info.TERMINFO = terminfo
         self.user_info.lib_suffix = self._lib_suffix


Test patch:
diff --git a/recipes/ncurses/all/test_package/CMakeLists.txt b/recipes/ncurses/all/test_package/CMakeLists.txt
--- a/recipes/ncurses/all/test_package/CMakeLists.txt
+++ b/recipes/ncurses/all/test_package/CMakeLists.txt
@@ -1,11 +1,8 @@
-cmake_minimum_required(VERSION 3.0)
-project(test_package)
-
-include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
-conan_basic_setup(TARGETS)
+cmake_minimum_required(VERSION 3.15)
+project(test_package LANGUAGES C)
 
 set(CURSES_NEED_NCURSES TRUE)
-find_package(Curses REQUIRED)
+find_package(Curses CONFIG REQUIRED)
 
 if(NOT CURSES_HAVE_NCURSES_NCURSES_H)
     message(FATAL_ERROR "ncurses/ncurses.h is not available (CURSES_HAVE_NCURSES_NCURSES_H)")
diff --git a/recipes/ncurses/all/test_package/conanfile.py b/recipes/ncurses/all/test_package/conanfile.py
--- a/recipes/ncurses/all/test_package/conanfile.py
+++ b/recipes/ncurses/all/test_package/conanfile.py
@@ -1,10 +1,26 @@
-from conans import ConanFile, CMake, tools
 import os
 
+from conan import ConanFile
+from conan.tools.build import can_run
+from conan.tools.cmake import cmake_layout, CMake
+from conan.tools.env import Environment
+
 
 class TestPackageConan(ConanFile):
-    settings = "os", "compiler", "build_type", "arch"
-    generators = "cmake", "cmake_find_package"
+    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 generate(self):
+        env = Environment()
+        env.define("TERM", "dumb")
+        env.vars(self, scope="run").save_script("conanrun_term")
 
     def build(self):
         cmake = CMake(self)
@@ -12,6 +28,6 @@ def build(self):
         cmake.build()
 
     def test(self):
-        if not tools.cross_building(self):
-            with tools.environment_append({"TERM": "dumb"}):
-                self.run(os.path.join("bin", "test_package"), run_environment=True)
+        if can_run(self):
+            bin_path = os.path.join(self.cpp.build.bindir, "test_package")
+            self.run(bin_path, env="conanrun")