2

I want to create a conan wrapper over a project's sources that can be downloaded.
Note that I cannot modify anything in that project; I am just given a URL from where it can be downloaded.

I know how to download and uncompressed the project's sources (using the tools module) by adding some code in the source() method in the conanfile.py.

That project (once downloaded and uncompressed) can be built with cmake and can use Boost.
So I added boost/1.75 in build_requires (I chose the version arbitrarily).
In the cmake's configuration phase of that project, it is possible to pass the Boost's location folder as an argument to cmake (e.g. -DWITH_BOOST=path_name).

But from within the build() method, I don't how to get the folder where Boost 1.75 is installed in the conan cache. Knowing that, I would then pass it to the cmake.configure(...) call.

Is there a way to get the package folder of a dependency from within conanfile.py? Perhaps by using something like self.build_requires['boost/1.75'].package_folder?

3
  • You don't need to pass source folder. As you are using CMake, Conan can generate cmake, cmake_paths, cmake_find_package which find all headers for you. Commented Jan 15, 2021 at 11:14
  • According to you, conan will automatically add -DWITH_BOOST=boost_dependency_path magically to the cmake configuration of a sourced project it does know anything about? Commented Jan 17, 2021 at 4:31
  • It will add, if the recipe is prepared to do it, and if you use a helper which passes all cmake defines, including that you mentioned. The cmake wrappers are those that I commented before. If you want to see the cmake command executed by Conan, you can set the env var CONAN_PRINT_RUN_COMMANDS. Commented Jan 18, 2021 at 11:05

1 Answer 1

2

The easiest way to get dependency path is:

from conans import ConanFile # for type hinting

# conan create
boost: ConanFile = self.dependencies.build["boost"]
boost.package_folder

but it will not work always:

# conan build (hacky)
self.deps_cpp_info["boost"].build_paths[0]
  • it might not be available in all steps (I did not check in detail)

The most reliable way to get this information is actually to read if from conanbuildinfo.txt - this file is created during install step, you can use different generators, like -g json to use it in different formats. You can read this file using conan api:

from conans.client.generators import TXTGenerator
with open("conanbuildinfo.txt", "r") as handle:
    contents = handle.read()
deps_cpp_info, deps_user_info, deps_env_info, user_info_build = TXTGenerator.loads(contents)

And the last way that I found in my code (this can be simplified, but that is what I can provide for now):

import sys

import conans.errorsc
import conans.cli.exit_codes
from conans import ConanFile

from conans.client.cache.cache import ClientCache
from conans.client.conan_api import Conan
from conans.model.ref import PackageReference
from conans.paths.package_layouts.package_editable_layout import PackageEditableLayout

try:
    conan_api, _, _ = Conan.factory()
except conans.errors.ConanMigrationError:
    sys.exit(conans.cli.exit_codes.ERROR_MIGRATION)
except conans.errors.ConanException as error:
    sys.exit(conans.cli.exit_codes.ERROR_GENERAL)


def _discover_package_path(dependency_name: str) -> str:
    """Returns a package folder in local conan cache for specified dependency.
    Function is similar to:
    > conan info conanfile.py --paths --only package_folder
    This implementation is based on _grab_info_data (Conan version 1.55.0-dev):
    >>> from conans.client.conan_command_output import CommandOutputer
    >>> CommandOutputer._grab_info_data
    """
    data, _ = conan_api.info(reference_or_path="conanfile.py")
    node = next(node for node in data.nodes if node.name == dependency_name)
    cache = ClientCache(conan_api.cache_folder, conan_api.out)
    layout = cache.package_layout(node.ref, node.conanfile.short_paths)
    if isinstance(layout, PackageEditableLayout):
        return node.conanfile.package_folder
    else:
        return layout.package(PackageReference(node.ref, node.package_id))


# _discover_package_path("cmake")

class MyDummy(ConanFile):
    name = "MyDummy"
    version = "0.0.1"
    requires = "boost/1.71.0"

    def build(self):
        print(80 * "#")
        print(_discover_package_path("boost"))
        print(80 * "#")

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.