add linker/archive options before and after a target

I have a library which symbols should be imported to an app despite the fact they aren’t used explicitly there. The purpose of the library is to execute static constructors and thus make itself available to an app at runtime (register its symbols).

I’ve found the corresponding flags (gcc): -Wl,--no-as-needed for shared library and --whole-archive for static. I can set a variable LINK_WHAT_YOU_USE to control --no-as-needed flag and STATIC_LIBRARY_OPTIONS but they will be applied to all libraries listed next after. What I need is to apply them only for one specific library, i.e. -Wl,--no-as-needed -lmylib -Wl,--as-needed and -Wl,--whole-archive -lmylib -Wl,--no-whole-archive.

Is it possible to do with cmake in a cross-platform way? If yes, then how?

This is, generally, a very hard problem. For example, Mach-O (used on macOS) doesn’t guarantee statics are initialized until something in the TU containing the static is used. So even if the symbols are brought in, the TU needs to be used for the code to actually work (in general). I don’t remember exactly, but that behavior might be for static builds only.

If you’d like to see how VTK manages this in a cross-platform way, “autoinit” is the term to search for in its codebase. Of particular interest are the vtkAutoInit.h header, vtkObjectFactory files (which are the code bits being initialized), and the vtk_module_autoinit function which generates the code to ensure that everything is registered as needed. It’s not trivial.

In any case, I don’t think CMake has a way to manage these “scoping” flags easily right now.

Cc: @brad.king @craig.scott

See CMake Issue 20078 , and in particular the discussion starting here.

For this particular use case, perhaps a different approach may achieve your goal. I would have expected that marking symbols to be exported/visible should be enough to prevent them from being removed by the linker (you should be able to do this even for a static library, its just that it won’t matter until that static library is linked into another shared library). If you don’t want to make the static constructors publicly visible, then you could potentially make some other symbol(s) publicly visible and have those somehow rely on the static constructor (take an address or some other thing that doesn’t actually call it but still refers to it). Not sure if the Mach-O situation for static initializers that Ben mentioned will still prevent this from working for you, but it’s worth a look.

CMake has good support for visibility control. Check out the <LANG>_VISIBILITY_PRESET and VISIBILITY_INLINES_HIDDEN target properties. There’s also a section on it near the start of my CppCon 2019 talk if you are not already familiar with these features.