Search code examples
cmakeg++cpackdebian-packaging

dpkg versioning problem with libstdc++ 10 and 11


I have a Debian package built in Ubuntu 21.10 which fails to install because of a dependcy on libstdc++6 (>= 11). Raspberry Pi OS uses GCC 10.3; so it only has libstdc++6 (10.3.x).

I switched the Ubuntu build to use the GCC 10.3 toolchain instead of GCC 11.2. I've verified that the package is being built with G++-10, not G++ or G++-11.

This worked for another package I'm building on the Ubuntu system. It produced a .deb file that has libstdc++6 (>= 9)! But the current one, with a longer list of dependencies still shows libstdc++6 (>= 11) even after building with GCC-10.3.

As far as I can tell, all other dependency versions are all comfortably met on the Raspberry pi system; but the failing .deb file does have a longer list of dependencies. I may be wrong about that. Is there a way to check whether one of my dependencies has dragged in libstdc++6 (11.x)?

I'm using a CMAKE/CPACK build, which examines the built binaries to determine dependencies automatically.

Is there a way to tell CPack to ask for libstdc++6(>= 10) instead of >= 11? I think it should be ok, if version numbers mean anything at all. Binaries built with G++10 *should be able to link against either that 10.x or the 11.x version of libstdc++, I think.


Solution

  • Found it! :-(

    The problem was caused by a stale versioned .so file. Apparently CPack looks at the binaries in the final installed location, not at the binaries in the build tree, in order to determine dependencies (because that's what dpkg-shlibdebs does in order to correctly address scenarios too horrible to contemplate). And when it did, it picked up an orphaned .so file from previous installs!

    The files in question.

     ToobAmp.so -> ToobAmp.so.0        #fresh install
     ToobAmp.so.0 -> TobbAmp.so.0.1.3  #fresh install
     ToobAmp.so.0.1.3                  #fresh install
     ToobAmp.so.0.0.2          # left over from an old install.
    

    ToobAmp.so.0.0.2 still had linkage to libstdc++6 (>11) because it had been built with G++-11. The freshly installed files had correct references to libstdc++6 (>9).

    CPack apparently decided that it had to include (>11) even though ToobAmp.so.0.0.2 wasn't part of the package.

    Pfft. Left in hopes that it may save somebody else many hours of grim gnashing of teeth, sackcloth and ashes.

    TLDR....

    In case you were wondering (and you probably weren't), dpkg-shlibdeps goes through each linkage into libstdc++6.so, and compares it against the public entry points of each known version of libstdc++6.so, picking the lowest version of the library that will satisfy all linkage requests. And one has to assume that the c++ standard headers use different entry points into libstdc++6 for the same std c++ method/object depending on whether you're using g++-10 or g++-11.

    Why does ToobAmp.so.0.0.2 get processed? Hard to say. dpkg-shlibdeps doesn't do it; CPack does. But at this point about seven things have gone wrong (the orphaned file that shouldn't be there, CPack analyzing a file that it shouldn't install, .so files with backward version relationships,a byzantine DPKG solution addressing a long history of spectacular versioning problems in the standard libraries, linux distributions that won't let you upgrade compilers or standard libraries, &c &c ... ).

    Horror.


    Details posted in response to comments.

    The most probable offender is marked with a comment. The command is required so that I can install with cmake. Perhaps Cpack executes the command as well while building the package.

    CMakeList.txt

    .... build several projects...
    ... install()-ing of various files and directories...
    
    
    
    # QUITE POSSIBLY THE DIRECTIVE THAT CAUSES PROBLEMS
    # The same command that is invoked in a postinst action.
    # cmake install, and  dpkg install both have to install services.
    
    install(
        CODE "execute_process(COMMAND ${CMAKE_INSTALL_PREFIX}/bin/pipedalconfig --install)"
    )
    
    
    set(CPACK_GENERATOR "DEB")
    set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Robin Davies<[email protected]>") # required
    set(CPACK_PACKAGE_VENDOR "Robin Davies")
    set(CPACK_PACKAGE_DESCRIPTION "IoT guitar effects pedal for Raspberry Pi, with phone-friendly web interface.")
    set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "IoT guitar effect for Raspberry Pi")
    set(CPACK_DEBIAN_PACKAGE_SECTION sound)
    set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
    set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
    set(CPACK_DEBIAN_PACKAGE_DEPENDS "jackd2, hostapd, dnsmasq" )
    #set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
    set(CPACK_PACKAGING_INSTALL_PREFIX /usr)
    set(CPACK_PROJECT_NAME ${PROJECT_NAME})
    set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
    set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
    set (CPACK_STRIP_FILES ON)
    
    
    set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/debian/postinst;${CMAKE_CURRENT_SOURCE_DIR}/debian/prerm")
    
    
    include(CPack)