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?
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.
On Linux or macOS/Darwin with GCC or Clang toolchain, a global reference
or definition of foo
is dynamically visible by default. But if the translation unit in
which it appears is compiled with -fvisibility=hidden
then is not dynamically
visible, unless the translation unit contains a declaration of foo
with
__attribute__((visibility("default")))
.
On Windows with GCC/Clang toolchain, a global definition of
foo
is dynamically visible by default if all the global symbols
defined in the translation unit similarly default. But if
any of them is declared with __declspec(dllexport)
then foo
remains dynamically
invisible unless it too is declared __declspec(dllexport)
. Any defined symbol with __declspec(dllexport)
in
a translation unit makes others dynamically invisible by default. An
undefined global reference of foo
is never made dynamically visible unless foo
is
declared with __declspec(dllimport)
.
On Windows with MSVC toolchain, an undefined global reference of foo
is
dynamically visible only if foo
is declared __declspec(dllimport)
in the
translation unit. A global definition of foo
is dynamically visible
only if foo
is declared __declspec(dllexport)
in the translation unit,
or is defined in the EXPORTS
of an associated .def
file, or is the argument
of the linkage option /EXPORT:foo
.
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