conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
8.22k stars 979 forks source link

[feature] stdcpp_library when using static-libstdc++ #15646

Open jcar87 opened 8 months ago

jcar87 commented 8 months ago

What is your suggestion?

Use case:

For cases like this, when linking the application, the linker won't know that the executable needs to load libstdc++.so (unless there were other C++ libraries involved, or the C++ compiler was invoked to do the linker). Thus, some recipes have some logic like this:

        if not self.options.shared:
            libcxx = stdcpp_library(self)
            if libcxx:
                self.cpp_info.components["xxx"].system_libs.append(libcxx)

where libcxx is the stdc++ library. This mirrors what happens outside of the Conan realm, where a .pc file for a library like this will have -lstdc++ as a linking flag.

However, there are cases in which the user on the consuming side might wish to link the final executable with the static C++ runtime (-static-libstdc++). This is valid - so long as the shared variant is not linked as well. For our static library, the binary package is the same: it assumes that the symbols will be satisfied, but it doesn't really mandate that the executable needs to load the C++ runtime as a shared or a static library. It would be a different case if we had a shared library.

In this PR https://github.com/conan-io/conan-center-index/pull/16236 we get an issue where users wishing to link their executables with -static-libstdc++ have issues because the recipe logic is adding -lstdc++ to the linking flags, and that takes precedence.

Given that the stdcpp_library helper is described as:

def stdcpp_library(conanfile):
    """ Returns the name of the C++ standard library that can be passed
    to the linker, based on the current settings. Returs None if the name 
    of the C++ standard library file is not known.
    """

If this function already has that "something that can be passed to the linker" in mind, and all invocations are protected and only apply to static libraries, we may wish to add a conf such that this outputs nothing and let the consumer user handle it. I don't think we can have this output -static-libstdc++ because that's a flag, not a linking library, and there are more possibly more libraries that need to be statically linked in order to get a working executable.

Have you read the CONTRIBUTING guide?

SpaceIm commented 8 months ago

From my point of view, all these things (stdcpp_library & -static-libstdc++) should be abstracted away:

If conan could know (with a property or whatever in package_info) whether a component is C++ or pure C, and assuming compiler.libcxx is properly set, it would deduce by itself what to inject (link to libraries, link flags etc), and recipes would be relieved from this micro management.

jcar87 commented 8 months ago

Android with c++_static and c++_shared might be a different case as those are already modelled (with those names) in the Android NDK and all relevant tooling. In the case of Windows, the /MT flag does not only indicate a linking flag, but there's also different defines in the compiler and symbols from the runtime are embedded in the output .obj file.

On GNU Linux on the other hand, for a static library (a .a) file the -static-libstdc++ flag has no effect for the compiler, and since the linker is not invoked, the contents of that library are going to be the exactly the same regardless of whether the end application links against libstdc++ statically or not. So introducing a setting with a different value would cause a different package ID that would be unnecessary. Unsure about what happens if one tries to produce a shared object with that flag - but I doubt a shared library that embeds the static C++ runtime is useful unless it's the only such library in the program.

On Ubuntu I've seen "C++ libraries with a pure C interface" that do list -lstdc++ in the Libs property in the generated .pc files - equivalent to what is done in Conan center.

So I'm not sure it's worth it to create a whole new setting on GNU linux, for something that doesn't fit in the package ID model, but rather is only relevant to the final application being linked. This issue is not about changing the implementation in the recipes, is about enabling the rather rare case of preventing the recipes from injecting any linking flags related to the C++ runtime