conan-io / conan-center-index

Recipes for the ConanCenter repository
https://conan.io/center
MIT License
958 stars 1.76k forks source link

[package] gcc recipe doesn't export library metdata #15099

Open samuel-emrys opened 1 year ago

samuel-emrys commented 1 year ago

Description

The current gcc recipe is predominantly targetted at providing executables, however it also provides the following libraries:

and a few others that require some more research to determine whether they're worth modelling. This ticket is to model the libraries distributed with gcc as components so that they can be appropriately linked against when required.

An example of when this is required is for an upcoming lapack recipe, which requires linkage against libgfortran. Without this change, it is not possible to prevent this linkage from happening against the system libraries, if they exist at all, which if they don't, would just fail to link.

Package and Environment Details

NA

Conan profile

NA

Steps to reproduce

NA

Logs

NA

jcar87 commented 1 year ago

hi @samuel-emrys, thanks for raising this issue.

An example of when this is required is for an upcoming lapack recipe, which requires linkage against libgfortran. Without this change, it is not possible to prevent this linkage from happening against the system libraries, if they exist at all, which if they don't, would just fail to link.

Would you be able to provide an example where this does not work as expected? If I'm not mistaken, a consumer using gcc from the recipe, if performing linking via gcc itself, should already be able to link against the libgfortran from the package, rather than a system one, without any additional actions. Is this not the case? If it is not, there may be something else that the recipe needs fixing!

samuel-emrys commented 1 year ago

Hey @jcar87 yes, linking works fine when invoking the compiler, so there are no problems when building. The problem is modelling the library as a dependency from the consumer perspective, or ensuring that the path to the library is exported appropriately/libraries are linked to in the right order when linking static libs. To be explicit about this, without modelling the libraries within the gcc package, one has to add gfortran to the system_libs list. This will append -lgfortran to the link command. There are a few problems with this:

To illustrate this, by modelling the internal libraries explicitly in the conan recipe, consumer recipes are able to specify the specific dependency:

    def package_info(self):
        self.cpp_info.components["blas"].set_property("cmake_target_name", "BLAS::BLAS")
        self.cpp_info.components["blas"].libs = [self.get_lib_name("blas")]
        self.cpp_info.components["blas"].requires = ["gcc::gfortran"]
#     self.cpp_info.components["blas"].system_libs.extend(["gfortran"]) # would otherwise require this

which will ensure that -l/home/user/.conan/data/gcc/_/_/package/<package_id>/lib/libgfortran.{a,so} is appended to the link command when linking against the blas target, i.e.

add_library(mylib ...)
target_link_libraries(mylib BLAS::BLAS) # implies also gcc::gfortran -> /path/to/libgfortran.{a,so}

Edit: for your awareness, this is how I'm currently using it in my WIP lapack recipe: https://github.com/samuel-emrys/conan-center-index/blob/8ae03841dce93cf9676e9c16606ef159cb1d1e25/recipes/lapack/all/conanfile.py#L176-L199

jcar87 commented 1 year ago

Hi @samuel-emrys - apologies for the delay in looking into this. We believe there is currently a shortcoming in our package modeling when it comes to toolchains. Something like a gcc package is meant to be used as a tool_requires (so, it is assumed it runs on the settings provided by the host profile) - the information from the package_info() does not propagate to consumers. Library information this way would be meant for a regular (host context) requirement.

The second issue is that I believe these are system libraries, and don't need to be modelled. There is probably a misconception of what a system library actually is - there are two aspects to this:

I'd say (B) is there more accurate - and when not cross-building and using a compiler that is installed system wide, A is also implied.

When cross building, a system library is one that lives in the "sysroot" of the target system, and not necessarily at the system level of the host machine at all. When not cross building and when using a gcc from a Conan package, that's where we could have problems.

There are two types of libraries inside a gcc toolchain:

To be explicit about this, without modelling the libraries within the gcc package, one has to add gfortran to the system_libs list. This will append -lgfortran to the link command. There are a few problems with this:

It may resolve to the system library depending on what the environment is

I dont see a problem with modelling gfortran as a system_lib, as long as the packaged gcc inside the recipe is configured to look for that library inside it. It is part of the compiler distribution, so a -lgfortran should always be resolved by the compiler to the one that comes with the compiler?

Build systems should also be aware of this, that's why autotools for example for some of these special libraries (e.g. libm and maybe gfortran etc), they check that -lgfortran works, rather than trying to locate the exact file. CMake also treats these differently - e.g. with things like https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.html#variable:CMAKE_%3CLANG%3E_IMPLICIT_LINK_DIRECTORIES -

A proposed FindFortran (https://github.com/scikit-build/cmake-FindFortran/blob/master/FindFortran.cmake) doesnt call find_library, but rather, relies on the paths derived from the compiler. I think that is the key difference in why these shouldn't as regular libraries in package_info.

It may resolve to the system library depending on what the environment is Do we have examples of this? It should not happen if gcc is built correctly. But I'd happily look into this.

This is semantically inaccurate - the intent here is not to link against the system library, but what's been provided by the gcc recipe.

Arguably, it is a system library with the definition from above.

GCC and and GCC-based C++ toolchain has multiple components that are tightly coupled: the compiler collection, binutils, glibc and the linux headers. And typically, those live together under the same prefix. I think the expectation that a standalone gcc recipe can exist, be relocatable, and be able to target the build machine (that is, not cross-compile), may be really difficult to achieve, and I would discourage using the gcc recipe in Conan Center as it is - but would consider uses for cross-building.

Unless there are specific issues that we can reproduce, we are unlikely to consider https://github.com/conan-io/conan-center-index/blob/39f5c236c9c7fb60187dfcdfb0f21f4c4b94460b/recipes/gcc/all/conanfile.py for merging. Will be happy to troubleshoot something we can reproduce and arrive at the correct solution.