0

I'm trying to build a service/daemon that facilitates 'applets' being run within its process envelope. The service exposes functionality through a library that these applets invoke. Most importantly, the requirement here is the need for these applets to all run within the same process boundary as the service itself. The applet also needs to register itself against the service on boot.

I would like to design the service such that it can be built independently of these applets, as well as to not have any code in it that specifically is aware of these applets.

One option here is to build the applets as shared libraries (.so), have them all be placed on the target filesystem at a particular folder that is searched by the service on boot, loading all .so's in that folder dynamically through dl_open. By tagging an init-function __attribute__((constructor)) in the applet itself, the applet gains the ability to register itself with the service at init time.

Is there a static/link-time version of this? I've dabbled with the suggestion here, but am not able to prevent the compiler from optimizing out the global function registry object that is being exported by each applet. Using -Wl,--whole-archive doesn't work either since it complains of multiple definition of functions provided by the service/daemon library when linking two or more such applet libraries.

cradical
  • 117
  • 7
  • 1
    Can you use `__attribute__((used))` to prevent the object from being optimized out? – Bodo Jan 10 '20 at 15:43
  • https://stackoverflow.com/a/41397268/412080 – Maxim Egorushkin Jan 10 '20 at 17:46
  • I tried ((used)), but it didn't do anything. I believe it's only applicable for functions. – cradical Jan 10 '20 at 21:51
  • The --undefined approach did work, but it doesn't cover the case where you have two different applets that have the same symbol name at the global scope. When you attempt to render that symbol undefined, the first applet that gets linked in by the linker is resolved to to that undefined symbol, leaving the other applet non-functional. – cradical Jan 10 '20 at 21:53
  • @Bodo: attribute `used` is not propagated to linker so it won't help in this case. – yugr Jan 12 '20 at 08:04
  • You can work around multiple definitions by marking registry object with `__attribute__((weak))`. But why not just move it to main app? – yugr Jan 12 '20 at 08:06

1 Answers1

1

Is there a static/link-time version of this?

There is, but such a solution fails to satisfy your requirement that "the service can be built independently of these applets". With static linking the service and all the applets are linked together, and therefore by definition can't be built separately.

That said, the -Wl,--whole-archive is the correct solution to your problem.

doesn't work either since it complains of multiple definition of functions provided by the service/daemon library

Don't put the service/daemon library into each of the applet libraries (it makes no sense to do so). Put it into its own library instead. This should work:

gcc main.o -Wl,--whole-archive -lapplet1 -lapplet2 ... -lservice -Wl,--no-whole-archive
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • You’re absolutely right in that a static version will have to give up on the ideal of building them independently. I’m willing to accept the compromise of having a ‘staging’ folder that all applet static libraries will be staged to, that will then be iterated over by a build script to create the final daemon binary with the appropriate “-lapplet” arguments passed in. However, even with the suggested approach, how would I resolve other library dependencies that these applets may have? – cradical Jan 16 '20 at 17:47