Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] "cpp_info.system_libs" and static linking of some system libs #17593

Open
1 task
amachado-pie opened this issue Jan 17, 2025 · 1 comment
Open
1 task
Assignees

Comments

@amachado-pie
Copy link

amachado-pie commented Jan 17, 2025

What is your question?

Whe are porting some custom makefiles with Conan v1 to Cmake + Conan 2.

Some recipes, such as libpng, use this approach:

def package_info(self):
    if self.settings.os in ["Linux", "Android", "FreeBSD", "SunOS", "AIX"]:
        self.cpp_info.system_libs.append("m")

This raises an issue when you want to mix static linking of just some system libraries, such as the case of libm using -Wl,-Bstatic -lstdc++ -lm -Wl,-Bdynamic

The issue is that system libraries of the conan recipes that added it as a dependency are repeated in the linking command:

[100%] Linking CXX executable
/usr/local/bin/cmake -E cmake_link_script CMakeFiles/project.dir/link.txt --verbose=1
/usr/bin/g++  -m32
...
-lpthread
-static-libstdc++
-static-libgcc
-Bstatic -lstdc++ -lm -Wl,-Bdynamic
/root/.conan2/p/b/freetafaa4833c1df1/p/lib/libfreetype.a
/root/.conan2/p/b/libpnb01f5f21fd40f/p/lib/libpng.a
...
/root/.conan2/p/b/opens5b1ba6b148939/p/lib/libcrypto.a
-lrt
/root/.conan2/p/b/xmlsead5ac171be143/p/lib/libxmlsec1.a
/root/.conan2/p/b/libxmab7a8911f883b/p/lib/libxml2.a
...
/root/.conan2/p/b/zlib8d00874752b7e/p/lib/libz.a
/root/.conan2/p/b/libic52d0797df088e/p/lib/libiconv.a
/root/.conan2/p/b/libic52d0797df088e/p/lib/libcharset.a
-ldl
-lpthread
-lm            <---
/root/.conan2/p/b/libjp57a4193473e2a/p/lib/libjpeg.a

So the executable is linked dynamically to libm:

ldd build/Release/project 
        linux-gate.so.1 (0xed5bd000)
        libdl.so.2 => /lib32/libdl.so.2 (0xec1dc000)
        librt.so.1 => /lib32/librt.so.1 (0xec1d3000)
        libpthread.so.0 => /lib32/libpthread.so.0 (0xec1b6000)
        libm.so.6 => /lib32/libm.so.6 (0xec161000)  <---
        libc.so.6 => /lib32/libc.so.6 (0xebfa9000)
        /lib/ld-linux.so.2 (0xed5bf000)

We need to still statically link some system libraries like libm because we need to support old distros that have outdated libs.

I tried to hack the dependencies in CMake to remove -lm like this but without success:

function(remove_transitive_dependencies target)
  if(TARGET ${target})
    message(STATUS "Target: ${target}")
    get_target_property(libs ${target} INTERFACE_LINK_LIBRARIES)
    if(libs)
      foreach(lib ${libs})
      message(STATUS "  lib ${lib}")
        if(lib STREQUAL "-lm")
          message(STATUS "    Removing transitive dependency '-lm' from target '${target}'")
          list(REMOVE_ITEM libs ${lib})
        endif()
      endforeach()
      set_target_properties(${target} PROPERTIES INTERFACE_LINK_LIBRARIES "${libs}")
    endif()
  endif()
endfunction()

# Remove transitive dependencies from common libraries
foreach(lib ${project_libraries})
  remove_transitive_dependencies(${lib})
endforeach()

Any idea about how can we deal with this issue?
Thanks

Have you read the CONTRIBUTING guide?

  • I've read the CONTRIBUTING guide
@memsharded memsharded self-assigned this Jan 19, 2025
@memsharded
Copy link
Member

Hi @amachado-pie

Thanks for your question

Whe are porting some custom makefiles with Conan v1 to Cmake + Conan 2.

From what I understand reading the issue, this is not something new due to the migration. I think that system_libs treatment as always been very similar, and it was not possible to differentiate between static/dynamic in Conan 1 either.

This raises an issue when you want to mix static linking of just some system libraries, such as the case of libm using -Wl,-Bstatic -lstdc++ -lm -Wl,-Bdynamic

Quick question, you are using recipes and packages from ConanCenter, or are you using your own recipes? Or maybe at least building the binaries from a conan-center-index Github source repo fork? I am asking in case you could change the recipes to customize it.

Regarding your attempt to remove the libraries from the consumer side CMake code, a couple of quick questions:

  • foreach(lib ${project_libraries}) how do you get project_libraries? The targets that actually get the flags are inner targets, the package::package targets are typically just interface targets that link other internal targets that define the properties, flags, etc. So it would be needed to iterate deeper in the targets graph.
  • Are you sure that if(lib STREQUAL "-lm") works? I think the property is a list of libraries, not a list of flags. It would be very useful to print the values to check.

I'd try to add more logs to the cmake code, printing the targets, the target properties, whether the if() matches or not, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants