Do not include the LLVM backend libraries in libLLVM.so, but instead
build them as modules that can be dlopen'd at runtime. This helps keeps
the memory footprint of libLLVM.so smaller, since in most cases there
is only 1 backend in use at any time.
I chose not to add a CMake option to enable/disable this feature,
because I don't want to add another set of configuration permutations
that we need to support.
Binary size comparison:
Without Backend Modules:
117M libLLVM-12git.so
With Backend Modules:
60M libLLVM-12git.so
14M LLVMAMDGPUBackend.so
12M LLVMX86Backend.so
8.5M LLVMAArch64Backend.so
7.2M LLVMARMBackend.so
6.7M LLVMHexagonBackend.so
3.6M LLVMPowerPCBackend.so
3.6M LLVMMipsBackend.so
2.2M LLVMSystemZBackend.so
2.1M LLVMNVPTXBackend.so
2.0M LLVMRISCVBackend.so
1.8M LLVMWebAssemblyBackend.so
881K LLVMSparcBackend.so
732K LLVMBPFBackend.so
730K LLVMAVRBackend.so
721K LLVMLanaiBackend.so
704K LLVMXCoreBackend.so
579K LLVMMSP430Backend.so
126M Total
I am somewhat surprised this works -- I usually try to avoid this kind of layering issue, because while it can work, it usually has weird edge cases.
In this case, each of your target backends will directly embed (and export!) its dependencies, which, are probably also embedded and exported by the libLLVM that loads it. Aside from bloat, this can cause issues with module statics being duplicated depending on how the child library references things in the module (tends to manifest with cl conflicts in the support library at runtime). Based on the sizes you report, I suspect this is adding ~a megabyte to each of your backends (completely guessing based on what I have seen).
There are two ways to later this better: