Uploaded image for project: 'Qbs ("Cubes")'
  1. Qbs ("Cubes")
  2. QBS-1276

Improve documentation about linking static/dynamic libraries with GCC

    XMLWordPrintable

Details

    • Suggestion
    • Resolution: Unresolved
    • Not Evaluated
    • None
    • None
    • Documentation
    • None

    Description

      I spent lot of time figuring out how to properly use linker flags.

      Basically the problem is that gcc liinker flags are positional, but qbs is not, and so it is doing some non trivial choices the user should be aware of.

      Let me share my experience of a real life cross platform (lin/win) project having several components linked in static libraries and finally assembled into a binary.

      Since static archive are mainly used as compilation units in a big project they have some inter dependency and cannot be modeled as a DAG like required by qbs dependency system.

      Before trying using qbs I was using qmake passing hand crafted linker flags and using --start-group and --end-group flags to link interdependent libraries.

      This is simply impossible with qbs since linker flags are passed before any input file.

      So, by looking at gcc.js file, I figured out that the right way to manage the linker  command line order was using qbs dependency tracking.

      Indeed, whenever a library dependency is injected by using a Depend item all cpp.staticLibraries and cpp.dynamicLibraries of the dependent artifcat are recursively add as well and in the proper order (I could not find this info in documentation)

      So, let's suppose A and B are mutually dependent static libraries and C requires A and B. The trick is the following:

      StaticLibrary {
        name: "a"
        Depends { name: "b" } // => the qbs engine will properly place libb after liba
        ...
        Group { // must install this library to be able to link it with library b
          fileTagsFilter: [ "staticlibrary" ]
          qbs.install: true
        }
      }
      
      StaticLibrary {
        name: "b"
        //  Depends { name: "a" } => cannot use this dependency since qbs dependency model is a DAG 
        cpp.dynamicLibraries: [ qbs.installRoot + "/liba.a" ] // => qbs will place liba after libb
      }
      
      CppApplication {
        Depends { name: "a" }
        Depends { name: "b" }
        // the final command line will be liba.a libb.a liba.a which is what is required to properly resolve undefined symbols of libb.a provided by liba.a and not required by main application
      }

      To sum up I would appreciate having more information about how to properly link interdependent static libraries and more generally about how the linker command line is populated by the tool.

       

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              Unassigned Unassigned
              arrigo arrigo zanette
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There are no open Gerrit changes