Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When linking, is there something between "grab what you need" and "grab all" (-Wl,--whole-archive)?

I have this library which involves some static initialization code which needs to run before main(). It all works well if you just compile all of the translation units together, but it doesn't work if I provide a static library (.a file) and have users link their application against it - the linker simply ignores the symbols which do my static initialization.

Alternatively, I can make the linker pick up everything in the static library, if I specify the -Wl,--whole-archive option to GCC, i.e. specify the --whole-archive option to GNU link.

But is there some middle ground? Can I mark some symbols and make the linker always pick them up for the executable, while the rest of the symbols are added only when needed?

Motivation: I use some static blocks to register classes in a factory; I want to make my code available as a (non-dynamic) library, without the user code having to perform any "magic incantation" for the factory to be populated.

Some related questions:

  • How to force include static objects from a static library in C++ (MSVC 11)
  • How to force gcc to link unreferenced, static C++ objects from a library
  • How to force gcc to link an unused static library
like image 320
einpoklum Avatar asked Oct 30 '22 09:10

einpoklum


1 Answers

You can force the linker to keep a given function (and naturally, all code that is called from this function). Add -u my_function to the link command. Many build systems let static libraries to 'export' the build settings to those who use them. E.g., for Android ndk-build framework, you can specify something like

include $(CLEAR_VARS)
LOCAL_MODULE := the_best_static_library
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfoo.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_LDFLAGS := -u my_function
include $(PREBUILT_STATIC_LIBRARY)

in your module Android.mk. People reuse it by adding to their Android.mk the simple statement

$(call import-module,third_party/the_best_static_library)

N.B. For this approach to work, my_function() cannot be declared static. If some symbol is declared as static at the file scope, then the linker guess not know it by name at all. Luckily, if it is referenced in some code that the linker decides to keep, then it will also not get stripped off. Furthermore, unless you make a special effort, the linker will strip or keep whole compilation units (a.k.a. C files). Thus, it is usually enough to "anchor" a dummy function to keep many functions and data.

like image 103
Alex Cohn Avatar answered Nov 15 '22 07:11

Alex Cohn