linker

How to export symbols from static library in Mac linker?


By default, symbols in a static library will not exported even if they are markded as dllexport or default visibility. In MSVC, the exported can be forced by /INCLUDE:symbol link directive. And in GNU linker, the whole library can be exported by -Wl,--whole-archive. However Apple's ld don't recognize the --whole-archive argument. So how can I do that in Apple?


Solution

  • The Apple linker's nearest equivalent of --whole-archive is -force_load archive. It is slightly different from --whole-archive in that it applies only to the static library archive, whereas --whole-archive applies to all static libraries subsequently input to the linkage until and unless it is disabled by the --no-whole-archive option.

    A related Apple linker option is -all_load, which implies -force_load for all static libraries in the linkage.


    But there are some misconceptions there that could lead to this answer not producing the desired exports in various circumstances.

    By default, symbols in a static library will not exported even if they are marked as dllexport or default visibility.

    In received usage, exporting a reference or definition of a symbol foo from a program/DSO/DLL/dylib means that the reference or definition is made visible to the dynamic linker, as distinct from a merely global reference or definition that is visible to the static linker but not the dynamic linker.

    A reference or definition of foo that occurs in a static library occurs in some object file that is a member of the static library, because a static library is nothing but an archive of object files from which the static linker can extract and link into the output image those object files that define symbols that have been referenced but not defined in the linkage thus far.

    That means, by default, the static linker will not extract and link object files from a static library that are superfluous, i.e. do not contribute any needed definitions to the linkage. This default behaviour can be overridden by the linker options --whole-archive (GNU Linker), /WHOLEARCHIVE (Windows MSVC linker) or -force_load (macOS/Darwin linker), coercing the static linker to extract and link all members of a static library to which the option applies whether it needs them or not.

    These options coerce the static linker to link certain object files that otherwise it would not, but they do not coerce it to make any symbol definitions or references that it does link visible to the dynamic linker if otherwise it would not. Linking a global reference or definition of foo into a program/DSO/DLL/dylib is a necessary condition of making it visible to the dynamic linker - the dynamic linker cannot be made to see what is not there - but it is not sufficient.

    In short, applying a linkage option (--whole-archive|/WHOLEARCHIVE|-force_load)
    to a static library will result in all of its member object files being linked into the image but will not result in any additional symbol references or definitions being dynamically visible except as allowed by the default or specified compile/link options and declaration attributes that control dynamic visibility.


    The MSVC linker option /INCLUDE:foo does not force foo to be exported. If directs the static linker to insert an undefined reference to foo into the initial global symbol table of the output image, with just the same effect as if the linkage included an undefined reference to foo from an input object file in the usual way. The linkage will fail with an undefined reference error unless a definition of foo is provided by some input file and if a definition is so provided then it will not be dynamically visible unless foo is additionally exported from the linked image in one of the ways already noted.

    The MSVC linker option /INCLUDE:foo is equivalent to the GNU linker option --undefined=foo.

    The MSVC linker option that forces a symbol to be made dynamically visible is the aforementioned /EXPORT:symbol. It requires that a definition of the symbol is linked into the image but cannot make that happen. The equivalent GNU linker option is --export-dynamic-symbol=symbol-glob, where symbol-glob is a symbol name or a glob pattern for matching symbol names. The equivalent Apple linker option is -exported_symbol=symbol