What could be causing linking errors when compiling in an Alpine Docker? What could be causing linking errors when compiling in an Alpine Docker? docker docker

What could be causing linking errors when compiling in an Alpine Docker?


I am still curious why, using the exact same library and instructions, this would fail to compile in an Alpine image while compiling without issue in an Ubuntu image.

The reason for the linking error on Alpine may be kind of surprising, and is actually not specific to Alpine.

While this fails to link:

gcc -largp -o progname progname.o

This works:

gcc -o progname progname.o -largp

The reason is the order of parameters passed to the linker, and it related to the linking algorithm. Typically, in the linking command line objects are specified first (and possibly user's static libraries in any), then libraries using -l. The standard linker algorithm is explained perfectly in Eli Bendersky's article, Library order in static linking:

Object files and libraries are provided in a certain order on the command-line, from left to right. This is the linking order. Here's what the linker does:

  • The linker maintains a symbol table. This symbol table does a bunch of things, but among them is keeping two lists:
    • A list of symbols exported by all the objects and libraries encountered so far.
    • A list of undefined symbols that the encountered objects and libraries requested to import and were not found yet.
  • When the linker encounters a new object file, it looks at:
    • The symbols it exports: these are added to the list of exported symbols mentioned above. If any symbol is in the undefined list, it's removed from there because it has now been found. If any symbol has already been in the exported list, we get a "multiple definition" error: two different objects export the same symbol and the linker is confused.
    • The symbols it imports: these are added to the list of undefined symbols, unless they can be found in the list of exported symbols.
  • When the linker encounters a new library, things are a bit more interesting. The linker goes over all the objects in the library. For each one, it first looks at the symbols it exports.
    • If any of the symbols it exports are on the undefined list, the object is added to the link and the next step is executed. Otherwise, the next step is skipped.
    • If the object has been added to the link, it's treated as described above - its undefined and exported symbols get added to the symbol table.
    • Finally, if any of the objects in the library has been included in the link, the library is rescanned again - it's possible that symbols imported by the included object can be found in other objects within the same library.

When -largp appears first, the linker does not include any of its objects in the linking procedure, since it doesn't have any undefined symbols yet. If the static library is provided by path, and not with -l, then all of its objects are added to the linking procedure.