Why adding unneeded libraries to invocation are linked anyway?

I’ve found that some libraries added to a compiler invocation will increase the final binary size,
while others do not. This is with both bytecode and opt.

for instance:
ocamlopt -o x helloworld.ml -I +compiler-libs ocamlcommon.cmxa

increases the size by 12MB, while ocamlbytecomp.cmxa adds nothing.
my expectation was unused libraries would not be linked unless -linkall used.
does anyone know what’s happening here?

  • using 4.14.2

-linkall can be used both when linking (to make sure that the modules/libraries on the command line are all linked) and when building a module or library (to indicate that any reference to the module must link it, usually because the module has side-effects that must be performed).
compilerlibs.common falls into the second category: a bunch of the typing modules use forward references, meaning that some modules only work correctly if the module later in the dependency graph are linked too. So they are compiled with -linkall, because we don’t have a good way to encode the precise constraints.

@progman next time you get tripped by that you can check this by looking at the Force link: fields in the output of:

ocamlobjinfo -no-code $(opam var lib)/ocaml/compiler-libs/ocamlcommon.cmxa

that’s … unfortunate.

you can check this by looking at the Force link:

I see an increase too for the miniscule xdg library for which Force Link is ‘no’,
though that’s probably just the line “dllxdg_stubs” under Used DLLs , which shouldn’t be there
I would have thought.

I have a follow-up question which is perhaps very dune-centric: if I add -linkall to one dune library, what does this imply:

  1. Does this Force link “bubble up” to any executable that depends on such library?
  2. If not, does it force linking of all the dependencies of this library as well?
  3. Or does it really just affect the modules in that one library?

For a long time I’ve used -linkall on an executable because there are modules (in a few libraries) that require it, but that has really bloated the executable with everything under the sun.
I only realized how bad this really is after using modulectomy on it.

So I’m now wondering how exactly I can optimize my use of -linkall such that everything necessary is forced, but as little extra as possible. I suppose there’s no way to control the Force link flag for an individual module via dune, is there?

-linkall for a library just sets the Force link @dbuenzli refers to above. The force linking itself only affects that library itself, so the answers are 1) no; 2) no; 3) yes!

In terms of finer-grain control, this is more a compiler feature than something Dune per se can do.

The “usual” (or perhaps “expected”) use for -linkall with executables is in conjunction with Dynlink, as it makes all the modules of a library available for use by plugins, even if those modules are not used by the program itself (but, again, the lack of fine-grained control is not wonderful).

1 Like

Note putting aside the “legit” use of -linkall on executables for dynlinking that @dra27 mentioned, IIRC it is almost always (if not always) possible to convert a library that requires -linkall to one that does not (I’m actually curious about those that you mention that need it if you have pointers). But it requires a bit of API twitching.

See this comment.

AFAIR the reason why it was not done for ocamlcommon.cmxa is that it would break compatibility.